lufia2ac: ability to swap party members mid-run and option to gain EXP while inactive (#2800)

This commit is contained in:
el-u 2024-04-09 00:33:34 +02:00 committed by GitHub
parent 1021df8b1b
commit 14437d653f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 101 additions and 7 deletions

View File

@ -593,6 +593,20 @@ class HealingFloorChance(Range):
default = 16
class InactiveExpGain(Choice):
"""The rate at which characters not currently in the active party gain EXP.
Supported values: disabled, half, full
Default value: disabled (same as in an unmodified game)
"""
display_name = "Inactive character EXP gain"
option_disabled = 0
option_half = 50
option_full = 100
default = option_disabled
class InitialFloor(Range):
"""The initial floor, where you begin your journey.
@ -805,7 +819,7 @@ class ShufflePartyMembers(Toggle):
false all 6 optional party members are present in the cafe and can be recruited right away
true only Maxim is available from the start; 6 new "items" are added to your pool and shuffled into the
multiworld; when one of these items is found, the corresponding party member is unlocked for you to use.
While cave diving, you can add newly unlocked ones to your party by using the character items from the inventory
While cave diving, you can add or remove unlocked party members by using the character items from the inventory
Default value: false (same as in an unmodified game)
"""
@ -838,6 +852,7 @@ class L2ACOptions(PerGameCommonOptions):
goal: Goal
gold_modifier: GoldModifier
healing_floor_chance: HealingFloorChance
inactive_exp_gain: InactiveExpGain
initial_floor: InitialFloor
iris_floor_chance: IrisFloorChance
iris_treasures_required: IrisTreasuresRequired

View File

@ -232,6 +232,7 @@ class L2ACWorld(World):
rom_bytearray[0x280018:0x280018 + 1] = self.o.shuffle_party_members.unlock.to_bytes(1, "little")
rom_bytearray[0x280019:0x280019 + 1] = self.o.shuffle_capsule_monsters.unlock.to_bytes(1, "little")
rom_bytearray[0x28001A:0x28001A + 1] = self.o.shop_interval.value.to_bytes(1, "little")
rom_bytearray[0x28001B:0x28001B + 1] = self.o.inactive_exp_gain.value.to_bytes(1, "little")
rom_bytearray[0x280030:0x280030 + 1] = self.o.goal.value.to_bytes(1, "little")
rom_bytearray[0x28003D:0x28003D + 1] = self.o.death_link.value.to_bytes(1, "little")
rom_bytearray[0x281200:0x281200 + 470] = self.get_capsule_cravings_table()

View File

@ -309,6 +309,12 @@ org $8EFD2E ; unused region at the end of bank $8E
DB $1E,$0B,$01,$2B,$05,$1A,$05,$00 ; add dekar
DB $1E,$0B,$01,$2B,$04,$1A,$06,$00 ; add tia
DB $1E,$0B,$01,$2B,$06,$1A,$07,$00 ; add lexis
DB $1F,$0B,$01,$2C,$01,$1B,$02,$00 ; remove selan
DB $1F,$0B,$01,$2C,$02,$1B,$03,$00 ; remove guy
DB $1F,$0B,$01,$2C,$03,$1B,$04,$00 ; remove arty
DB $1F,$0B,$01,$2C,$05,$1B,$05,$00 ; remove dekar
DB $1F,$0B,$01,$2C,$04,$1B,$06,$00 ; remove tia
DB $1F,$0B,$01,$2C,$06,$1B,$07,$00 ; remove lexis
pullpc
SpecialItemUse:
@ -328,11 +334,15 @@ SpecialItemUse:
SEP #$20
LDA $8ED8C7,X ; load predefined bitmask with a single bit set
BIT $077E ; check against EV flags $02 to $07 (party member flags)
BNE + ; abort if character already present
LDA $07A9 ; load EV register $11 (party counter)
BEQ ++
LDA.b #$30 ; character already present; modify pointer to point to L2SASM leave script
ADC $09B7
STA $09B7
BRA +++
++: LDA $07A9 ; character not present; load EV register $0B (party counter)
CMP.b #$03
BPL + ; abort if party full
LDA.b #$8E
+++ LDA.b #$8E
STA $09B9
PHK
PEA ++
@ -340,7 +350,6 @@ SpecialItemUse:
JML $83BB76 ; initialize parser variables
++: NOP
JSL $809CB8 ; call L2SASM parser
JSL $81F034 ; consume the item
TSX
INX #13
TXS
@ -490,6 +499,73 @@ pullpc
; allow inactive characters to gain exp
pushpc
org $81DADD
; DB=$81, x=0, m=1
NOP ; overwrites BNE $81DAE2 : JMP $DBED
JML HandleActiveExp
AwardExp:
; isolate exp distribution into a subroutine, to be reused for both active party members and inactive characters
org $81DAE9
NOP #2 ; overwrites JMP $DBBD
RTL
org $81DB42
NOP #2 ; overwrites JMP $DBBD
RTL
org $81DD11
; DB=$81, x=0, m=1
JSL HandleInactiveExp ; overwrites LDA $0A8A : CLC
pullpc
HandleActiveExp:
BNE + ; (overwritten instruction; modified) check if statblock not empty
JML $81DBED ; (overwritten instruction; modified) abort
+: JSL AwardExp ; award exp (X=statblock pointer, Y=position in battle order, $00=position in menu order)
JML $81DBBD ; (overwritten instruction; modified) continue to next level text
HandleInactiveExp:
LDA $F0201B ; load inactive exp gain rate
BEQ + ; zero gain; skip everything
CMP.b #$64
BCS ++ ; full gain
LSR $1607
ROR $1606 ; half gain
ROR $1605
++: LDY.w #$0000 ; start looping through all characters
-: TDC
TYA
LDX.w #$0003 ; start looping through active party
--: CMP $0A7B,X
BEQ ++ ; skip if character in active party
DEX
BPL -- ; continue looping through active party
STA $153D ; inactive character detected; overwrite character index of 1st slot in party battle order
ASL
TAX
REP #$20
LDA $859EBA,X ; convert character index to statblock pointer
SEP #$20
TAX
PHY ; stash character loop index
LDY $0A80
PHY ; stash 1st (in menu order) party member statblock pointer
STX $0A80 ; overwrite 1st (in menu order) party member statblock pointer
LDY.w #$0000 ; set to use 1st position (in battle order)
STY $00 ; set to use 1st position (in menu order)
JSL AwardExp ; award exp (X=statblock pointer, Y=position in battle order, $00=position in menu order)
PLY ; restore 1st (in menu order) party member statblock pointer
STY $0A80
PLY ; restore character loop index
++: INY
CPY.w #$0007
BCC - ; continue looping through all characters
+: LDA $0A8A ; (overwritten instruction) load current gold
CLC ; (overwritten instruction)
RTL
; receive death link
pushpc
org $83BC91
@ -1226,6 +1302,7 @@ pullpc
; $F02018 1 party members available
; $F02019 1 capsule monsters available
; $F0201A 1 shop interval
; $F0201B 1 inactive exp gain rate
; $F02030 1 selected goal
; $F02031 1 goal completion: boss
; $F02032 1 goal completion: iris_treasure_hunt

View File

@ -53,8 +53,9 @@ Your Party Leader will hold up the item they received when not in a fight or in
- Randomize enemy movement patterns, enemy sprites, and which enemy types can appear at which floor numbers
- Option to make shops appear in the cave so that you have a way to spend your hard-earned gold
- Option to shuffle your party members and/or capsule monsters into the multiworld, meaning that someone will have to
find them in order to unlock them for you to use. While cave diving, you can add newly unlocked members to your party
by using the character items from your inventory
find them in order to unlock them for you to use. While cave diving, you can add or remove unlocked party members by
using the character items from your inventory. There's also an option to allow inactive characters to gain some EXP,
so that new party members added during a run don't have to start off at a low level
###### Quality of life: