Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add B_FLAG_SLEEP_CLAUSE #5566

Open
wants to merge 65 commits into
base: upcoming
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
8e2c56d
Sleep Clause sleep prevention
Pawkkie Jul 14, 2024
00df583
add one test case and several TODO battle tests
iriv24 Jul 14, 2024
0b59b17
Merge pull request #1 from iriv24/more-sleep-clause
Pawkkie Aug 5, 2024
81dd174
Merge remote-tracking branch 'upstream' into sleep-clause
Pawkkie Aug 5, 2024
521ad97
add some wake up and edge case handling
iriv24 Oct 4, 2024
fb1267e
rename to isMonCausingSleepClause, handle if sleeping mon faints
iriv24 Oct 4, 2024
b2266d7
rename to isCausingSleepClause, hopefully last rename. add some comme…
iriv24 Oct 4, 2024
403e12a
handle sleep clause being disabled when awoken by item usage
iriv24 Oct 6, 2024
42bc12a
handle deactivating sleep clause when being awoken by a held item
iriv24 Oct 6, 2024
64ab52f
add handling for shed skin and hydration
iriv24 Oct 6, 2024
fad1ce5
add handling for gaining insomnia/vital spirit, wake up slap, uproar,…
iriv24 Oct 19, 2024
5e26d03
add handling for healer, natural cure, working on heal bell
iriv24 Oct 20, 2024
bc8120f
add handling for psycho shift and healbell/aromatherapy
iriv24 Oct 21, 2024
272533d
Add TODO AI test
Pawkkie Oct 21, 2024
a0a13ec
First batch of tests
Pawkkie Oct 21, 2024
e762c0a
TODO test name cleanup
Pawkkie Oct 21, 2024
eeb4543
More tests
Pawkkie Oct 22, 2024
6d04533
More tests
Pawkkie Oct 22, 2024
aa01ba9
Vital Spirit / Insomnia tests
Pawkkie Oct 22, 2024
1608701
Comment cleanup
Pawkkie Oct 22, 2024
ed0d851
Assumes and final tests
Pawkkie Oct 22, 2024
a98e2bd
Last KNOWN_FAILING
Pawkkie Oct 22, 2024
954f411
Merge pull request #2 from Pawkkie/sleep-clause-tests
iriv24 Oct 22, 2024
3c48bca
Merge pull request #5 from iriv24/even-more-sleep-clause
Pawkkie Oct 22, 2024
4550ef5
Merge remote-tracking branch 'upstream/upcoming' into sleep-clause
Pawkkie Oct 22, 2024
7110f89
Merge fixes
Pawkkie Oct 22, 2024
538712a
Sparkly Swirl test
Pawkkie Oct 22, 2024
0e5aaa8
Link issues to known failings
Pawkkie Oct 22, 2024
c7379dc
Switch to using B_FLAG_SLEEP_CLAUSE
Pawkkie Oct 22, 2024
d07b7ac
Merge remote-tracking branch 'upstream/upcoming' into sleep-clause
Pawkkie Oct 22, 2024
e1cf7fa
Merge remote-tracking branch 'upstream/upcoming' into sleep-clause
Pawkkie Oct 22, 2024
7f137dd
Remove Healer KNOWN_FAILING
Pawkkie Oct 22, 2024
3ab9192
initial pass at sleep clause cleanup
iriv24 Oct 22, 2024
0ae4f8f
Extend Heal Bell test to both slots
Pawkkie Oct 22, 2024
9890359
Merge branch 'sleep-clause' of https://github.com/Pawkkie/pokeemerald…
iriv24 Oct 22, 2024
d062a97
more clean up, add code comments for documentation
iriv24 Oct 23, 2024
c7db719
switch to using bitfield for isCausingSleepClause which also allows i…
iriv24 Oct 23, 2024
449b1a9
Merge pull request #7 from iriv24/sleep-clause-cleanup1
Pawkkie Oct 23, 2024
389490c
Lum Berry test
Pawkkie Oct 23, 2024
bce0bcd
psf's suggested doubles tests
Pawkkie Oct 23, 2024
b04157a
Fix spacing
Pawkkie Oct 23, 2024
7e833d5
Pre-existing sleep test
Pawkkie Oct 23, 2024
d04dbcb
Broken case
Pawkkie Oct 23, 2024
681d8e8
LET IT FAIL
Pawkkie Oct 23, 2024
c33b98b
Fix Effect Spore, more tests
Pawkkie Oct 24, 2024
5ee1117
Merge remote-tracking branch 'upstream/upcoming' into sleep-clause
Pawkkie Oct 24, 2024
2ea4fe1
Update Shed Skin test
Pawkkie Oct 24, 2024
31b18e5
stop using bitfield, add some documentation comments
iriv24 Oct 24, 2024
b65e252
Last missing Effect Spore / Rest tests
Pawkkie Oct 24, 2024
c169f45
Yawn tests
Pawkkie Oct 25, 2024
a82c2a7
yawn fix with comment
iriv24 Oct 25, 2024
ba0640a
Fling, reflection, partner targeting tests
Pawkkie Oct 25, 2024
d787ead
Merge branch 'sleep-clause' of https://github.com/Pawkkie/pokeemerald…
Pawkkie Oct 25, 2024
1773540
Encore and AI doubles tests
Pawkkie Oct 25, 2024
bab4013
Change comment
Pawkkie Oct 25, 2024
bcd0f3f
Fix AI targeting its own partner with sleep effects
Pawkkie Oct 25, 2024
3c4e2e3
Fix partner sleep effect fix
Pawkkie Oct 25, 2024
2d2840e
Fix partner sleep Yawn
Pawkkie Oct 25, 2024
c215d31
add message for when sleep clause blocks sleep
iriv24 Oct 25, 2024
d970587
Remove struct and use BattleStruct
Pawkkie Oct 25, 2024
2431ccb
add effect exempt for falling asleep due to disobedience
iriv24 Oct 26, 2024
8964cf9
Fix Yawn'ing partner bugs
Pawkkie Oct 27, 2024
f592e44
rename IsSleepClauseTriggeringEffect to IsEffectBlockedBySleepClause,…
iriv24 Oct 28, 2024
bc182f0
Move doubles AI to Check Bad Move
Pawkkie Oct 29, 2024
114515d
Confirmed that this was the appropriate course of action
Pawkkie Oct 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion asm/macros/battle_script.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1669,6 +1669,12 @@
callnative BS_DamageToQuarterTargetHP
.endm

.macro jumpifsleepclause battler:req, jumpInstr:req
callnative BS_JumpIfSleepClause
.byte \battler
.4byte \jumpInstr
.endm

.macro ficklebeamdamagecalculation
callnative BS_FickleBeamDamageCalculation
.endm
Expand Down Expand Up @@ -1993,9 +1999,10 @@
.4byte \jumpInstr
.endm

.macro trypsychoshift failInstr:req
.macro trypsychoshift failInstr:req sleepClauseFailInstr:req
various BS_ATTACKER, VARIOUS_PSYCHO_SHIFT
.4byte \failInstr
.4byte \sleepClauseFailInstr
.endm

.macro curestatus battler:req
Expand Down
17 changes: 16 additions & 1 deletion data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -1639,7 +1639,7 @@ BattleScript_EffectPsychoShift::
BattleScript_EffectPsychoShiftCanWork:
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
jumpifsafeguard BattleScript_SafeguardProtected
trypsychoshift BattleScript_ButItFailed
trypsychoshift BattleScript_ButItFailed, BattleScript_SleepClauseBlocked
attackanimation
waitanimation
copybyte gEffectBattler, gBattlerTarget
Expand Down Expand Up @@ -2893,6 +2893,7 @@ BattleScript_EffectSleep::
jumpifleafguardprotected BS_TARGET, BattleScript_AbilityProtectsDoesntAffect
jumpifshieldsdown BS_TARGET, BattleScript_AbilityProtectsDoesntAffect
jumpifstatus BS_TARGET, STATUS1_ANY, BattleScript_ButItFailed
jumpifsleepclause BS_TARGET, BattleScript_SleepClauseBlocked
jumpifterrainaffected BS_TARGET, STATUS_FIELD_ELECTRIC_TERRAIN, BattleScript_ElectricTerrainPrevents
jumpifterrainaffected BS_TARGET, STATUS_FIELD_MISTY_TERRAIN, BattleScript_MistyTerrainPrevents
accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE
Expand Down Expand Up @@ -5154,6 +5155,7 @@ BattleScript_EffectYawn::
jumpifflowerveil BattleScript_FlowerVeilProtects
jumpifleafguardprotected BS_TARGET, BattleScript_AbilityProtectsDoesntAffect
jumpifshieldsdown BS_TARGET, BattleScript_AbilityProtectsDoesntAffect
jumpifsleepclause BS_TARGET, BattleScript_SleepClauseBlocked
jumpifsubstituteblocks BattleScript_ButItFailed
jumpifsafeguard BattleScript_SafeguardProtected
accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON
Expand Down Expand Up @@ -10098,3 +10100,16 @@ BattleScript_EffectSnow::
call BattleScript_CheckPrimalWeather
setfieldweather ENUM_WEATHER_SNOW
goto BattleScript_MoveWeatherChange

BattleScript_SleepClauseBlocked::
pause B_WAIT_TIME_SHORT
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
printstring STRINGID_BLOCKEDBYSLEEPCLAUSE
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd

BattleScript_SleepClausePreventsEnd::
pause B_WAIT_TIME_SHORT
printstring STRINGID_BLOCKEDBYSLEEPCLAUSE
waitmessage B_WAIT_TIME_LONG
end2
2 changes: 2 additions & 0 deletions include/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,8 @@ struct BattleStruct
u8 padding:4;
u8 usedEjectItem;
u8 usedMicleBerry;
u8 monCausingSleepClause[NUM_BATTLE_SIDES]; // Stores which pokemon on a given side is causing Sleep Clause to be active as the mon's index in the party
u8 sleepClauseEffectExempt[MAX_BATTLERS_COUNT]; // Stores whether effect should be exempt from triggering Sleep Clause (Effect Spore)
};

// The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider,
Expand Down
1 change: 1 addition & 0 deletions include/battle_ai_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove);
bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck);
bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove);
bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove);
bool32 PartnerMoveActivatesSleepClause(u32 move);
bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u32 move);

// party logic
Expand Down
1 change: 1 addition & 0 deletions include/battle_scripts.h
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ extern const u8 BattleScript_Terastallization[];
extern const u8 BattleScript_BoosterEnergyEnd2[];
extern const u8 BattleScript_TeraShellDistortingTypeMatchups[];
extern const u8 BattleScript_TeraFormChange[];
extern const u8 BattleScript_SleepClausePreventsEnd[];

// zmoves
extern const u8 BattleScript_ZMoveActivateDamaging[];
Expand Down
5 changes: 4 additions & 1 deletion include/battle_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ bool32 MoveHasChargeTurnAdditionalEffect(u32 move);
bool32 CanTargetPartner(u32 battlerAtk, u32 battlerDef);
bool32 TargetFullyImmuneToCurrMove(u32 battlerAtk, u32 battlerDef);

bool32 CanBeSlept(u32 battler, u32 ability);
bool32 CanBeSlept(u32 battler, u32 ability, u32 isBlockedBySleepClause);
bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 defAbility);
bool32 CanBeBurned(u32 battler, u32 ability);
bool32 CanBeParalyzed(u32 battler, u32 ability);
Expand All @@ -300,5 +300,8 @@ bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon);
bool8 IsMonBannedFromSkyBattles(u16 species);
void RemoveBattlerType(u32 battler, u8 type);
u32 GetMoveType(u32 move);
void TryActivateSleepClause(u32 battler, u32 indexInParty);
void TryDeactivateSleepClause(u32 battlerSide, u32 indexInParty);
bool8 IsSleepClauseActiveForSide(u32 battlerSide);

#endif // GUARD_BATTLE_UTIL_H
1 change: 1 addition & 0 deletions include/config/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@
#define B_FLAG_DYNAMAX_BATTLE 0 // If this flag is set, the ability to Dynamax in battle is enabled for all trainers.
#define B_FLAG_TERA_ORB_CHARGED 0 // If this flag is set, the Tera Orb is charged. It is automatically set upon healing and cleared upon Terastallizing once configured.
#define B_FLAG_TERA_ORB_NO_COST 0 // If this flag is set, the Tera Orb does not use up its charge upon Terastallization. In S/V, this occurs after an event with Terapagos.
#define B_FLAG_SLEEP_CLAUSE 0 // If this flag is set, sleep clause is enabled; if the player / AI has already put a Pokémon on the opponent's side to sleep and it is still sleeping, another one can't be put to sleep. AI requires AI_FLAG_CHECK_BAD_MOVE to understand.

