Sega Genesis Programming Part 15: Inventory


 

Goals

This little article has significantly fewer pictures than the previous one, sorry if that disappoints/bores you. There are almost 500 lines of code in here if that does anything for you.

Today we'll be adding inventory management to the demo, this includes:

1) Adding & removing items from the player's inventory

2) Displaying a give/take dialog where the player can choose items

3) Responding to a selection from the previous step

Alright, let's get going...

Inventory management

First off is defining the maximum number of items the player can carry. This is small for two reasons: laziness. Well, mostly laziness. I was going to add an excuse that it makes the game more realistic if the player can't carry 99 potions but I assume most of you would see through that.

MAX_ITEMS=$04 ; maximum number of items the player can carry

Next is reserving some places in memory to store the item list:

;-----------------

; player inventory

;-----------------

MEM_PLAYER_ITEM_COUNT=$FFFF002C ; how many items the player is holding

MEM_PLAYER_ITEMS=$FFFF002E ; item list

Now we need the basic add & remove subroutines. Add is first for hopefully obvious reasons:

;---------------------------------------

; adds an item to the player's inventory

; d7 = item to add

; d6 is modified by this subroutine

; a1 is modified by this subroutine

;---------------------------------------

AddItem:

 move.w (MEM_PLAYER_ITEM_COUNT),d6 ; copy current item count to d6

 cmpi.w #MAX_ITEMS,d6 ; check if inventory is full

 bge.s ExitAddItem ; branch if already at the limit

 addq #$1,(MEM_PLAYER_ITEM_COUNT) ; increment item count

 mulu.w #WORD_SIZE,d6 ; find index of location to write the item

 lea MEM_PLAYER_ITEMS,a1 ; point to start of item list

 move.w d7,(a1,d6) ; copy the item 

ExitAddItem:

 rts

Before we can remove an item we need a subroutine to determine if the player is carrying it in the first place. "Remove by index" is an easy enough subroutine to add but not as useful. There are a dozen scenarios where removing an item by item ID makes sense. Anyway, this subroutine checks if the player has an item and if so returns the index. -1 (FFFF) is returned if the item is not found.

;---------------------------------------------------

; tests if the player has an item

; d7 = item to look for

; d6 will have index of item if found, otherwise FFFF

; d5 is modified by this subroutine

; a1 is modified by this subroutine

;-----------------------------------------------------

HasItem:

 move.w (MEM_PLAYER_ITEM_COUNT),d6 ; copy item count to d6

 tst.w d6 ; test if item count is zero

 beq.s HasItemNotFound ; item count is zero, return FFFF and exit

 subq #$1,d6 ; decrement for zero-based list

 move.w d6,d5 ; copy item count to d5

 mulu.w #WORD_SIZE,d5 ; multiply to get the index of the last item

 lea MEM_PLAYER_ITEMS,a1 ; point to start of item list

 adda.l d5,a1 ; move a1 to last item in the list

HasItemLoop:

 cmp.w (a1),d7 ; test if this is the item we're looking for

 beq.s ExitHasItem ; branch if it is

 suba.l #WORD_SIZE,a1 ; move to next item

 dbra d6,HasItemLoop ; loop to the end of the list

HasItemNotFound:

 move.w #$FFFF,d6 ; set FFFF as the return value

ExitHasItem:

 rts

Last is the subroutine to remove an item, which calls the previous subroutine:

;--------------------------------------------

; removes an item from the player's inventory

; d7 = item to remove

; d5 and d6 are modified by this subroutine

; a1 is modified by this subroutine

;--------------------------------------------

