mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-12-25 01:28:54 -05:00
RBA and BA
This commit is contained in:
parent
bccd96966f
commit
4ffdc0b2f9
@ -1551,8 +1551,6 @@ void DrawEnhancementsMenu() {
|
||||
UIWidgets::Tooltip("Restore pre-release behavior where defeating a Gold Skulltula will play a cutscene showing it die.");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Quick Bongo Kill", CVAR_ENHANCEMENT("QuickBongoKill"), true, false);
|
||||
UIWidgets::Tooltip("Restore a bug from NTSC 1.0 that allows bypassing Bongo Bongo's intro cutscene to quickly kill him");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Original RBA Values", CVAR_ENHANCEMENT("RestoreRBAValues"), true, false);
|
||||
UIWidgets::Tooltip("Restores the original outcomes when performing Reverse Bottle Adventure.");
|
||||
UIWidgets::PaddedEnhancementCheckbox("Early Eyeball Frog", CVAR_ENHANCEMENT("EarlyEyeballFrog"), true, false);
|
||||
UIWidgets::Tooltip("Restores a bug from NTSC 1.0/1.1 that allows you to obtain the eyeball frog from King Zora instead of the Zora Tunic by holding shield.");
|
||||
|
||||
|
@ -1439,6 +1439,140 @@ Gfx* Gfx_TextureI8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 te
|
||||
return displayListHead;
|
||||
}
|
||||
|
||||
void Inventory_DoBA(u8 cRight) {
|
||||
if (cRight >= ITEM_STICK && cRight <= ITEM_POTION_BLUE) {
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.items[cRight];
|
||||
} else if (cRight >= ITEM_FAIRY && cRight <= ITEM_MASK_BUNNY) {
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.ammo[cRight - ITEM_FAIRY];
|
||||
} else if (cRight == ITEM_MASK_GORON) {
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.equipment >> 8) & 0xFF;
|
||||
} else if (cRight == ITEM_MASK_ZORA) {
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.equipment & 0xFF;
|
||||
} else if (cRight == ITEM_MASK_GERUDO || cRight == ITEM_MASK_TRUTH) {
|
||||
// ITEM_MASK_GERUDO and ITEM_MASK_TRUTH land in padding bytes
|
||||
gSaveContext.equips.buttonItems[0] = 0;
|
||||
} else if (cRight == ITEM_SOLD_OUT) {
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.upgrades >> 24) & 0xFF;
|
||||
} else if (cRight == ITEM_POCKET_EGG) {
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.upgrades >> 16) & 0xFF;
|
||||
} else if (cRight == ITEM_POCKET_CUCCO) {
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.upgrades >> 8) & 0xFF;
|
||||
} else if (cRight == ITEM_COJIRO) {
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.upgrades & 0xFF;
|
||||
} else if (cRight == ITEM_ODD_MUSHROOM) {
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.questItems >> 24) & 0xFF;
|
||||
} else if (cRight == ITEM_ODD_POTION) {
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.questItems >> 16) & 0xFF;
|
||||
} else if (cRight == ITEM_SAW) {
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.questItems >> 8) & 0xFF;
|
||||
} else if (cRight == ITEM_SWORD_BROKEN) {
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.questItems & 0xFF;
|
||||
} else if (cRight >= ITEM_PRESCRIPTION && cRight <= ITEM_BULLET_BAG_30) {
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.dungeonItems[cRight - ITEM_PRESCRIPTION];
|
||||
} else if (cRight >= ITEM_BULLET_BAG_40 && cRight <= ITEM_SWORD_KNIFE) {
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.dungeonKeys[cRight - ITEM_BULLET_BAG_40];
|
||||
} else if (cRight == ITEM_SONG_BOLERO) {
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.defenseHearts;
|
||||
} else if (cRight == ITEM_SONG_SERENADE) {
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.gsTokens >> 8) & 0xFF;
|
||||
} else if (cRight == ITEM_SONG_REQUIEM) {
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.gsTokens & 0xFF;
|
||||
} else if (cRight == ITEM_SONG_NOCTURNE || cRight == ITEM_SONG_PRELUDE) {
|
||||
// ITEM_SONG_NOCTURNE and ITEM_SONG_PRELUDE land in padding bytes
|
||||
gSaveContext.equips.buttonItems[0] = 0;
|
||||
} else if (cRight >= ITEM_SONG_LULLABY) {
|
||||
// The rest of the items fall into the saved scene flags. Let's calculate the scene and which field it pulls from
|
||||
u32 offset = cRight - ITEM_SONG_LULLABY;
|
||||
u32 scene = offset / sizeof(SavedSceneFlags);
|
||||
switch (offset % sizeof(SavedSceneFlags)) {
|
||||
case 0:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 24) & 0xFF;
|
||||
break;
|
||||
case 1:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 16) & 0xFF;
|
||||
break;
|
||||
case 2:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 8) & 0xFF;
|
||||
break;
|
||||
case 3:
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].chest & 0xFF;
|
||||
break;
|
||||
case 4:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 24) & 0xFF;
|
||||
break;
|
||||
case 5:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 16) & 0xFF;
|
||||
break;
|
||||
case 6:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 8) & 0xFF;
|
||||
break;
|
||||
case 7:
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].swch & 0xFF;
|
||||
break;
|
||||
case 8:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 24) & 0xFF;
|
||||
break;
|
||||
case 9:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 16) & 0xFF;
|
||||
break;
|
||||
case 10:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 8) & 0xFF;
|
||||
break;
|
||||
case 11:
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].clear & 0xFF;
|
||||
break;
|
||||
case 12:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 24) & 0xFF;
|
||||
break;
|
||||
case 13:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 16) & 0xFF;
|
||||
break;
|
||||
case 14:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 8) & 0xFF;
|
||||
break;
|
||||
case 15:
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].collect & 0xFF;
|
||||
break;
|
||||
case 16:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 24) & 0xFF;
|
||||
break;
|
||||
case 17:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 16) & 0xFF;
|
||||
break;
|
||||
case 18:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 8) & 0xFF;
|
||||
break;
|
||||
case 19:
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].unk & 0xFF;
|
||||
break;
|
||||
case 20:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 24) & 0xFF;
|
||||
break;
|
||||
case 21:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 16) & 0xFF;
|
||||
break;
|
||||
case 22:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 8) & 0xFF;
|
||||
break;
|
||||
case 23:
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].rooms & 0xFF;
|
||||
break;
|
||||
case 24:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 24) & 0xFF;
|
||||
break;
|
||||
case 25:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 16) & 0xFF;
|
||||
break;
|
||||
case 26:
|
||||
gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 8) & 0xFF;
|
||||
break;
|
||||
case 27:
|
||||
gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].floors & 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Rando_Inventory_SwapAgeEquipment(void) {
|
||||
s16 i;
|
||||
u16 shieldEquipValue;
|
||||
@ -1518,8 +1652,13 @@ void Rando_Inventory_SwapAgeEquipment(void) {
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_POE)) ||
|
||||
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
||||
if (i == 0) {
|
||||
// If bottle is on B, it triggers BA, which we need to recreate
|
||||
Inventory_DoBA(gSaveContext.equips.buttonItems[3]);
|
||||
} else {
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1675,8 +1814,13 @@ void Inventory_SwapAgeEquipment(void) {
|
||||
((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) &&
|
||||
(gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK))) {
|
||||
osSyncPrintf("Register_Item_Pt(%d)=%d\n", i, gSaveContext.equips.cButtonSlots[i - 1]);
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
||||
if (i == 0) {
|
||||
// If bottle is on B, it triggers BA, which we need to recreate
|
||||
Inventory_DoBA(gSaveContext.equips.buttonItems[3]);
|
||||
} else {
|
||||
gSaveContext.equips.buttonItems[i] =
|
||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[i - 1]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2699,11 +2843,136 @@ s32 Inventory_HasSpecificBottle(u8 bottleItem) {
|
||||
}
|
||||
}
|
||||
|
||||
void byteSwapInventory() {
|
||||
gSaveContext.inventory.equipment = BE16SWAP(gSaveContext.inventory.equipment);
|
||||
gSaveContext.inventory.upgrades = BE32SWAP(gSaveContext.inventory.upgrades);
|
||||
gSaveContext.inventory.questItems = BE32SWAP(gSaveContext.inventory.questItems);
|
||||
gSaveContext.inventory.gsTokens = BE16SWAP(gSaveContext.inventory.gsTokens);
|
||||
void Inventory_DoRBA(u8 cRight, u8 item) {
|
||||
if (cRight >= ITEM_STICK && cRight <= ITEM_POTION_BLUE) {
|
||||
gSaveContext.inventory.items[cRight] = item;
|
||||
} else if (cRight >= ITEM_FAIRY && cRight <= ITEM_MASK_BUNNY) {
|
||||
gSaveContext.inventory.ammo[cRight - ITEM_FAIRY] = item;
|
||||
} else if (cRight == ITEM_MASK_GORON) {
|
||||
gSaveContext.inventory.equipment = (item << 8) | (gSaveContext.inventory.equipment & 0x00FF);
|
||||
} else if (cRight == ITEM_MASK_ZORA) {
|
||||
gSaveContext.inventory.equipment = item | (gSaveContext.inventory.equipment & 0xFF00);
|
||||
}
|
||||
// ITEM_MASK_GERUDO and ITEM_MASK_TRUTH land in padding bytes
|
||||
else if (cRight == ITEM_SOLD_OUT) {
|
||||
gSaveContext.inventory.upgrades = (item << 24) | (gSaveContext.inventory.upgrades & 0x00FFFFFF);
|
||||
} else if (cRight == ITEM_POCKET_EGG) {
|
||||
gSaveContext.inventory.upgrades = (item << 16) | (gSaveContext.inventory.upgrades & 0xFF00FFFF);
|
||||
} else if (cRight == ITEM_POCKET_CUCCO) {
|
||||
gSaveContext.inventory.upgrades = (item << 8) | (gSaveContext.inventory.upgrades & 0xFFFF00FF);
|
||||
} else if (cRight == ITEM_COJIRO) {
|
||||
gSaveContext.inventory.upgrades = item | (gSaveContext.inventory.upgrades & 0xFFFFFF00);
|
||||
} else if (cRight == ITEM_ODD_MUSHROOM) {
|
||||
gSaveContext.inventory.questItems = (item << 24) | (gSaveContext.inventory.questItems & 0x00FFFFFF);
|
||||
} else if (cRight == ITEM_ODD_POTION) {
|
||||
gSaveContext.inventory.questItems = (item << 16) | (gSaveContext.inventory.questItems & 0xFF00FFFF);
|
||||
} else if (cRight == ITEM_SAW) {
|
||||
gSaveContext.inventory.questItems = (item << 8) | (gSaveContext.inventory.questItems & 0xFFFF00FF);
|
||||
} else if (cRight == ITEM_SWORD_BROKEN) {
|
||||
gSaveContext.inventory.questItems = item | (gSaveContext.inventory.questItems & 0xFFFFFF00);
|
||||
} else if (cRight >= ITEM_PRESCRIPTION && cRight <= ITEM_BULLET_BAG_30) {
|
||||
gSaveContext.inventory.dungeonItems[cRight - ITEM_PRESCRIPTION] = item;
|
||||
} else if (cRight >= ITEM_BULLET_BAG_40 && cRight <= ITEM_SWORD_KNIFE) {
|
||||
gSaveContext.inventory.dungeonKeys[cRight - ITEM_BULLET_BAG_40] = item;
|
||||
} else if (cRight == ITEM_SONG_BOLERO) {
|
||||
gSaveContext.inventory.defenseHearts = item;
|
||||
} else if (cRight == ITEM_SONG_SERENADE) {
|
||||
gSaveContext.inventory.gsTokens = (item << 8) | (gSaveContext.inventory.gsTokens & 0x00FF);
|
||||
} else if (cRight == ITEM_SONG_REQUIEM) {
|
||||
gSaveContext.inventory.gsTokens = item | (gSaveContext.inventory.gsTokens & 0xFF00);
|
||||
}
|
||||
// ITEM_SONG_NOCTURNE and ITEM_SONG_PRELUDE land in padding bytes
|
||||
else if (cRight >= ITEM_SONG_LULLABY) {
|
||||
// The rest of the items fall into the saved scene flags. Let's calculate the scene and which field it sets
|
||||
u32 offset = cRight - ITEM_SONG_LULLABY;
|
||||
u32 scene = offset / sizeof(SavedSceneFlags);
|
||||
switch (offset % sizeof(SavedSceneFlags)) {
|
||||
case 0:
|
||||
gSaveContext.sceneFlags[scene].chest = (item << 24) | (gSaveContext.sceneFlags[scene].chest & 0x00FFFFFF);
|
||||
break;
|
||||
case 1:
|
||||
gSaveContext.sceneFlags[scene].chest = (item << 16) | (gSaveContext.sceneFlags[scene].chest & 0xFF00FFFF);
|
||||
break;
|
||||
case 2:
|
||||
gSaveContext.sceneFlags[scene].chest = (item << 8) | (gSaveContext.sceneFlags[scene].chest & 0xFFFF00FF);
|
||||
break;
|
||||
case 3:
|
||||
gSaveContext.sceneFlags[scene].chest = item | (gSaveContext.sceneFlags[scene].chest & 0xFFFFFF00);
|
||||
break;
|
||||
case 4:
|
||||
gSaveContext.sceneFlags[scene].swch = (item << 24) | (gSaveContext.sceneFlags[scene].swch & 0x00FFFFFF);
|
||||
break;
|
||||
case 5:
|
||||
gSaveContext.sceneFlags[scene].swch = (item << 16) | (gSaveContext.sceneFlags[scene].swch & 0xFF00FFFF);
|
||||
break;
|
||||
case 6:
|
||||
gSaveContext.sceneFlags[scene].swch = (item << 8) | (gSaveContext.sceneFlags[scene].swch & 0xFFFF00FF);
|
||||
break;
|
||||
case 7:
|
||||
gSaveContext.sceneFlags[scene].swch = item | (gSaveContext.sceneFlags[scene].swch & 0xFFFFFF00);
|
||||
break;
|
||||
case 8:
|
||||
gSaveContext.sceneFlags[scene].clear = (item << 24) | (gSaveContext.sceneFlags[scene].clear & 0x00FFFFFF);
|
||||
break;
|
||||
case 9:
|
||||
gSaveContext.sceneFlags[scene].clear = (item << 16) | (gSaveContext.sceneFlags[scene].clear & 0xFF00FFFF);
|
||||
break;
|
||||
case 10:
|
||||
gSaveContext.sceneFlags[scene].clear = (item << 8) | (gSaveContext.sceneFlags[scene].clear & 0xFFFF00FF);
|
||||
break;
|
||||
case 11:
|
||||
gSaveContext.sceneFlags[scene].clear = item | (gSaveContext.sceneFlags[scene].clear & 0xFFFFFF00);
|
||||
break;
|
||||
case 12:
|
||||
gSaveContext.sceneFlags[scene].collect = (item << 24) | (gSaveContext.sceneFlags[scene].collect & 0x00FFFFFF);
|
||||
break;
|
||||
case 13:
|
||||
gSaveContext.sceneFlags[scene].collect = (item << 16) | (gSaveContext.sceneFlags[scene].collect & 0xFF00FFFF);
|
||||
break;
|
||||
case 14:
|
||||
gSaveContext.sceneFlags[scene].collect = (item << 8) | (gSaveContext.sceneFlags[scene].collect & 0xFFFF00FF);
|
||||
break;
|
||||
case 15:
|
||||
gSaveContext.sceneFlags[scene].collect = item | (gSaveContext.sceneFlags[scene].collect & 0xFFFFFF00);
|
||||
break;
|
||||
case 16:
|
||||
gSaveContext.sceneFlags[scene].unk = (item << 24) | (gSaveContext.sceneFlags[scene].unk & 0x00FFFFFF);
|
||||
break;
|
||||
case 17:
|
||||
gSaveContext.sceneFlags[scene].unk = (item << 16) | (gSaveContext.sceneFlags[scene].unk & 0xFF00FFFF);
|
||||
break;
|
||||
case 18:
|
||||
gSaveContext.sceneFlags[scene].unk = (item << 8) | (gSaveContext.sceneFlags[scene].unk & 0xFFFF00FF);
|
||||
break;
|
||||
case 19:
|
||||
gSaveContext.sceneFlags[scene].unk = item | (gSaveContext.sceneFlags[scene].unk & 0xFFFFFF00);
|
||||
break;
|
||||
case 20:
|
||||
gSaveContext.sceneFlags[scene].rooms = (item << 24) | (gSaveContext.sceneFlags[scene].rooms & 0x00FFFFFF);
|
||||
break;
|
||||
case 21:
|
||||
gSaveContext.sceneFlags[scene].rooms = (item << 16) | (gSaveContext.sceneFlags[scene].rooms & 0xFF00FFFF);
|
||||
break;
|
||||
case 22:
|
||||
gSaveContext.sceneFlags[scene].rooms = (item << 8) | (gSaveContext.sceneFlags[scene].rooms & 0xFFFF00FF);
|
||||
break;
|
||||
case 23:
|
||||
gSaveContext.sceneFlags[scene].rooms = item | (gSaveContext.sceneFlags[scene].rooms & 0xFFFFFF00);
|
||||
break;
|
||||
case 24:
|
||||
gSaveContext.sceneFlags[scene].floors = (item << 24) | (gSaveContext.sceneFlags[scene].floors & 0x00FFFFFF);
|
||||
break;
|
||||
case 25:
|
||||
gSaveContext.sceneFlags[scene].floors = (item << 16) | (gSaveContext.sceneFlags[scene].floors & 0xFF00FFFF);
|
||||
break;
|
||||
case 26:
|
||||
gSaveContext.sceneFlags[scene].floors = (item << 8) | (gSaveContext.sceneFlags[scene].floors & 0xFFFF00FF);
|
||||
break;
|
||||
case 27:
|
||||
gSaveContext.sceneFlags[scene].floors = item | (gSaveContext.sceneFlags[scene].floors & 0xFFFFFF00);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Inventory_UpdateBottleItem(PlayState* play, u8 item, u8 button) {
|
||||
@ -2717,10 +2986,9 @@ void Inventory_UpdateBottleItem(PlayState* play, u8 item, u8 button) {
|
||||
item = ITEM_MILK_HALF;
|
||||
}
|
||||
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("RestoreRBAValues"),0)) {
|
||||
byteSwapInventory();
|
||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[button - 1]] = item;
|
||||
byteSwapInventory();
|
||||
if (button == 0) {
|
||||
// If bottle is on B, it triggers RBA, which we need to recreate
|
||||
Inventory_DoRBA(gSaveContext.equips.buttonItems[3], item);
|
||||
} else {
|
||||
gSaveContext.inventory.items[gSaveContext.equips.cButtonSlots[button - 1]] = item;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user