You've already forked pokecrystal-board
mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2025-12-11 05:02:16 -08:00
Multiplayer engine [Commit 1] (#40)
This commit is contained in:
@@ -17,3 +17,11 @@ DEF PLAYERDATA_FRONTPIC rw
|
||||
DEF PLAYERDATA_BACKPIC rw
|
||||
DEF PLAYERDATA_PIC_PAL rw
|
||||
DEF PLAYERDATA_LENGTH EQU _RS
|
||||
; see data/players/objects.asm
|
||||
const_def
|
||||
const PLAYER_DEFAULT ; 0
|
||||
const PLAYER_YOUNGSTER_1 ; 1
|
||||
const PLAYER_YOUNGSTER_2 ; 2
|
||||
const PLAYER_YOUNGSTER_3 ; 3
|
||||
const PLAYER_BUG_CATCHER_1 ; 4
|
||||
DEF NUM_PLAYER_CHARACTERS EQU const_value
|
||||
|
||||
53
data/players/objects.asm
Executable file
53
data/players/objects.asm
Executable file
@@ -0,0 +1,53 @@
|
||||
PlayerObjects:
|
||||
table_width 2, PlayerObjects
|
||||
dw .Default ; PLAYER_DEAFULT
|
||||
dw .Youngster1 ; PLAYER_YOUNGSTER_1
|
||||
dw .Youngster2 ; PLAYER_YOUNGSTER_2
|
||||
dw .Youngster3 ; PLAYER_YOUNGSTER_3
|
||||
dw .BugCatcher1 ; PLAYER_BUG_CATCHER_1
|
||||
assert_table_length NUM_PLAYER_CHARACTERS
|
||||
|
||||
.Default:
|
||||
db -1 ; MAPOBJECT_OBJECT_STRUCT_ID
|
||||
object_event 0, 0, SPRITE_CHRIS, SPRITEMOVEDATA_STANDING_DOWN, 0, 0, -1, -1, PAL_NPC_RED, OBJECTTYPE_SCRIPT, 0, ObjectEvent, -1
|
||||
.DefaultFields:
|
||||
; [wPlayerGender], [wPlayerState], sprite id, palette
|
||||
db 0, PLAYER_NORMAL, SPRITE_CHRIS, PAL_NPC_RED << 4 | OBJECTTYPE_SCRIPT
|
||||
db 1 << PLAYERGENDER_FEMALE_F, PLAYER_NORMAL, SPRITE_KRIS, PAL_NPC_BLUE << 4 | OBJECTTYPE_SCRIPT
|
||||
db 0, PLAYER_SURF, SPRITE_SURF, PAL_NPC_RED << 4 | OBJECTTYPE_SCRIPT
|
||||
db 1 << PLAYERGENDER_FEMALE_F, PLAYER_SURF, SPRITE_SURF, PAL_NPC_BLUE << 4 | OBJECTTYPE_SCRIPT
|
||||
db 0, PLAYER_BIKE, SPRITE_CHRIS_BIKE, PAL_NPC_RED << 4 | OBJECTTYPE_SCRIPT
|
||||
db 1 << PLAYERGENDER_FEMALE_F, PLAYER_BIKE, SPRITE_KRIS_BIKE, PAL_NPC_BLUE << 4 | OBJECTTYPE_SCRIPT
|
||||
db -1
|
||||
|
||||
.Youngster1:
|
||||
object_event 0, 0, SPRITE_YOUNGSTER, SPRITEMOVEDATA_STANDING_DOWN, 0, 0, -1, -1, PAL_NPC_RED, OBJECTTYPE_SCRIPT, 0, ObjectEvent, -1
|
||||
; [wPlayerState], sprite id, palette
|
||||
db PLAYER_NORMAL, SPRITE_YOUNGSTER, PAL_NPC_RED << 4 | OBJECTTYPE_SCRIPT
|
||||
db PLAYER_SURF, SPRITE_SURF, PAL_NPC_RED << 4 | OBJECTTYPE_SCRIPT
|
||||
db PLAYER_BIKE, SPRITE_CHRIS_BIKE, PAL_NPC_RED << 4 | OBJECTTYPE_SCRIPT
|
||||
db -1
|
||||
|
||||
.Youngster2:
|
||||
object_event 0, 0, SPRITE_YOUNGSTER, SPRITEMOVEDATA_STANDING_DOWN, 0, 0, -1, -1, PAL_NPC_BLUE, OBJECTTYPE_SCRIPT, 0, ObjectEvent, -1
|
||||
; [wPlayerState], sprite id, palette
|
||||
db PLAYER_NORMAL, SPRITE_YOUNGSTER, PAL_NPC_BLUE << 4 | OBJECTTYPE_SCRIPT
|
||||
db PLAYER_SURF, SPRITE_YOUNGSTER, PAL_NPC_BLUE << 4 | OBJECTTYPE_SCRIPT
|
||||
db PLAYER_BIKE, SPRITE_YOUNGSTER, PAL_NPC_BLUE << 4 | OBJECTTYPE_SCRIPT
|
||||
db -1
|
||||
|
||||
.Youngster3:
|
||||
object_event 0, 0, SPRITE_YOUNGSTER, SPRITEMOVEDATA_STANDING_DOWN, 0, 0, -1, -1, PAL_NPC_GREEN, OBJECTTYPE_SCRIPT, 0, ObjectEvent, -1
|
||||
; [wPlayerState], sprite id, palette
|
||||
db PLAYER_NORMAL, SPRITE_YOUNGSTER, PAL_NPC_GREEN << 4 | OBJECTTYPE_SCRIPT
|
||||
db PLAYER_SURF, SPRITE_YOUNGSTER, PAL_NPC_GREEN << 4 | OBJECTTYPE_SCRIPT
|
||||
db PLAYER_BIKE, SPRITE_YOUNGSTER, PAL_NPC_GREEN << 4 | OBJECTTYPE_SCRIPT
|
||||
db -1
|
||||
|
||||
.BugCatcher1:
|
||||
object_event 0, 0, SPRITE_BUG_CATCHER, SPRITEMOVEDATA_STANDING_DOWN, 0, 0, -1, -1, PAL_NPC_BROWN, OBJECTTYPE_SCRIPT, 0, ObjectEvent, -1
|
||||
; [wPlayerState], sprite id, palette
|
||||
db PLAYER_NORMAL, SPRITE_YOUNGSTER, PAL_NPC_BROWN << 4 | OBJECTTYPE_SCRIPT
|
||||
db PLAYER_SURF, SPRITE_YOUNGSTER, PAL_NPC_BROWN << 4 | OBJECTTYPE_SCRIPT
|
||||
db PLAYER_BIKE, SPRITE_YOUNGSTER, PAL_NPC_BROWN << 4 | OBJECTTYPE_SCRIPT
|
||||
db -1
|
||||
@@ -228,13 +228,15 @@ The view map mode is like a moving camera. The player sprite stays static while
|
||||
|
||||
Off-limits means that tiles that have special collision value *COLL_OUT_OF_BOUNDS* (specifically defined for this) can't be crossed, and that map limits can't be crossed unless there is a connection to another map. Additionally, a maximum view map mode range that the player is allowed in either direction, counting from the coordinates where view map mode was started, is governed by *wViewMapModeRange* (in number of tiles). Initialization or unlocking of *wViewMapModeRange* is your design choice.
|
||||
|
||||
View map mode is exited by pressing the B button. Exiting view map mode effectively triggers a warp to where the player was at before entering view map mode, with whatever the state was.
|
||||
|
||||

|
||||
|
||||
While in view map mode, *hCurBoardEvent* contains *BOARDEVENT_VIEW_MAP_MODE*. Transition from view map mode to the "regular" overworld occurs with *hCurBoardEvent* containing *BOARDEVENT_REDISPLAY_MENU* (if view map mode entered from board menu) or *BOARDEVENT_RESUME_BRANCH* (if view map mode entered from branch space). As with other board event values, they have a specific handler in *CheckBoardEvent*.
|
||||
While in view map mode, *hCurBoardEvent* contains *BOARDEVENT_VIEW_MAP_MODE*. When view map mode is entered, the player sprite is temporarily "turned into" an NPC by copying its data to the last object slot in *wMapObjects* (see *MockPlayerObject*), whilst the actual player sprite is made transparent.
|
||||
|
||||
A rough workflow of the view map mode engine is available in [docs/develop/workflows.md](docs/develop/workflows.asm). View map mode player movement logic is at *DoPlayerMovement* in [engine/overworld/player_movement.md](engine/overworld/player_movement.asm) along with other types of player movement. Logic for entering view map mode is embedded into the board menu code or the branch space code. When view map mode is entered, the player sprite is temporarily "turned into" an NPC (see *MockPlayerObject*), whilst the actual player sprite is made transparent.
|
||||
View map mode is exited by pressing the B button. Exiting view map mode effectively triggers a warp to where the player was at before entering view map mode, with whatever the state was. Transition from view map mode to the "regular" overworld occurs with *hCurBoardEvent* containing *BOARDEVENT_REDISPLAY_MENU* (if view map mode entered from board menu) or *BOARDEVENT_RESUME_BRANCH* (if view map mode entered from branch space). As with other board event values, they have a specific handler in *CheckBoardEvent*.
|
||||
|
||||
View map mode player movement logic is at *DoPlayerMovement* in [engine/overworld/player_movement.md](engine/overworld/player_movement.asm) along with other types of player movement. Logic for entering view map mode is embedded into the board menu code or the branch space code.
|
||||
|
||||
A rough workflow of the view map mode engine is available in [docs/develop/workflows.md](docs/develop/workflows.asm).
|
||||
|
||||
## Map state preservation
|
||||
|
||||
@@ -246,6 +248,8 @@ The backing up of disabled spaces to WRAM is done individually per space the mom
|
||||
|
||||
When a map is entered during a level, if the map has been visited before during the current level, there will be backup disabled space and map object data for it. Its existence is looked up in *wDisabledSpacesBackups* and *wMapObjectsBackups* by searching for an entry matching the map group and map id of the map being entered (*LoadDisabledSpaces* map setup command and an extension to *CopyMapObjectEvents* all the way from the *LoadMapAttributes* map setup command).
|
||||
|
||||
Regarding map connections, note that, while a mocked player sprite during view map mode remains visible when crossing a connection by "respawning" it in the destination map (see *RepositionMockedPlayerObject*), the "respawning" of other map objects across map connections isn't supported. If you for example put an NPC too close to a map connection, it will disappear from the screen when crossing the connection, just like in Pokemon Crystal.
|
||||
|
||||
# Game navigation and progression
|
||||
|
||||
The main menus (in some cases just mocks) outside the overworld provided in pokecrystal-board are:
|
||||
|
||||
@@ -153,6 +153,19 @@ StartMap:
|
||||
cp MAPSETUP_ENTERLEVEL
|
||||
jr nz, .not_starting_level
|
||||
|
||||
; initialize board players
|
||||
ld a, 1
|
||||
ld [wNumLevelPlayers], a
|
||||
ld hl, wPlayer1Id
|
||||
ld a, PLAYER_DEFAULT
|
||||
ld [hli], a ; wPlayer1Id
|
||||
ld a, PLAYER_YOUNGSTER_1
|
||||
ld [hli], a ; wPlayer2Id
|
||||
ld a, PLAYER_YOUNGSTER_3
|
||||
ld [hli], a ; wPlayer3Id
|
||||
ld a, PLAYER_BUG_CATCHER_1
|
||||
ld [hl], a ; wPlayer4Id
|
||||
|
||||
; initialize board state
|
||||
xor a
|
||||
ld hl, wCurTurn
|
||||
|
||||
@@ -940,18 +940,29 @@ MockPlayerObject::
|
||||
; refresh wPlayerObjectYCoord and wPlayerObjectXCoord (not strictly necessary)
|
||||
farcall RefreshPlayerCoords
|
||||
; copy default sprite object to the last object struct
|
||||
ld hl, .DefaultPlayerObject
|
||||
ld hl, PlayerObjects.Default
|
||||
ld de, wMapObject{d:LAST_OBJECT}
|
||||
ld bc, OBJECT_EVENT_SIZE + 1
|
||||
ld a, -1 ; MAPOBJECT_OBJECT_STRUCT_ID
|
||||
ld [de], a
|
||||
inc de
|
||||
ld bc, OBJECT_EVENT_SIZE
|
||||
call CopyBytes
|
||||
|
||||
; adjust palette number
|
||||
ld a, [wPlayerCharacter]
|
||||
ld e, PLAYERDATA_OW_PAL
|
||||
call GetPlayerField
|
||||
add PAL_NPC ; convert from PAL_OW to PAL_NPC
|
||||
swap a
|
||||
or OBJECTTYPE_SCRIPT
|
||||
; adjust sprite id and palette number
|
||||
ld hl, PlayerObjects.Default + (PlayerObjects.DefaultFields - PlayerObjects.Default)
|
||||
.loop
|
||||
ld a, [wPlayerGender]
|
||||
cp [hl]
|
||||
inc hl
|
||||
jr nz, .next1
|
||||
ld a, [wPlayerState]
|
||||
cp [hl]
|
||||
inc hl
|
||||
jr nz, .next2
|
||||
; found a match
|
||||
ld a, [hli] ; sprite
|
||||
ld [wMapObject{d:LAST_OBJECT}Sprite], a
|
||||
ld a, [hl] ; palette | objecttype
|
||||
ld [wMapObject{d:LAST_OBJECT}Palette], a ; also wMapObject{d:LAST_OBJECT}Type
|
||||
|
||||
; adjust sprite id
|
||||
@@ -985,10 +996,6 @@ MockPlayerObject::
|
||||
call UnmaskCopyMapObjectStruct
|
||||
ret
|
||||
|
||||
.DefaultPlayerObject:
|
||||
db -1 ; MAPOBJECT_OBJECT_STRUCT_ID
|
||||
object_event 0, 0, SPRITE_CHRIS, SPRITEMOVEDATA_STANDING_DOWN, 0, 0, -1, -1, PAL_NPC_RED, OBJECTTYPE_SCRIPT, 0, ObjectEvent, -1
|
||||
|
||||
GetSouthConnectedSpriteCoords:
|
||||
; ycoord / 2 <= 2
|
||||
ld a, e
|
||||
@@ -1192,3 +1199,5 @@ CheckPlayerMockSpriteOutOfScreen:
|
||||
ret z ; nc
|
||||
scf
|
||||
ret
|
||||
|
||||
INCLUDE "data/players/objects.asm"
|
||||
|
||||
@@ -2531,6 +2531,12 @@ wBikeStep:: dw
|
||||
wKurtApricornQuantity:: db
|
||||
|
||||
wCurLevel:: db
|
||||
wNumLevelPlayers:: db
|
||||
wPlayer1Id:: db
|
||||
wPlayer2Id:: db
|
||||
wPlayer3Id:: db
|
||||
wPlayer4Id:: db
|
||||
|
||||
wDefaultLevelSelectionMenuLandmark:: db
|
||||
wLevelSelectionMenuEntryEventQueue:: flag_array NUM_LSM_EVENTS
|
||||
|
||||
@@ -2571,6 +2577,8 @@ wCurSpace:: db
|
||||
wCurLevelCoins:: ds 3
|
||||
wCurLevelExp:: ds 3
|
||||
|
||||
wCurTurnPlayer:: db
|
||||
|
||||
wCurSpaceStruct:: space_struct wCurSpace
|
||||
wCurSpaceStructEnd::
|
||||
|
||||
|
||||
Reference in New Issue
Block a user