RemoveItem:

 bsr.w HasItem ; test if the item is in the inventory

 cmpi.w #$FFFF,d6 ; test if the item was found

 beq.s ExitRemoveItem ; exit if it was not

 subq #$1,(MEM_PLAYER_ITEM_COUNT) ; decrement item count

 move.w d6,d5 ; copy item index to d5

 mulu.w #WORD_SIZE,d5 ; multiply to get the index of the removed item

 lea MEM_PLAYER_ITEMS,a1 ; point to start of item list

 adda.l d5,a1 ; move a1 to the removed item

 move.w #$0000,(a1) ; clear removed item

 move.w (MEM_PLAYER_ITEM_COUNT),d5 ; copy item count to d5

 sub.w d6,d5 ; subtract item index from count to get loop control

 beq.s ExitRemoveItem ; exit if the only item in inventory was removed

RemoveItemLoop:

 move.w (WORD_SIZE,a1),(a1) ; copy item +1 to current item

 adda.l #WORD_SIZE,a1 ; move to next item

 move.w #$0000,(a1) ; clear item slot 

 dbra d5,RemoveItemLoop ; loop to next item

ExitRemoveItem:

 rts

With the basic plumbing out of the way we can move on to the slightly more difficult part...

Item dialog

In previous articles we built dialogs with two and three selections. We now need a dialog that displays four selections. This magical number is based on the number of items in the player's inventory. Although it could page to fit more if needed. It will also be used when the player selects "Take" from the A button menu to present them with a list of items to choose. Also, I think it will be helpful at some point to have a dialog that gives the player four choices. Like in a battle it could show options like: Fight, Item, Defend, or Wet Pants.

Step one is adding some new dialog flags and renaming a couple others:

DIALOG_FLAG_STYLE_ITEM_MENU=$15 ; item menu dialog

DIALOG_FLAG_STYLE_MENU=$16 ; overworld menu style dialog

DIALOG_FLAG_STYLE_TEXT_4CHOICE=$17 ; dialog has text with selection at the end

DIALOG_FLAG_STYLE_TEXT_2CHOICE=$18 ; dialog has text with selection at the end

DIALOG_FLAG_STYLE_TEXT_4CHOICE is used mostly when the selector sprite is moved. DIALOG_FLAG_STYLE_ITEM_MENU tells the ProcessDialog subroutine to draw a list of items. It also changes the values set when the dialog is closed.

For ProcessDialog to handle items we need three new variables. We need a pointer to a list of items, a counter of where we are in drawing that list, and also a place to store the item selected.

MEM_ACTIVE_ITEM=$FFFF001A ; item that is currently being used

[...]

MEM_DIALOG_ITEM_LIST=$FFFF0046 ; pointer to location of item list to display

MEM_DIALOG_ITEM_INDEX=$FFFF004A ; track which item in the list is being drawn

The nice thing about MEM_DIALOG_ITEM_LIST is that it can either point to an address in the ROM or in memory so it can be used to display static items or what the player is currently carrying.

Now we need some items. Since the player starts off close to the magazine rack, and I'm incredibly lazy, the first items will be magazines. This requires creating some item IDs, names for the items, and a lookup table for the names:

;-----------------------------------

; items

;-----------------------------------

OBJ_ITEM_BASE=$3000

OBJ_ITEM_NOTHING=OBJ_ITEM_BASE

OBJ_ITEM_MAG_GAMEPRO=OBJ_ITEM_BASE+1

OBJ_ITEM_MAG_EGM=OBJ_ITEM_BASE+2

OBJ_ITEM_MAG_ANTIC=OBJ_ITEM_BASE+3

OBJ_ITEM_MAG_ANALOG=OBJ_ITEM_BASE+4

[...]

ItemNameNothing:

 dc.b "Nothing",ITEMNAMEEND

ItemNameMagGamePro:

 dc.b "GamePro",ITEMNAMEEND

ItemNameMagEGM:

 dc.b "EGM",ITEMNAMEEND

ItemNameMagAntic:

 dc.b "Antic",ITEMNAMEEND

ItemNameMagAnalog:

 dc.b "Analog",ITEMNAMEEND

[...]

