summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRangi <remy.oukaour+rangi42@gmail.com>2018-07-28 13:49:10 -0400
committerRangi <remy.oukaour+rangi42@gmail.com>2018-07-28 13:49:10 -0400
commit25103d65e37c07f9e629feaf9c6e9be3bf1f743d (patch)
tree186623fb0db6e2bf8d9e66cbf868f42fc970a4a6
parent571f1554dad9482c11c86dfb3dff7e6735dfeabd (diff)
Allow more than 15 object_events per map
-rw-r--r--Allow-more-than-15-object_events-per-map.md145
-rw-r--r--Tutorials.md2
-rw-r--r--screenshots/17-object_events.pngbin0 -> 1839 bytes
3 files changed, 146 insertions, 1 deletions
diff --git a/Allow-more-than-15-object_events-per-map.md b/Allow-more-than-15-object_events-per-map.md
new file mode 100644
index 0000000..2f67d9f
--- /dev/null
+++ b/Allow-more-than-15-object_events-per-map.md
@@ -0,0 +1,145 @@
+Map scripts in [maps/\*.asm](../tree/master/maps/) declare new objects—NPCs, item balls, Berry trees, etc—with the `object_event` macro. But you can't have more than 15 `object_event`s in one map. ([GoldenrodCity.asm](../blob/master/maps/GoldenrodCity.asm) reaches this limit, and four other maps nearly do with 14 `object_event`s.) Turns out this is an easy limit to increase.
+
+Edit [constants/wram_constants.asm](../blob/master/constants/wram_constants.asm):
+
+```diff
+ ; wMapObjects:: ; d71e
+ PLAYER_OBJECT EQU 0
+-NUM_OBJECTS EQU $10
++NUM_OBJECTS EQU $12
+```
+
+And edit [wram.asm](../blob/master/wram.asm):
+
+```diff
+- ds 40
++ ds 6
+
+ wMapObjects:: ; d71e
+ wPlayerObject:: map_object wPlayer
+ wMap1Object:: map_object wMap1
+ wMap2Object:: map_object wMap2
+ wMap3Object:: map_object wMap3
+ wMap4Object:: map_object wMap4
+ wMap5Object:: map_object wMap5
+ wMap6Object:: map_object wMap6
+ wMap7Object:: map_object wMap7
+ wMap8Object:: map_object wMap8
+ wMap9Object:: map_object wMap9
+ wMap10Object:: map_object wMap10
+ wMap11Object:: map_object wMap11
+ wMap12Object:: map_object wMap12
+ wMap13Object:: map_object wMap13
+ wMap14Object:: map_object wMap14
+ wMap15Object:: map_object wMap15
++wMap16Object:: map_object wMap16
++wMap17Object:: map_object wMap17
+ wMapObjectsEnd::
+
+ wObjectMasks:: ds NUM_OBJECTS ; d81e
+```
+
+That's it! We just added space for maps to define two more `object_event`s.
+
+We can demonstrate this by editing [maps/GoldenrodCity.asm](../blob/master/maps/GoldenrodCity.asm):
+
+```diff
+- db 15 ; object events
++ db 17 ; object events
+ object_event 7, 18, SPRITE_POKEFAN_M, SPRITEMOVEDATA_STANDING_UP, 0, 0, -1, -1, 0, OBJECTTYPE_SCRIPT, 0, GoldenrodCityPokefanMScript, EVENT_GOLDENROD_CITY_CIVILIANS
+ ...
+ object_event 12, 22, SPRITE_POKEFAN_M, SPRITEMOVEDATA_SPINRANDOM_SLOW, 0, 0, -1, -1, PAL_NPC_RED, OBJECTTYPE_SCRIPT, 0, MoveTutorScript, EVENT_GOLDENROD_CITY_MOVE_TUTOR
++ object_event 17, 12, SPRITE_YOUNGSTER, SPRITEMOVEDATA_STANDING_LEFT, 0, 0, -1, -1, PAL_NPC_RED, OBJECTTYPE_SCRIPT, 0, GoldenrodCityTrainSpotter1Script, EVENT_RESTORED_POWER_TO_KANTO
++ object_event 22, 13, SPRITE_YOUNGSTER, SPRITEMOVEDATA_SPINRANDOM_SLOW, 0, 0, -1, -1, PAL_NPC_BLUE, OBJECTTYPE_SCRIPT, 0, GoldenrodCityTrainSpotter2Script, EVENT_RESTORED_POWER_TO_KANTO
++
++GoldenrodCityTrainSpotter1Script:
++ jumptextfaceplayer .Text
++
++.Text:
++ text "The MAGNET TRAIN"
++ line "isn't here, so"
++ cont "we're safe on the"
++ cont "tracks."
++
++ para "I'm disappointed"
++ line "though… I wanted"
++ cont "to photograph it!"
++ done
++
++GoldenrodCityTrainSpotter2Script:
++ jumptextfaceplayer .Text
++
++.Text:
++ text "Trainspotting is"
++ line "a hobby anyone"
++ cont "can get into!"
++
++ para "I collect train"
++ line "tickets and"
++ cont "timetables!"
++ done
+```
+
+The new 16th and 17th NPCs will appear:
+
+![Screenshot](screenshots/17-object_events.png)
+
+Let's look at how it works. `wMapObjects` is an array of `map_object` structs, one for each possible object (including the player). You can see what data is stored for each `map_object` in the macro definition in [macros/wram.asm](../blob/master/macros/wram.asm):
+
+```asm
+map_object: MACRO
+\1ObjectStructID:: db
+\1ObjectSprite:: db
+\1ObjectYCoord:: db
+\1ObjectXCoord:: db
+\1ObjectMovement:: db
+\1ObjectRadius:: db
+\1ObjectHour:: db
+\1ObjectTimeOfDay:: db
+\1ObjectColor:: db
+\1ObjectRange:: db
+\1ObjectScript:: dw
+\1ObjectEventFlag:: dw
+ ds 2
+ENDM
+```
+
+This is all the same data that gets declared by the `object_event` macro, defined in [macros/scripts/maps.asm](../blob/master/macros/scripts/maps.asm):
+
+```asm
+object_event: MACRO
+;\1: x: left to right, starts at 0
+;\2: y: top to bottom, starts at 0
+;\3: sprite: a SPRITE_* constant
+;\4: movement function: a SPRITEMOVEDATA_* constant
+;\5, \6: movement radius: x, y
+;\7, \8: hour limits: h1, h2 (0-23)
+; * if h1 < h2, the object_event will only appear from h1 to h2
+; * if h1 > h2, the object_event will not appear from h2 to h1
+; * if h1 == h2, the object_event will always appear
+; * if h1 == -1, h2 is treated as a time-of-day value:
+; a combo of MORN, DAY, and/or NITE, or -1 to always appear
+;\9: color: a PAL_NPC_* constant, or 0 for sprite default
+;\10: function: a OBJECTTYPE_* constant
+;\11: sight range: applies to OBJECTTYPE_TRAINER
+;\12: script pointer
+;\13: event flag: an EVENT_* constant, or -1 to always appear
+ db \3, \2 + 4, \1 + 4, \4
+ dn \6, \5
+ db \7, \8
+ shift
+ dn \8, \9
+ shift
+ db \9
+ shift
+ dw \9
+ shift
+ dw \9
+ENDM
+```
+
+`wObjectMasks` is likewise an array of mask bytes, one for each possible object. If the mask is −1, the object is hidden.
+
+Basically, the `object_event` structs in the ROM get copied into the `map_object` structs in RAM, so there needs to be enough space in RAM for all of them. And each new object needs 17 bytes—16 for its `map_object` (count them), and one for its mask—so we had to use 34 of the unused bytes in that `ds 40`.
+
+If you wanted to allow an 18th object, you would have to find 17 bytes of unused space here and there in the same `SECTION` as `wMapObjects` and `wObjectMasks`. Which is not difficult; if you scroll down to the "`map scene ids`" and "`fight counts`", they both have large chunks of unused space afterwards (`ds 49` and `ds 100`).
diff --git a/Tutorials.md b/Tutorials.md
index 2259341..2265c4d 100644
--- a/Tutorials.md
+++ b/Tutorials.md
@@ -40,6 +40,7 @@ Tutorials may use diff syntax to show edits:
- [Expand tilesets from 192 to 255 tiles](Expand-tilesets-from-192-to-255-tiles)
- [Allow map tiles to appear above sprites (so NPCs can walk behind tiles) with `PRIORITY` colors](Allow-map-tiles-to-appear-above-sprites-\(so-NPCs-can-walk-behind-tiles\)-with-PRIORITY-colors)
- [Allow tiles to have different attributes in different blocks (including X and Y flip)](Allow-tiles-to-have-different-attributes-in-different-blocks-\(including-X-and-Y-flip\))
+- [Allow more than 15 `object_event`s per map](Allow-more-than-15-object_events-per-map)
- [Increase Pokémon sprite animation size](Increase-Pokémon-sprite-animation-size)
- [Allow more trainer parties, with individual DVs, stat experience, and nicknames](Allow-more-trainer-parties,-with-individual-DVs,-stat-experience,-and-nicknames)
- [Colored trainer card badges](Colored-trainer-card-badges)
@@ -80,7 +81,6 @@ Tutorials may use diff syntax to show edits:
- Dive (exists in [Orange](https://github.com/PiaCarrot/pokeorange))
- Evolution methods (location, held item, move, [etc](https://gitgud.io/pfero/axyllagame/commit/81914d43eb89195734caee724c0a40d4686a0bab))
- More daily and weekly events
-- More than 15 `object_event`s per map
- Third trainer card page for Kanto badges
- Fourth stats page for caught data
- Colored party menu icons
diff --git a/screenshots/17-object_events.png b/screenshots/17-object_events.png
new file mode 100644
index 0000000..26d2c07
--- /dev/null
+++ b/screenshots/17-object_events.png
Binary files differ