mirror of
https://github.com/thornAvery/kep-hack.git
synced 2025-09-17 02:40:50 +12:00

The Gift Pokemon from vanilla now use the LGPE levels, which are all far more applicable for general use. With the Move Relearner's existence, it is unnecessary to hold back their levels anymore. This most notably means the Silph Co. Lapras is now Level 34, much more appropriate for general use.
670 lines
14 KiB
NASM
670 lines
14 KiB
NASM
VermilionCity_Script:
|
|
call EnableAutoTextBoxDrawing
|
|
ld hl, wCurrentMapScriptFlags
|
|
bit 6, [hl]
|
|
res 6, [hl]
|
|
push hl
|
|
call nz, .initCityScript
|
|
pop hl
|
|
bit 5, [hl]
|
|
res 5, [hl]
|
|
call nz, .setFirstLockTrashCanIndex
|
|
ld hl, VermilionCity_ScriptPointers
|
|
ld a, [wVermilionCityCurScript]
|
|
jp CallFunctionInTable
|
|
|
|
.setFirstLockTrashCanIndex
|
|
call Random
|
|
ldh a, [hRandomSub]
|
|
and $e
|
|
ld [wFirstLockTrashCanIndex], a
|
|
ret
|
|
|
|
.initCityScript
|
|
CheckEventHL EVENT_SS_ANNE_LEFT
|
|
ret z
|
|
CheckEventReuseHL EVENT_WALKED_PAST_GUARD_AFTER_SS_ANNE_LEFT
|
|
SetEventReuseHL EVENT_WALKED_PAST_GUARD_AFTER_SS_ANNE_LEFT
|
|
ret nz
|
|
ld a, $2
|
|
ld [wVermilionCityCurScript], a
|
|
ret
|
|
|
|
VermilionCity_ScriptPointers:
|
|
dw VermilionCityScript0
|
|
dw VermilionCityScript1
|
|
dw VermilionCityScript2
|
|
dw VermilionCityScript3
|
|
dw VermilionCityScript4
|
|
|
|
VermilionCityScript0:
|
|
ld a, [wSpritePlayerStateData1FacingDirection]
|
|
and a ; cp SPRITE_FACING_DOWN
|
|
ret nz
|
|
ld hl, SSAnneTicketCheckCoords
|
|
call ArePlayerCoordsInArray
|
|
ret nc
|
|
xor a
|
|
ldh [hJoyHeld], a
|
|
ld [wcf0d], a
|
|
ld a, $3
|
|
ldh [hSpriteIndexOrTextID], a
|
|
call DisplayTextID
|
|
ld a, [wObtainedBadges] ; ship returns after obtaining the marsh badge
|
|
bit 5, a
|
|
jr nz, .default
|
|
CheckEvent EVENT_SS_ANNE_LEFT
|
|
jr nz, .shipHasDeparted
|
|
.default
|
|
ld b, S_S_TICKET
|
|
predef GetQuantityOfItemInBag
|
|
ld a, b
|
|
and a
|
|
ret nz
|
|
.shipHasDeparted
|
|
ld a, D_UP
|
|
ld [wSimulatedJoypadStatesEnd], a
|
|
ld a, $1
|
|
ld [wSimulatedJoypadStatesIndex], a
|
|
call StartSimulatingJoypadStates
|
|
ld a, $1
|
|
ld [wVermilionCityCurScript], a
|
|
ret
|
|
|
|
SSAnneTicketCheckCoords:
|
|
dbmapcoord 18, 30
|
|
db -1 ; end
|
|
|
|
VermilionCityScript4:
|
|
ld hl, SSAnneTicketCheckCoords
|
|
call ArePlayerCoordsInArray
|
|
ret c
|
|
ld a, $0
|
|
ld [wVermilionCityCurScript], a
|
|
ret
|
|
|
|
VermilionCityScript2:
|
|
ld a, $ff
|
|
ld [wJoyIgnore], a
|
|
ld a, D_UP
|
|
ld [wSimulatedJoypadStatesEnd], a
|
|
ld [wSimulatedJoypadStatesEnd + 1], a
|
|
ld a, 2
|
|
ld [wSimulatedJoypadStatesIndex], a
|
|
call StartSimulatingJoypadStates
|
|
ld a, $3
|
|
ld [wVermilionCityCurScript], a
|
|
ret
|
|
|
|
VermilionCityScript3:
|
|
ld a, [wSimulatedJoypadStatesIndex]
|
|
and a
|
|
ret nz
|
|
xor a
|
|
ld [wJoyIgnore], a
|
|
ldh [hJoyHeld], a
|
|
ld a, $0
|
|
ld [wVermilionCityCurScript], a
|
|
ret
|
|
|
|
VermilionCityScript1:
|
|
ld a, [wSimulatedJoypadStatesIndex]
|
|
and a
|
|
ret nz
|
|
ld c, 10
|
|
call DelayFrames
|
|
ld a, $0
|
|
ld [wVermilionCityCurScript], a
|
|
ret
|
|
|
|
; New Pass script begins here
|
|
VermillionCityScript_GetPassesInBag:
|
|
; Gets a list of Passes in the player's bag.
|
|
; Ripped and modified from the fossil guy
|
|
xor a
|
|
ld [wFilteredBagItemsCount], a
|
|
ld de, wFilteredBagItems
|
|
ld hl, PassList
|
|
.loop
|
|
ld a, [hli]
|
|
and a
|
|
jr z, .done
|
|
push hl
|
|
push de
|
|
ld [wd11e], a
|
|
ld b, a
|
|
predef GetQuantityOfItemInBag
|
|
pop de
|
|
pop hl
|
|
ld a, b
|
|
and a
|
|
jr z, .loop
|
|
|
|
; A Pass is in the bag
|
|
ld a, [wd11e]
|
|
ld [de], a
|
|
inc de
|
|
push hl
|
|
ld hl, wFilteredBagItemsCount
|
|
inc [hl]
|
|
pop hl
|
|
jr .loop
|
|
.done
|
|
ld a, $ff
|
|
ld [de], a
|
|
ret
|
|
|
|
PassList:
|
|
db S_S_TICKET
|
|
db OLD_SEA_MAP
|
|
db CITRINE_PASS
|
|
;db RAINBOW_PASS maybe someday
|
|
db 0 ; end
|
|
|
|
PrintPassesInBag:
|
|
; Prints each pass in the player's bag on a separate line in the menu.
|
|
ld hl, wFilteredBagItems
|
|
xor a
|
|
ldh [hItemCounter], a
|
|
.loop
|
|
ld a, [hli]
|
|
cp $ff
|
|
ret z
|
|
push hl
|
|
ld [wd11e], a
|
|
call GetItemName
|
|
hlcoord 2, 2
|
|
ldh a, [hItemCounter]
|
|
ld bc, SCREEN_WIDTH * 2
|
|
call AddNTimes
|
|
ld de, wcd6d
|
|
call PlaceString
|
|
ld hl, hItemCounter
|
|
inc [hl]
|
|
pop hl
|
|
jr .loop
|
|
|
|
PassListings:
|
|
ld hl, VermillionCityPassSelectionText
|
|
call PrintText
|
|
call VermillionCityScript_GetPassesInBag
|
|
ld hl, wd730
|
|
set 6, [hl]
|
|
xor a
|
|
ld [wCurrentMenuItem], a
|
|
ld a, A_BUTTON | B_BUTTON
|
|
ld [wMenuWatchedKeys], a
|
|
ld a, [wFilteredBagItemsCount]
|
|
dec a
|
|
ld [wMaxMenuItem], a
|
|
ld a, 2
|
|
ld [wTopMenuItemY], a
|
|
ld a, 1
|
|
ld [wTopMenuItemX], a
|
|
ld a, [wFilteredBagItemsCount]
|
|
dec a
|
|
ld bc, 2
|
|
ld hl, 3
|
|
call AddNTimes
|
|
dec l
|
|
ld b, l
|
|
ld c, $d
|
|
hlcoord 0, 0
|
|
call TextBoxBorder
|
|
call UpdateSprites
|
|
call PrintPassesInBag
|
|
ld hl, wd730
|
|
res 6, [hl]
|
|
call HandleMenuInput
|
|
bit BIT_B_BUTTON, a
|
|
jr nz, .cancelledPass
|
|
ld hl, wFilteredBagItems
|
|
ld a, [wCurrentMenuItem]
|
|
ld d, 0
|
|
ld e, a
|
|
add hl, de
|
|
ld a, [hl]
|
|
ldh [hItemToRemoveID], a
|
|
cp S_S_TICKET
|
|
jr z, .choseSSAnne
|
|
cp OLD_SEA_MAP
|
|
jr z, .choseFaraway
|
|
cp CITRINE_PASS
|
|
jr z, .choseCitrine
|
|
; god bless the safari game and pokemon tower 7f for being the few times a forcewarp exists
|
|
; For some reason, these aren't working properly...
|
|
.choseSSAnne
|
|
jp VermilionCityText3.playerHasTicket ; Saves time and less risk of bugs
|
|
.choseFaraway
|
|
ld hl, EventVermillionCityOldSeaMap
|
|
call PrintText
|
|
ld a, FARAWAY_ISLAND_OUTSIDE
|
|
ldh [hWarpDestinationMap], a
|
|
ld a, $1
|
|
ld [wDestinationWarpID], a
|
|
call WarpFound2
|
|
jr .done
|
|
.choseCitrine
|
|
ld hl, EventVermillionCityCitrinePass
|
|
call PrintText
|
|
ld a, CITRINE_CITY
|
|
ldh [hWarpDestinationMap], a
|
|
ld a, $6
|
|
ld [wDestinationWarpID], a
|
|
call WarpFound2
|
|
jr .done
|
|
.cancelledPass
|
|
ld hl, PassRefuse
|
|
call PrintText
|
|
.done
|
|
ret
|
|
|
|
VermilionCity_TextPointers:
|
|
dw VermilionCityText1
|
|
dw VermilionCityText2
|
|
dw VermilionCityText3
|
|
dw VermilionCityText4
|
|
dw VermilionCityText5
|
|
dw VermilionCityText6
|
|
dw OfficerJennySquirtle
|
|
dw VermilionBeauty
|
|
dw VermilionCityText7
|
|
dw VermilionCityText8
|
|
dw MartSignText
|
|
dw PokeCenterSignText
|
|
dw VermilionCityText11
|
|
dw VermilionCityText12
|
|
dw VermilionCityText13
|
|
|
|
VermilionCityText1:
|
|
text_far _VermilionCityText1
|
|
text_end
|
|
|
|
VermilionCityText2:
|
|
text_asm
|
|
CheckEvent EVENT_SS_ANNE_LEFT
|
|
jr nz, .shipHasDeparted
|
|
ld hl, VermilionCityTextDidYouSee
|
|
call PrintText
|
|
jr .end
|
|
.shipHasDeparted
|
|
ld hl, VermilionCityTextSSAnneDeparted
|
|
call PrintText
|
|
.end
|
|
jp TextScriptEnd
|
|
|
|
VermilionCityTextDidYouSee:
|
|
text_far _VermilionCityTextDidYouSee
|
|
text_end
|
|
|
|
VermilionCityTextSSAnneDeparted:
|
|
text_far _VermilionCityTextSSAnneDeparted
|
|
text_end
|
|
|
|
VermilionCityText3:
|
|
text_asm
|
|
|
|
; If you have either of these, go to Pass List.
|
|
; You only access these in the post-game, really, so it works out.
|
|
ld b, OLD_SEA_MAP
|
|
predef GetQuantityOfItemInBag
|
|
ld a, b
|
|
and a
|
|
jp nz, PassListings
|
|
ld b, CITRINE_PASS
|
|
predef GetQuantityOfItemInBag
|
|
ld a, b
|
|
and a
|
|
jp nz, PassListings
|
|
|
|
ld a, [wObtainedBadges]
|
|
bit 5, a ; after obtaining marsh badge the ship returns
|
|
jr nz, .default
|
|
CheckEvent EVENT_SS_ANNE_LEFT
|
|
jr nz, .shipHasDeparted
|
|
.default
|
|
ld a, [wSpritePlayerStateData1FacingDirection]
|
|
cp SPRITE_FACING_RIGHT
|
|
jr z, .greetPlayer
|
|
ld hl, .inFrontOfOrBehindGuardCoords
|
|
call ArePlayerCoordsInArray
|
|
jr nc, .greetPlayerAndCheckTicket
|
|
.greetPlayer
|
|
ld hl, SSAnneWelcomeText4
|
|
call PrintText
|
|
jr .end
|
|
.greetPlayerAndCheckTicket
|
|
ld hl, SSAnneWelcomeText9
|
|
call PrintText
|
|
ld b, S_S_TICKET
|
|
predef GetQuantityOfItemInBag
|
|
ld a, b
|
|
and a
|
|
jr nz, .playerHasTicket
|
|
ld hl, SSAnneNoTicketText
|
|
call PrintText
|
|
jr .end
|
|
.playerHasTicket
|
|
ld hl, SSAnneFlashedTicketText
|
|
call PrintText
|
|
ld a, $4
|
|
ld [wVermilionCityCurScript], a
|
|
jr .end
|
|
.shipHasDeparted
|
|
ld hl, SSAnneNotHereText
|
|
call PrintText
|
|
.end
|
|
jp TextScriptEnd
|
|
|
|
.inFrontOfOrBehindGuardCoords
|
|
dbmapcoord 19, 29 ; in front of guard
|
|
dbmapcoord 19, 31 ; behind guard
|
|
db -1 ; end
|
|
|
|
SSAnneWelcomeText4:
|
|
text_far _SSAnneWelcomeText4
|
|
text_end
|
|
|
|
SSAnneWelcomeText9:
|
|
text_far _SSAnneWelcomeText9
|
|
text_end
|
|
|
|
SSAnneFlashedTicketText:
|
|
text_far _SSAnneFlashedTicketText
|
|
text_end
|
|
|
|
SSAnneNoTicketText:
|
|
text_far _SSAnneNoTicketText
|
|
text_end
|
|
|
|
SSAnneNotHereText:
|
|
text_far _SSAnneNotHereText
|
|
text_end
|
|
|
|
VermilionCityText4:
|
|
text_far _VermilionCityText4
|
|
text_end
|
|
|
|
VermilionCityText5:
|
|
text_far _VermilionCityText5
|
|
text_asm
|
|
ld a, MACHOP
|
|
call PlayCry
|
|
call WaitForSoundToFinish
|
|
ld hl, VermilionCityText14
|
|
ret
|
|
|
|
VermilionCityText14:
|
|
text_far _VermilionCityText14
|
|
text_end
|
|
|
|
VermilionCityText6:
|
|
text_asm
|
|
ld a, [wObtainedBadges]
|
|
bit 5, a ; after obtaining the marsh badge the ship returns
|
|
jr z, .default
|
|
ld hl, VermilionCityText15
|
|
ret
|
|
.default
|
|
ld hl, VermilionCityText6get
|
|
ret
|
|
|
|
VermilionCityText6get:
|
|
text_far _VermilionCityText6
|
|
text_end
|
|
|
|
VermilionCityText15:
|
|
text_far _VermilionCityText15
|
|
text_end
|
|
|
|
VermilionCityText7:
|
|
text_far _VermilionCityText7
|
|
text_end
|
|
|
|
VermilionCityText8:
|
|
text_far _VermilionCityText8
|
|
text_end
|
|
|
|
VermilionCityText11:
|
|
text_far _VermilionCityText11
|
|
text_end
|
|
|
|
VermilionCityText12:
|
|
text_far _VermilionCityText12
|
|
text_end
|
|
|
|
VermilionCityText13:
|
|
text_far _VermilionCityText13
|
|
text_end
|
|
|
|
OfficerJennySquirtle:
|
|
text_asm
|
|
CheckEvent EVENT_GOT_SQUIRTLE
|
|
jr nz, .howDoing
|
|
ld a, [wObtainedBadges]
|
|
bit 3, a ; THUNDERBADGE
|
|
jr z, .noBadge
|
|
ld hl, OfficerJennyHasBadge
|
|
call PrintText
|
|
call YesNoChoice
|
|
ld a, [wCurrentMenuItem]
|
|
and a
|
|
jr nz, .refuse
|
|
ld a, SQUIRTLE
|
|
ld [wd11e], a
|
|
ld [wcf91], a
|
|
call GetMonName
|
|
ld a, $1
|
|
ld [wDoNotWaitForButtonPressAfterDisplayingText], a
|
|
lb bc, SQUIRTLE, 16
|
|
call GivePokemon
|
|
ld a, [wAddedToParty]
|
|
and a
|
|
call z, WaitForTextScrollButtonPress
|
|
ld a, $1
|
|
ld [wDoNotWaitForButtonPressAfterDisplayingText], a
|
|
ld hl, OfficerJennyGive
|
|
call PrintText
|
|
SetEvent EVENT_GOT_SQUIRTLE
|
|
jp TextScriptEnd
|
|
|
|
.howDoing
|
|
ld hl, OfficerJennyHowDoing
|
|
jr .done
|
|
.noBadge
|
|
ld hl, OfficerJennyNoBadge
|
|
jr .done
|
|
.refuse
|
|
ld hl, OfficerJennyRefuse
|
|
; fallthrough
|
|
.done
|
|
call PrintText
|
|
jp TextScriptEnd
|
|
|
|
OfficerJennyNoBadge:
|
|
text_far _OfficerJennyText1
|
|
text_end
|
|
|
|
OfficerJennyHasBadge:
|
|
text_far _OfficerJennyText2
|
|
text_end
|
|
|
|
OfficerJennyGive:
|
|
text_far _OfficerJennyText3
|
|
text_waitbutton
|
|
text_end
|
|
|
|
OfficerJennyRefuse:
|
|
text_far _OfficerJennyText4
|
|
text_end
|
|
|
|
OfficerJennyHowDoing:
|
|
text_far _OfficerJennyText5
|
|
text_end
|
|
|
|
VermillionCityPassSelectionText:
|
|
text_far _VermillionCityPassSelectionText
|
|
text_end
|
|
|
|
EventVermillionCityOldSeaMap:
|
|
text_far _VermillionCityOldSeaMap
|
|
text_end
|
|
|
|
EventVermillionCityCitrinePass:
|
|
text_far _VermillionCityCitrinePass
|
|
text_end
|
|
|
|
EventVermillionCitySSTicket:
|
|
text_far _SSAnneFlashedTicketText
|
|
text_end
|
|
|
|
PassRefuse:
|
|
text_far _VermillionCityHarborRefuse
|
|
text_end
|
|
|
|
; LGPE Beauty who gives you a Persian or Arcanine depending on the game.
|
|
; Here, we make it a Cats vs Dogs question and change based on that.
|
|
; The way it works is it makes the player catch the opposite Pokemon, and then get the one they picked.
|
|
; Meowth = Arcanine
|
|
; Growlithe = Persian
|
|
; This code is nightmare fuel but it does the job.
|
|
; Basically, at some point, wBeautyChoice stops working for reasons scientists are still trying to figure out.
|
|
VermilionBeauty:
|
|
text_asm
|
|
|
|
CheckEvent EVENT_VERMILION_BEAUTY_DONE ; First, check if the event is actually done.
|
|
jp nz, .beautyDone ; Yes? Alright, no need for this.
|
|
|
|
ld a, [wBeautyChoice] ; Next, we check if wBeautyChoice has been set. This saves an event constant.
|
|
cp 0 ; It will never be 0 if the player has made their choice.
|
|
jr z, .eventStart ; If it is, then the event needs to start.
|
|
|
|
; We need to do 2 skips here which triggers me but it works.
|
|
; You could put the finish check before the choice check, but then it gets a little weird.
|
|
; All it really achieves is weird architecture for like 3-4 less machine cycles.
|
|
ld a, [wBeautyCounter] ; Alright, if you got here, then the event is in progress.
|
|
cp 5 ; Do you have 5 of the scrunklies?
|
|
jr z, .eventIsFinished ; Big if true.
|
|
jr nz, .eventInProgress ; Small if false.
|
|
|
|
; Let us start the game.
|
|
.eventStart
|
|
ld hl, BeautyText1 ; Let's open the text.
|
|
call PrintText
|
|
call CatsDogsChoice
|
|
ld a, [wCurrentMenuItem] ; Let's load what they picked. 0 is cats, 1 is dogs.
|
|
and a
|
|
jr nz, .getArcanine ; Skip storing Growlithe if dogs.
|
|
ld a, GROWLITHE ; If they picked cats, then store Growlithe.
|
|
jr .skip ; I know this looks bad, but if it isn't here, it'd store Growlithe and then go to Meowth anyway.
|
|
.getArcanine ; If they get here, they picked dogs, so we store Meowth.
|
|
ld a, MEOWTH
|
|
.skip ; Now we land here.
|
|
ld [wBeautyChoice], a ; Finally store the choice in wBeautyChoice.
|
|
ld hl, BeautyText2 ; Now spit it out.
|
|
call PrintText
|
|
|
|
; This is a jump point for if the event was already started.
|
|
.eventInProgress
|
|
ld a, [wBeautyChoice]
|
|
ld [wd11e], a
|
|
call GetMonName
|
|
ld hl, BeautyChoice
|
|
call PrintText
|
|
jr .done ; no give pokemon. bad.
|
|
|
|
; Now if the event is finished, she needs to hand the Pokemon over.
|
|
.eventIsFinished
|
|
call SaveScreenTilesToBuffer1 ; saves us from some corruption disasters if nicknaming.
|
|
ld hl, BeautyFinish1
|
|
ld a, [wBeautyChoice]
|
|
cp GROWLITHE
|
|
jr z, .skip2
|
|
ld hl, BeautyFinish2
|
|
.skip2
|
|
call PrintText
|
|
ld a, [wSimulatedJoypadStatesEnd] ; ensuring that the text doesn't autoskip.
|
|
and a ; yep, here too.
|
|
call z, WaitForTextScrollButtonPress ; and here.
|
|
call EnableAutoTextBoxDrawing ; and here. GivePokemon is very hasty.
|
|
lb bc, PERSIAN, 16 ; because we're elitists, let's see if they chose cats first.
|
|
ld a, [wBeautyChoice] ; *sigh*, but if they're dog lovers, let's make sure they actually want Persian.
|
|
cp GROWLITHE ; Do they? If yes, skip.
|
|
jr z, .skip3 ; electric boogaloo
|
|
lb bc, ARCANINE, 16 ; ok but skip2 means arc never gets loaded in. very good sequel. disney would NEVER.
|
|
.skip3
|
|
call GivePokemon
|
|
jr nc, .done
|
|
call LoadScreenTilesFromBuffer1 ; saves us from some corruption disasters if nicknaming.
|
|
SetEvent EVENT_VERMILION_BEAUTY_DONE ; and now we can finally rest.
|
|
ld hl, wd72e
|
|
set 0, [hl]
|
|
jr .done
|
|
|
|
; Now if it's already been said and done, we go here.
|
|
; Due to man-made horrors beyond my comprehension, we need to split the text here.
|
|
.beautyDone
|
|
ld hl, BeautyExplain1
|
|
ld a, [wBeautyChoice]
|
|
cp GROWLITHE
|
|
jr z, .skip4
|
|
ld hl, BeautyExplain2
|
|
.skip4
|
|
call PrintText
|
|
ld hl, BeautyExplainCont
|
|
call PrintText
|
|
;fallthrough
|
|
.done
|
|
jp TextScriptEnd
|
|
|
|
; displays cats/dogs choice
|
|
CatsDogsChoice:
|
|
call SaveScreenTilesToBuffer1
|
|
call InitCatsDogsTextBoxParameters
|
|
jr DisplayCatsDogsChoice
|
|
|
|
InitCatsDogsTextBoxParameters:
|
|
ld a, $2 ; loads the value for the unused SOUTH/EAST choice, that was changed to say CATS/DOGS
|
|
ld [wTwoOptionMenuID], a
|
|
hlcoord 12, 8
|
|
lb bc, 10, 13
|
|
ret
|
|
|
|
DisplayCatsDogsChoice:
|
|
ld a, $14
|
|
ld [wTextBoxID], a
|
|
call DisplayTextBoxID
|
|
jp LoadScreenTilesFromBuffer1
|
|
|
|
BeautyText1:
|
|
text_far _BeautyText1
|
|
text_end
|
|
|
|
BeautyText2:
|
|
text_far _BeautyText2
|
|
text_end
|
|
|
|
BeautyChoice:
|
|
text_far _BeautyChoice
|
|
text_end
|
|
|
|
BeautyFinish1:
|
|
text_far _BeautyFinish1
|
|
text_end
|
|
|
|
BeautyFinish2:
|
|
text_far _BeautyFinish2
|
|
text_end
|
|
|
|
BeautyExplain1:
|
|
text_far _BeautyExplain1
|
|
text_end
|
|
|
|
BeautyExplain2:
|
|
text_far _BeautyExplain2
|
|
text_end
|
|
|
|
BeautyExplainCont:
|
|
text_far _BeautyExplainCont
|
|
text_end
|