ItemNameTable:

 ;OBJ_ITEM_NOTHING

 dc.l ItemNameNothing

 ;OBJ_ITEM_MAG_GAMEPRO

 dc.l ItemNameMagGamePro

 ;OBJ_ITEM_MAG_EGM

 dc.l ItemNameMagEGM

 ;OBJ_ITEM_MAG_ANTIC

 dc.l ItemNameMagAntic

 ;OBJ_ITEM_MAG_ANALOG

 dc.l ItemNameMagAnalog

We also need a list that will be referenced in ProcessDialog. I guess I should figure out how to store this in the scene definition or something. For now it's hard-coded in some random spot:

ItemListVBMagazine:

 dc.w OBJ_ITEM_MAG_GAMEPRO

 dc.w OBJ_ITEM_MAG_EGM

 dc.w OBJ_ITEM_MAG_ANTIC

 dc.w OBJ_ITEM_MAG_ANALOG

Here's some new text that will come up later. ITEMNAMESTART is a new constant that will be used to tell ProcessDialog to draw the next item in the list.

ItemMenu:

 dc.b "{",ITEMNAMESTART

;-------------------------

; take menus and messages

;-------------------------

TakeMenuFull:

 dc.b "You can't carry any",LF

 dc.b "more items.",ETX

TakeMenuMagazines:

 dc.b "Which magazine do you",LF

 dc.b "want to take? ^",FF

 dc.b "{",ITEMNAMESTART

TakeMagazinesOption0:

 dc.b "You selected option 0.",ETX

TakeMagazinesOption1:

 dc.b "You selected option 1.",ETX

TakeMagazinesOption2:

 dc.b "You selected option 2.",ETX

TakeMagazinesOption3:

 dc.b "You selected option 3.",ETX

ProcessDialog is doing the most complicated work, and it's not terribly complicated at all. When it encouters the ITEMNAMESTART character it looks up the name of the next item and sets it as the next text to draw. When it encounters the ITEMNAMEEND character it determines whether there are more items to draw. If so it resets the text back to ItemMenu, otherwise it moves to the next dialog state.

ProcessDialogTextDrawing:

[...]

TestItemNameStart:

 cmpi.b #ITEMNAMESTART,d6 ; start of an item name?

 bne.s TestItemNameEnd ; not the ITEMNAMESTART character, next test

 ;------------------------------------------

 ; build text for next item name in the list

 ;------------------------------------------

 ; lookup the object ID for the next item 

 move.l (MEM_DIALOG_ITEM_LIST),a6 ; copy address of item list to a6

 move.w (MEM_DIALOG_ITEM_INDEX),d6 ; copy current item index to d6

 mulu.w #WORD_SIZE,d6 ; multiply by WORD_SIZE to get the offset

 adda.l d6,a6 ; add offset

 move.w (a6),d6 ; copy item ID to d6

 andi.w #$0FFF,d6 ; clear the base value

 ; object ID is in d6 now, find the address for the text

 mulu.w #LWORD_SIZE,d6 ; multiply by LWORD_SIZE to get the offset

 lea ItemNameTable,a6 ; point a6 to item name table

 adda.l d6,a6 ; add offset

 move.l (a6),(MEM_DIALOG_TEXT) ; copy value at a6 to MEM_DIALOG_TEXT

 bra.w ExitProcessDialog ; exit