// Var Settings
// To use the following features in scripting, replace the 0s with the var ID you're assigning it to.
Expand Down
4 changes: 4 additions & 0 deletions include/config/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -1129,4 +1129,8 @@
#undef P_FAMILY_PECHARUNT
#define P_FAMILY_PECHARUNT TRUE

// Flags
#undef B_FLAG_SLEEP_CLAUSE
#define B_FLAG_SLEEP_CLAUSE FLAG_SPECIAL_FLAG_UNUSED_0x4003

#endif // GUARD_CONFIG_TEST_H
3 changes: 2 additions & 1 deletion include/constants/battle_string_ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -724,8 +724,9 @@
#define STRINGID_ELECTRICCURRENTISRUNNING 722
#define STRINGID_SEEMSWEIRD 723
#define STRINGID_WAGGLINGAFINGER 724
#define STRINGID_BLOCKEDBYSLEEPCLAUSE 725

#define BATTLESTRINGS_COUNT 725
#define BATTLESTRINGS_COUNT 726

// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,
Expand Down
10 changes: 7 additions & 3 deletions src/battle_ai_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_SLEEP:
if (!AI_CanPutToSleep(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, aiData->partnerMove))
ADJUST_SCORE(-10);
if (PartnerMoveActivatesSleepClause(aiData->partnerMove))
ADJUST_SCORE(-20);
break;
case EFFECT_EXPLOSION:
if (!(AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_WILL_SUICIDE))
Expand Down Expand Up @@ -1807,7 +1809,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
ADJUST_SCORE(-10);
break;
case EFFECT_REST:
if (!CanBeSlept(battlerAtk, aiData->abilities[battlerAtk]))
if (!CanBeSlept(battlerAtk, aiData->abilities[battlerAtk], FALSE))
ADJUST_SCORE(-10);
//fallthrough
case EFFECT_RESTORE_HP:
Expand Down Expand Up @@ -2090,6 +2092,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
ADJUST_SCORE(-10);
else if (!AI_CanPutToSleep(battlerAtk, battlerDef, aiData->abilities[battlerDef], move, aiData->partnerMove))
ADJUST_SCORE(-10);
if (PartnerMoveActivatesSleepClause(aiData->partnerMove))
ADJUST_SCORE(-20);
break;
case EFFECT_SKILL_SWAP:
if (aiData->abilities[battlerAtk] == ABILITY_NONE || aiData->abilities[battlerDef] == ABILITY_NONE
Expand Down Expand Up @@ -2692,7 +2696,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
if (IsMoveEffectWeather(move))
ADJUST_SCORE(-10);
break;
}
}
} // check partner move effect

