Lose money proportional to badges and level - pret/pokecrystal GitHub Wiki

In RBY, GSC, and RSE, if you lost a battle you would simply lose half of your money. Starting in FRLG, you lose an amount proportional to how many badges you have and the maximum level of your party Pokémon. This tutorial ports that feature to pokecrystal.

(The code for this feature was adapted from Twitch Plays Pokémon: Anniversary Crystal.)

Contents

  1. Prepare to print how much money you lost in wild and trainer battles
  2. Save whether the battle was with a trainer or a wild Pokémon
  3. Implement the Gen 3+ money loss formula

1. Prepare to print how much money you lost in wild and trainer battles

Edit data/text/common_2.asm:

 _WhitedOutText::
 	text "<PLAYER> is out of"
 	line "useable #MON!"

 	para "<PLAYER> whited"
 	line "out!"
 	done
+
+_WhitedOutToWildMonText::
+	text "<PLAYER> is out of"
+	line "useable #MON!"
+
+	para "<PLAYER> panicked"
+	line "and dropped"
+	cont "¥@"
+	text_decimal hMoneyTemp, 3, 6
+	text "…"
+
+	para "<……><……><……>"
+	line "<……><……><……>"
+
+	para "<PLAYER> whited"
+	line "out!"
+	done
+
+_WhitedOutToTrainerText::
+	text "<PLAYER> is out of"
+	line "useable #MON!"
+
+	para "<PLAYER> paid"
+	line "¥@"
+	text_decimal hMoneyTemp, 3, 6
+	text " to the"
+	cont "winner…"
+
+	para "<……><……><……>"
+	line "<……><……><……>"
+
+	para "<PLAYER> whited"
+	line "out!"
+	done

2. Save whether the battle was with a trainer or a wild Pokémon

Edit wram.asm:

 	...
-	ds 1
+wWildBattlePanic:: db
 wWildEncounterCooldown:: db ; d452
 wXYComparePointer:: dw ; d453
 	ds 4

 wBattleScriptFlags:: dw ; d459
 	...

And edit engine/overworld/scripting.asm:

 Script_reloadmapafterbattle:
 ; script command 0x60
 
 	ld hl, wBattleScriptFlags
 	ld d, [hl]
 	ld [hl], 0
+	ld hl, wWildBattlePanic
+	ld [hl], d
 	...

We have to cache the value of [wBattleScriptFlags] in [wWildBattlePanic] since [wBattleScriptFlags] gets reset to 0 here.

3. Implement the Gen 3+ money loss formula

Edit engine/events/whiteout.asm:

 Script_Whiteout:
+	checkflag ENGINE_BUG_CONTEST_TIMER
+	iftrue .bug_contest
+	callasm LoseWhiteOutMoney
+	iffalse .plain_whiteout_text
+	callasm CheckWildBattlePanic
+	iffalse .wild_whiteout_text
+	writetext .WhitedOutToTrainerText
+	sjump .text_done
+.wild_whiteout_text
+	writetext .WhitedOutToWildMonText
+	sjump .text_done
+.plain_whiteout_text
 	writetext .WhitedOutText
+.text_done
 	waitbutton
 	special FadeOutToWhite ;older versions have FadeOutPalettes instead
 	pause 40
 	special HealParty
-	checkflag ENGINE_BUG_CONTEST_TIMER
-	iftrue .bug_contest
-	callasm HalveMoney
 	callasm GetWhiteoutSpawn
 	farscall Script_AbortBugContest
 	special WarpToSpawnPoint
 	newloadmap MAPSETUP_WARP
 	endall
 
 .bug_contest
+	writetext .WhitedOutText
+	waitbutton
+	special FadeOutToWhite ;older versions have FadeOutPalettes instead
+	pause 40
+	special HealParty
 	jumpstd BugContestResultsWarpScript
 
 .WhitedOutText:
 	; is out of useable #MON!  whited out!
 	text_far UnknownText_0x1c0a4e
 	text_end
+
+.WhitedOutToWildMonText:
+	text_far _WhitedOutToWildMonText
+	text_end
+
+.WhitedOutToTrainerText:
+	text_far _WhitedOutToTrainerText
+	text_end

Here we determine which message to print. Note that we don't lose any money during the Bug-Catching Contest.

-HalveMoney:
-	farcall StubbedTrainerRankings_WhiteOuts
-
-; Halve the player's money.
-	ld hl, wMoney
-	ld a, [hl]
-	srl a
-	ld [hli], a
-	ld a, [hl]
-	rra
-	ld [hli], a
-	ld a, [hl]
-	rra
-	ld [hl], a
-	ret
+LoseWhiteOutMoney:
+; Lose money proportional to your badges and highest-level Pokémon.
+	ld hl, wMoney
+; Check if you have any money
+	ld a, [hli]
+	or [hl]
+	inc hl
+	or [hl]
+	jr z, .done
+; Count your badges (capped at 8)
+	ld hl, wBadges
+	ld b, 2
+	call CountSetBits
+	cp 9
+	jr c, .got_badge_count
+	ld c, 8
+.got_badge_count
+; Get the payout factor for your badge count
+	ld b, 0
+	ld hl, .PayoutBadgeFactors
+	add hl, bc
+	ld a, [hl]
+	ldh [hMultiplier], a
+; Get your highest party mon level
+	ld a, [wPartyCount]
+	ld c, a
+	ld hl, wPartyMon1Level
+	ld de, PARTYMON_STRUCT_LENGTH
+.loop
+	ld a, [hl]
+	cp b
+	jr c, .next
+	ld b, a
+.next
+	add hl, de
+	dec c
+	jr nz, .loop
+; Multiply the badge factor by the max level
+	xor a
+	ldh [hMultiplicand + 0], a
+	ldh [hMultiplicand + 1], a
+	ld a, b
+	ldh [hMultiplicand + 2], a
+	call Multiply
+; Save the amount (capped at your total) in hMoneyTemp to print
+	ld de, hMoneyTemp
+	ld hl, hProduct + 1
+	ld bc, 3
+	call CopyBytes
+	ld de, wMoney
+	ld bc, hMoneyTemp
+	push bc
+	push de
+	farcall CompareMoney
+	jr nc, .not_enough
+	ld hl, wMoney
+	ld de, hMoneyTemp
+	ld bc, 3
+	call CopyBytes
+.not_enough
+	pop de
+	pop bc
+	farcall TakeMoney
+; Return TRUE in [wScriptVar] if you had any money to lose
+	ld a, TRUE
+.done
+	ld [wScriptVar], a
+	ret
+
+.PayoutBadgeFactors:
+	db   8 ; 0
+	db  16 ; 1
+	db  24 ; 2
+	db  36 ; 3
+	db  48 ; 4
+	db  64 ; 5
+	db  80 ; 6
+	db 100 ; 7
+	db 120 ; 8+
+
+CheckWildBattlePanic:
+	ld hl, wWildBattlePanic
+	ld a, [hl]
+	and 1
+	ld [wScriptVar], a
+	xor a
+	ld [hl], a
+	ret

The HalveMoney routine is completely replaced by LoseWhiteOutMoney, and we also implement CheckWildBattlePanic for use in Script_Whiteout. It makes use of various helper routines that already exist, like CountSetBits and CompareMoney, so we don't have to do everything in raw assembly instructions.

(Note that in Gen 3 and 4 the base payout for five badges was ¥60, not ¥64.)

Screenshot

⚠️ **GitHub.com Fallback** ⚠️