TestItemNameEnd:

 cmpi.b #ITEMNAMEEND,d6 ; end of an item name?

 bne.s TestLF ; not the ITEMNAMEEND character, next test

 ;---------------------------------------------

 ; determine if there are more items to display

 ;---------------------------------------------

 addq #$1,(MEM_DIALOG_ITEM_INDEX) ; increment item name

 cmpi.w #MAX_ITEMS,(MEM_DIALOG_ITEM_INDEX) ; at max items?

 bge.s ProcessDialogTextEnd ; branch if at max items

 ; test if the next item is OBJ_ITEM_NOTHING

 move.l (MEM_DIALOG_ITEM_LIST),a6 ; copy address of item list to a6

 move.w (MEM_DIALOG_ITEM_INDEX),d6 ; copy current item index to d6

 mulu.w #WORD_SIZE,d6 ; multiply by WORD_SIZE to get the offset

 adda.l d6,a6 ; add offset

 cmpi.w #OBJ_ITEM_NOTHING,(a6) ; test if value at a6 = OBJ_ITEM_NOTHING

 beq.s ProcessDialogTextEnd ; branch if next item is OBJ_ITEM_NOTHING

 cmpi.w #$0000,(a6) ; test if value at a6 = 0000

 beq.s ProcessDialogTextEnd ; branch if next item is OBJ_ITEM_NOTHING

 ;----------------------------

 ; setup to draw the next item

 ;----------------------------

 lea ItemMenu,a6 ; point a6 to the item menu text

 move.l a6,(MEM_DIALOG_TEXT) ; copy a6 to MEM_DIALOG_TEXT

 bsr.w SetItemMenuDrawLocation ; set the draw location of the next item

 bra.w ExitProcessDialog

[...]

There's also some work to set where the next item name should be drawn in the dialog.

SetItemMenuDrawLocation:

 move.w (MEM_DIALOG_ITEM_INDEX),d6 ; copy index of current item to d6

 ;test for 0001

 cmpi.w #$0001,d6 ; is it one?

 bne.s .1 ; branch if not

 ; move down 2 rows

 move.l #(VDP_VRAM_WRITE_A+DIALOG_ROWCOL+$01020000),(MEM_DIALOG_VPD)

 bra.s ExitSetItemMenuDrawLocation ; exit

.1 ; test for 0002

 cmpi.w #$0002,d6 ; is it two?

 bne.s .2 ; branch if not

 ; move down 1 row

 move.l #(VDP_VRAM_WRITE_A+DIALOG_ROWCOL+$00980000),(MEM_DIALOG_VPD)

 bra.s ExitSetItemMenuDrawLocation ; exit

.2 ; test for 0003

 cmpi.w #$0003,d6 ; is it theee?

 bne.s ExitSetItemMenuDrawLocation ; exit if not

 ; move down 1 row and column

 move.l #(VDP_VRAM_WRITE_A+DIALOG_ROWCOL+$01180000),(MEM_DIALOG_VPD)

ExitSetItemMenuDrawLocation:

 rts

Moving the selector sprite needs to account for the new four choice style. It also needs to account for the possibility that there might only be 1-3 items in the list.

FourChoiceLeftRight:

 btst.l #DIALOG_FLAG_STYLE_ITEM_MENU,d7 ; test if this is an item menu

 beq.s .1 ; not an item menu, branch

 ; MEM_DIALOG_ITEM_INDEX has the total number of items in dialog +1

 cmpi.w #$0002,(MEM_DIALOG_ITEM_INDEX) ; are there 2 or fewer items?

 ble.s ExitFourChoiceLeftRight ; exit if 2 or fewer

 ; there are 3 or 4 items, 4 items is fine

 cmpi.w #$0004,(MEM_DIALOG_ITEM_INDEX) ; are there 4 items?

 bge.s .1 ; if so continue

 ; three items is the only possibility now

 cmpi.w #$0001,(MEM_MENU_SELECTION) ; is the 2nd item selected?

 beq.s ExitFourChoiceLeftRight ; if so exit

.1

 cmpi.w #$0002,(MEM_MENU_SELECTION) ; test if <2

 blt.s .2 ; MEM_MENU_SELECTION is > 2

 subq #$0002,(MEM_MENU_SELECTION) ; subtract 2 to rollover

 bra.s ExitFourChoiceLeftRight ; exit

.2

 addq #$0002,(MEM_MENU_SELECTION) ; add 2 to move right

ExitFourChoiceLeftRight:

 rts