// Adjust for always crit moves
Expand Down Expand Up @@ -3470,7 +3474,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move)
}
break;
case EFFECT_REST:
if (!(CanBeSlept(battlerAtk, aiData->abilities[battlerAtk])))
if (!(CanBeSlept(battlerAtk, aiData->abilities[battlerAtk], FALSE)))
{
break;
}
Expand Down
2 changes: 1 addition & 1 deletion src/battle_ai_switch_items.c
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ static bool32 ShouldSwitchIfGameStatePrompt(u32 battler, bool32 emitResult)
{
//Yawn
if (gStatuses3[battler] & STATUS3_YAWN
&& CanBeSlept(battler, monAbility)
&& CanBeSlept(battler, monAbility, TRUE)
&& gBattleMons[battler].hp > gBattleMons[battler].maxHP / 3)
{
switchMon = TRUE;
Expand Down
13 changes: 12 additions & 1 deletion src/battle_ai_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -2859,7 +2859,7 @@ bool32 IsBattlerIncapacitated(u32 battler, u32 ability)

bool32 AI_CanPutToSleep(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 move, u32 partnerMove)
{
if (!CanBeSlept(battlerDef, defAbility)
if (!CanBeSlept(battlerDef, defAbility, TRUE)
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|| PartnerMoveEffectIsStatusSameTarget(BATTLE_PARTNER(battlerAtk), battlerDef, partnerMove)) // shouldn't try to sleep mon that partner is trying to make sleep
return FALSE;
Expand Down Expand Up @@ -3352,6 +3352,17 @@ bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMov
return FALSE;
}

bool32 PartnerMoveActivatesSleepClause(u32 partnerMove)
{
u32 effect = gMovesInfo[partnerMove].effect;
if (!IsDoubleBattle() || !FlagGet(B_FLAG_SLEEP_CLAUSE))
return FALSE;
if (effect == EFFECT_SLEEP
|| effect == EFFECT_YAWN)
return TRUE;
return FALSE;
}

bool32 ShouldUseWishAromatherapy(u32 battlerAtk, u32 battlerDef, u32 move)
{
u32 i;
Expand Down
7 changes: 5 additions & 2 deletions src/battle_dynamax.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ void BS_SetMaxMoveEffect(void)
{
static const u8 sSnoozeEffects[] = {TRUE, FALSE};
if (!(gStatuses3[gBattlerTarget] & STATUS3_YAWN)
&& CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget))
&& CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget), TRUE)
&& RandomElement(RNG_G_MAX_SNOOZE, sSnoozeEffects)) // 50% chance of success
{
gStatuses3[gBattlerTarget] |= STATUS3_YAWN_TURN(2);
Expand Down Expand Up @@ -884,12 +884,15 @@ void BS_TrySetStatus1(void)
}
break;
case STATUS1_SLEEP:
if (CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget)))
if (CanBeSlept(gBattlerTarget, GetBattlerAbility(gBattlerTarget), TRUE))
{
if (B_SLEEP_TURNS >= GEN_5)
gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 3) + 2);
else
gBattleMons[gBattlerTarget].status1 |= STATUS1_SLEEP_TURN((Random() % 4) + 3);

// Try to activate Sleep Clause when a mon is put to Sleep
TryActivateSleepClause(gBattlerTarget, gBattlerPartyIndexes[gBattlerTarget]);
gBattleCommunication[MULTISTRING_CHOOSER] = 4;
effect++;
}
Expand Down
7 changes: 7 additions & 0 deletions src/battle_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3129,6 +3129,13 @@ static void BattleStartClearSetData(void)

gSelectedMonPartyId = PARTY_SIZE; // Revival Blessing
gCategoryIconSpriteId = 0xFF;

if(FlagGet(B_FLAG_SLEEP_CLAUSE))
{
// If monCausingSleepClause[side] equals PARTY_SIZE, Sleep Clause is not active for the given side.
gBattleStruct->monCausingSleepClause[B_SIDE_PLAYER] = PARTY_SIZE;
gBattleStruct->monCausingSleepClause[B_SIDE_OPPONENT] = PARTY_SIZE;
}
}

void SwitchInClearSetData(u32 battler)
Expand Down
2 changes: 2 additions & 0 deletions src/battle_message.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ static const u8 sText_SpAttack[] = _("Sp. Atk");
static const u8 sText_SpDefense[] = _("Sp. Def");
static const u8 sText_Accuracy[] = _("accuracy");
static const u8 sText_Evasiveness[] = _("evasiveness");
static const u8 sText_BlockedBySleepClause[] = _("Sleep Clause kept {B_DEF_NAME_WITH_PREFIX2} awake!");

const u8 *const gStatNamesTable[NUM_BATTLE_STATS] =
{
Expand Down Expand Up @@ -1585,6 +1586,7 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_ELECTRICCURRENTISRUNNING - BATTLESTRINGS_TABLE_START] = sText_ElectricCurrentIsRunning,
[STRINGID_SEEMSWEIRD - BATTLESTRINGS_TABLE_START] = sText_SeemsWeird,
[STRINGID_WAGGLINGAFINGER - BATTLESTRINGS_TABLE_START] = sText_WagglingAFinger,
[STRINGID_BLOCKEDBYSLEEPCLAUSE - BATTLESTRINGS_TABLE_START] = sText_BlockedBySleepClause,
};

const u16 gTrainerUsedItemStringIds[] =
Expand Down
Loading
Loading