FourChoiceUpDown:

 btst.l #DIALOG_FLAG_STYLE_ITEM_MENU,d7 ; test if this is an item menu

 beq.s .1 ; not an item menu, branch

 ; MEM_DIALOG_ITEM_INDEX has the total number of items in dialog +1

 cmpi.w #$0001,(MEM_DIALOG_ITEM_INDEX) ; is there only 1 item?

 beq.s ExitFourChoiceFourChoiceUpDown ; exit if only 1 item

 ; there are 3 or 4 items, 4 items is fine

 cmpi.w #$0004,(MEM_DIALOG_ITEM_INDEX) ; are there 4 items?

 bge.s .1 ; if so continue

 ; three items is the only possibility now

 cmpi.w #$0002,(MEM_MENU_SELECTION) ; is the 3rd item selected?

 beq.s ExitFourChoiceFourChoiceUpDown ; if so exit

.1

 cmpi.w #$0000,(MEM_MENU_SELECTION) ; test if 0

 beq.s FourChoiceUpDownAdd ; MEM_MENU_SELECTION is 0

 cmpi.w #$0002,(MEM_MENU_SELECTION) ; test if 2

 beq.s FourChoiceUpDownAdd ; MEM_MENU_SELECTION is 2

 subq #$0001,(MEM_MENU_SELECTION) ; subtract 1 to rollover

 bra.s ExitFourChoiceFourChoiceUpDown ; exit

FourChoiceUpDownAdd:

 addq #$0001,(MEM_MENU_SELECTION) ; add 2 to move down

ExitFourChoiceFourChoiceUpDown:

 rts

When the player confirms a menu selection there's a little new work to determine if this is an item list and if so to store the selected item.

ConfirmMenuSelection:

[...]

ConfirmMenuSelection4Choice:

 move.w (MEM_MENU_SELECTION),(MEM_MENU_RESPONSE) ; selection->response

 btst.l #DIALOG_FLAG_STYLE_ITEM_MENU,d7 ; test if this is an item menu

 beq.s ExitConfirmMenuSelection ; not an item menu, branch

 ; store selected item in MEM_ACTIVE_ITEM 

 move.l (MEM_DIALOG_ITEM_LIST),a6 ; copy address of item list to a6

 move.w (MEM_MENU_SELECTION),d6 ; copy current item index to d6

 mulu.w #WORD_SIZE,d6 ; multiply by WORD_SIZE to get the offset

 adda.l d6,a6 ; add offset

 move.w (a6),(MEM_ACTIVE_ITEM) ; copy item ID to d6

[...]

The end result is this little dialog showing a list of items:

Item menu

That was fun, OK not a lot of fun to debug but overall this wasn't too bad. Let's wrap this up by...

Responding to item selections

The ProcessAction subroutine was previously built to handle forwarding actions to the appropriate day/scene/action handler. One (of possibly many) flaws with this approach is there are some actions that don't change based on the day & scene. Giving an item is one of them, or at least the initial act of displaying the list of items to give. There needs to be a default handler for this, it needs to be smart enough to determine if the player is trying to open the Give menu or has just selected an item in it. That's pretty easy to sort out:

ProcessAction:

 bsr.w ResetDialog ; reset the dialog

 ; ----------------------------------------

 ; test if a default handler should be used

 ; ----------------------------------------

 cmpi.w #ACTION_TAKE_GIVE,(MEM_ACTION_ID) ; test if this is a give action

 bne.s ProcessActionBuildActionTableOffset ; not give action, branch

 move.w (MEM_ACTION_TARGET_OBJID),d7 ; copy action target to d7

 andi.w #OBJ_NPC_BASE,d7 ; and against base npc ID

 beq.s .1 ; target is not an NPC

 ; --------------------------------------------

 ; default handler for giving an item to an NPC

 ; --------------------------------------------

 cmpi.w #$0000,(MEM_ACTIVE_ITEM) ; test if there is an active item

 bne.s ProcessActionBuildActionTableOffset ; responding to a give menu

 bsr.w DefaultActionGive ; otherwise launch default action

 bra.s ExitProcessAction ; exit

.1 ; test if target is scenery

 move.w (MEM_ACTION_TARGET_OBJID),d7 ; copy action target to d7

 andi.w #OBJ_SCENE_BASE,d7 ; and against base npc ID

 beq.s ProcessActionBuildActionTableOffset ; target is not scenery

 cmpi.w #MAX_ITEMS,(MEM_PLAYER_ITEM_COUNT) ; carrying max items?

 bne.s ProcessActionBuildActionTableOffset ; branch if < max

 bsr.w DefaultActionInventoryFull ; launch default action

 bra.s ExitProcessAction ; exit

ProcessActionBuildActionTableOffset:

 bsr.w BuildActionTableOffset ; build action table offset

 lea ActionTable,a5 ; point to action table

 adda.w (MEM_ACTION_TABLE_OFFSET),a5 ; move to offset location

 move.l (a5),a6 ; a5 has the address of the subroutine to jump to

 jsr (a6) ; jump to location of code to process this event

ExitProcessAction:

 move.l (MEM_GAME_STATE),d7 ; copy current game state to d7

 bclr.l #STATE_FLAG_ACTION,d7 ; clear action flag

 move.l d7,(MEM_GAME_STATE) ; save it back

 rts

The default Give action then displays the menu or a message saying the player doesn't have any items. As a bonus, there's also a message if a player tries to take an item when their inventory is full.

;--------------------------------------------------------------------

; builds the give menu or displays message if the player has no items

;--------------------------------------------------------------------

DefaultActionGive:

 cmpi.w #$0000,(MEM_PLAYER_ITEM_COUNT) ; is item count 0?

 beq.s DefaultActionGiveNoItems ; branch if 0

 lea ItemMenu,a6 ; load dialog text

 move.l a6,MEM_DIALOG_TEXT ; copy address to MEM_DIALOG_TEXT

 lea MEM_PLAYER_ITEMS,a6 ; load item list

 move.l a6,MEM_DIALOG_ITEM_LIST ; copy address to MEM_DIALOG_ITEM_LIST

 move.l (MEM_DIALOG_FLAGS),d7 ; copy dialog flags to d7

 bset.l #DIALOG_FLAG_STYLE_TEXT_4CHOICE,d7 ; set text choice flag

 bset.l #DIALOG_FLAG_STYLE_ITEM_MENU,d7 ; set item menu flag

 move.l d7,(MEM_DIALOG_FLAGS) ; save updated dialog flags

 bra.s ExitDefaultActionGive ; exit

DefaultActionGiveNoItems:

 lea DialogTextNoItems,a6 ; load dialog text

 move.l a6,MEM_DIALOG_TEXT ; copy address to MEM_DIALOG_TEXT

ExitDefaultActionGive:

 rts

;-------------------------------------------------------

; displays a message if the player can't hold more items

;-------------------------------------------------------

DefaultActionInventoryFull:

 lea TakeMenuFull,a6 ; load dialog text

 move.l a6,MEM_DIALOG_TEXT ; copy address to MEM_DIALOG_TEXT

ExitDefaultActionInventoryFull:

 rts

In the action script there are two ways we can respond to a Give/Take action. We can look at the selected index in the dialog and display a message. This code example does that. Another option is responding based on the item ID that was selected. This is more useful in 99% of cases but I coded the other one first (and again am lazy). This also shows how to handle giving an item to an NPC.

Day00Scene00Action02: ; ACTION_TAKE_GIVE

 move.w (MEM_ACTION_TARGET_OBJID),d6 ; copy action target to d6

 andi.w #OBJ_SCENE_BASE,d6 ; and against base scene ID

 beq.w Day00Scene00Action02DefaultGive ; not scenery

 move.w (MEM_ACTION_TARGET_OBJID),d6 ; copy action target to d6

 cmpi.w #OBJ_SCENE_VB_MAGS,d6 ; is the magazine rack the target?

 bne.w Day00Scene00Action02DefaultTake ; not the magazine rack, branch

 ; check if we are coming back from a take menu or need to open one 

 cmpi.w #DIALOG_NO_RESPONSE,(MEM_MENU_RESPONSE) ; test response

 beq.s .5 ; branch if no response

 cmpi.w #$0000,(MEM_MENU_RESPONSE) ; test response

 bne.s .1

 lea TakeMagazinesOption0,a6 ; load dialog text

 bra.s .4

.1

 cmpi.w #$0001,(MEM_MENU_RESPONSE) ; test response

 bne.s .2

 lea TakeMagazinesOption1,a6 ; load dialog text

 bra.s .4

.2

 cmpi.w #$0002,(MEM_MENU_RESPONSE) ; test response

 bne.s .3

 lea TakeMagazinesOption2,a6 ; load dialog text

 bra.s .4

.3

 cmpi.w #$0003,(MEM_MENU_RESPONSE) ; test response

 bne.s .3

 lea TakeMagazinesOption3,a6 ; load dialog text

.4

 move.l a6,MEM_DIALOG_TEXT ; copy address to MEM_DIALOG_TEXT

 move.l (MEM_DIALOG_FLAGS),d7 ; copy dialog flags to d7

 bclr.l #DIALOG_FLAG_STYLE_TEXT_4CHOICE,d7 ; set text choice flag

 move.l d7,(MEM_DIALOG_FLAGS) ; save updated dialog flags

 bra.s ExitDay00Scene00Action02

.5

 lea TakeMenuMagazines,a6 ; load dialog text

 move.l a6,MEM_DIALOG_TEXT ; copy address to MEM_DIALOG_TEXT

 lea ItemListVBMagazine,a6 ; load item list

 move.l a6,MEM_DIALOG_ITEM_LIST ; copy address to MEM_DIALOG_ITEM_LIST

 move.l (MEM_DIALOG_FLAGS),d7 ; copy dialog flags to d7

 bset.l #DIALOG_FLAG_STYLE_TEXT_4CHOICE,d7 ; set text choice flag

 bset.l #DIALOG_FLAG_STYLE_ITEM_MENU,d7 ; set item menu flag

 move.l d7,(MEM_DIALOG_FLAGS) ; save updated dialog flags

 bra.s ExitDay00Scene00Action02

Day00Scene00Action02DefaultTake:

 lea DialogTextCantTake,a6 ; load dialog text

 move.l a6,MEM_DIALOG_TEXT ; copy address to MEM_DIALOG_TEXT

 bra.s ExitDay00Scene00Action02

Day00Scene00Action02DefaultGive:

 lea DialogTextNothingHappens,a6 ; load dialog text

 move.l a6,MEM_DIALOG_TEXT ; copy address to MEM_DIALOG_TEXT

ExitDay00Scene00Action02:

 rts

And the end result is this exciting message:

Responding to a selection

With just a little work items can be added to all the shelves and racks. We can also have the NPCs respond to items you show them. This is all part of the overall game plan for a one-room demo. This seems like a good enough time as any to check in on that...

What's next?

Looking at the "plan" from three articles ago:

1) Dialog between characters - meaning an NPC says something to you and you respond. Maybe you respond with more dialog, maybe you give them an item. That leads to...

2) Inventory management - along with basic stuff like taking and giving items.

3) Game event tracking - we need a way to say "if [X] happened and you talk to character [Y] then do [Z]", I'll probably over-complicate this. I won't call this 100% complete but it's functional enough.

4) Scripted sprite movements - if the ultimate goal is to get a customer to leave a store then there needs to be an animation where they walk away.

5) Adding & removing NPCs from the current scene - the one NPC is hard-coded, there needs to be a way to move NPCs in and out of scenes. The removing part hasn't been needed yet but it's small and will be addressed with #4.

6) To make this look like a real demo I should really create a title screen and ending message.

7) Dozens of things I didn't think of that will all be painful to work out.

Next round will be scripted sprite movements, along with removing NPCs from the scene. Of course adding more items and NPC dialog needs to happen along the way too.

Download

Download the latest source code on GitHub




Tweet