mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-04-28 21:27:58 +03:00
fix market grass and crate logic
This commit is contained in:
parent
a247c06be8
commit
ef1bc2f5f0
4 changed files with 34 additions and 38 deletions
|
@ -50,7 +50,7 @@ void RegionTable_Init_BottomOfTheWell() {
|
||||||
LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, true),
|
LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_LEFT_FAKE_WALL_CHEST, true),
|
||||||
LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, true),
|
LOCATION(RC_BOTTOM_OF_THE_WELL_RIGHT_BOTTOM_FAKE_WALL_CHEST, true),
|
||||||
LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, true),
|
LOCATION(RC_BOTTOM_OF_THE_WELL_COMPASS_CHEST, true),
|
||||||
//N64 has no extra check here, but I can't get past without dealing with the spider or taking a hit, they probably assume sticks
|
//You can just barely pass the spider on the right side without damage or items, but it's probably tight enough to count as as a trick
|
||||||
LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()),
|
LOCATION(RC_BOTTOM_OF_THE_WELL_CENTER_SKULLTULA_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->TakeDamage()),
|
||||||
//Not technically behind a wall, but still logically needs lens due to pits
|
//Not technically behind a wall, but still logically needs lens due to pits
|
||||||
LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives()),
|
LOCATION(RC_BOTTOM_OF_THE_WELL_BACK_LEFT_BOMBABLE_CHEST, logic->HasExplosives()),
|
||||||
|
@ -160,7 +160,7 @@ void RegionTable_Init_BottomOfTheWell() {
|
||||||
}, {
|
}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, []{return logic->IsChild && logic->CanPassEnemy(RE_BIG_SKULLTULA);}),
|
Entrance(RR_BOTTOM_OF_THE_WELL_SOUTHWEST_ROOM, []{return logic->IsChild && logic->CanPassEnemy(RE_BIG_SKULLTULA);}),
|
||||||
//It's possible top abuse boulder's limited range of collision detection to detonate the flowers through the boulder with bow, but this is a glitch
|
//It's possible to abuse boulder's limited range of collision detection to detonate the flowers through the boulder with bow, but this is a glitch
|
||||||
//the exact range is just past the furthest away plank in the green goo section
|
//the exact range is just past the furthest away plank in the green goo section
|
||||||
Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS, []{return Here(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || (logic->CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_BASEMENT));});}),
|
Entrance(RR_BOTTOM_OF_THE_WELL_BASEMENT_USEFUL_BOMB_FLOWERS, []{return Here(RR_BOTTOM_OF_THE_WELL_BASEMENT, []{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || (logic->CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_BASEMENT));});}),
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,18 +14,19 @@ void RegionTable_Init_Market() {
|
||||||
|
|
||||||
areaTable[RR_THE_MARKET] = Region("Market", "Market", {RA_THE_MARKET}, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[RR_THE_MARKET] = Region("Market", "Market", {RA_THE_MARKET}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
//Locations
|
//Locations
|
||||||
LOCATION(RC_MARKET_GRASS_1, logic->IsChild && logic->CanCutShrubs()),
|
//RANDOTODO add item avalibility to regions to remove need to hardcode logic in limited item use situations
|
||||||
LOCATION(RC_MARKET_GRASS_2, logic->IsChild && logic->CanCutShrubs()),
|
LOCATION(RC_MARKET_GRASS_1, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))),
|
||||||
LOCATION(RC_MARKET_GRASS_3, logic->IsChild && logic->CanCutShrubs()),
|
LOCATION(RC_MARKET_GRASS_2, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))),
|
||||||
LOCATION(RC_MARKET_GRASS_4, logic->IsChild && logic->CanCutShrubs()),
|
LOCATION(RC_MARKET_GRASS_3, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))),
|
||||||
LOCATION(RC_MARKET_GRASS_5, logic->IsChild && logic->CanCutShrubs()),
|
LOCATION(RC_MARKET_GRASS_4, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))),
|
||||||
LOCATION(RC_MARKET_GRASS_6, logic->IsChild && logic->CanCutShrubs()),
|
LOCATION(RC_MARKET_GRASS_5, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))),
|
||||||
LOCATION(RC_MARKET_GRASS_7, logic->IsChild && logic->CanCutShrubs()),
|
LOCATION(RC_MARKET_GRASS_6, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))),
|
||||||
LOCATION(RC_MARKET_GRASS_8, logic->IsChild && logic->CanCutShrubs()),
|
LOCATION(RC_MARKET_GRASS_7, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))),
|
||||||
LOCATION(RC_MK_NEAR_BAZAAR_CRATE_1, logic->IsChild && logic->CanBreakCrates()),
|
LOCATION(RC_MARKET_GRASS_8, logic->IsChild && (logic->CanUseSword() || logic->HasItem(RG_GORONS_BRACELET))),
|
||||||
LOCATION(RC_MK_NEAR_BAZAAR_CRATE_2, logic->IsChild && logic->CanBreakCrates()),
|
LOCATION(RC_MK_NEAR_BAZAAR_CRATE_1, logic->IsChild /*&& logic->CanRoll()*/),
|
||||||
LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_1, logic->IsChild && logic->CanBreakCrates()),
|
LOCATION(RC_MK_NEAR_BAZAAR_CRATE_2, logic->IsChild /*&& logic->CanRoll()*/),
|
||||||
LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_2, logic->IsChild && logic->CanBreakCrates()),
|
LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_1, logic->IsChild /*&& logic->CanRoll()*/),
|
||||||
|
LOCATION(RC_MK_SHOOTING_GALLERY_CRATE_2, logic->IsChild /*&& logic->CanRoll()*/),
|
||||||
}, {
|
}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(RR_MARKET_ENTRANCE, []{return true;}),
|
Entrance(RR_MARKET_ENTRANCE, []{return true;}),
|
||||||
|
|
|
@ -558,9 +558,8 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal
|
||||||
}
|
}
|
||||||
return killed;
|
return killed;
|
||||||
case RE_DODONGO:
|
case RE_DODONGO:
|
||||||
return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) ||
|
return CanUseSword() || CanUse(RG_MEGATON_HAMMER) || (quantity <= 5 && CanUse(RG_STICKS)) ||
|
||||||
CanUse(RG_MEGATON_HAMMER) || (quantity <= 5 && CanUse(RG_STICKS)) || HasExplosives() ||
|
HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);
|
||||||
CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);
|
|
||||||
case RE_LIZALFOS:
|
case RE_LIZALFOS:
|
||||||
return CanJumpslash() || HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);
|
return CanJumpslash() || HasExplosives() || CanUse(RG_FAIRY_SLINGSHOT) || CanUse(RG_FAIRY_BOW);
|
||||||
case RE_KEESE:
|
case RE_KEESE:
|
||||||
|
@ -604,11 +603,9 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal
|
||||||
(CanUse(RG_NUTS) || HookshotOrBoomerang() || CanStandingShield()));
|
(CanUse(RG_NUTS) || HookshotOrBoomerang() || CanStandingShield()));
|
||||||
case RE_DEAD_HAND:
|
case RE_DEAD_HAND:
|
||||||
// RANDOTODO change Dead Hand trick to be sticks Dead Hand
|
// RANDOTODO change Dead Hand trick to be sticks Dead Hand
|
||||||
return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) ||
|
return CanUseSword() || (CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_CHILD_DEADHAND));
|
||||||
(CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_CHILD_DEADHAND));
|
|
||||||
case RE_WITHERED_DEKU_BABA:
|
case RE_WITHERED_DEKU_BABA:
|
||||||
return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) ||
|
return CanUseSword() || CanUse(RG_BOOMERANG);
|
||||||
CanUse(RG_BOOMERANG);
|
|
||||||
case RE_LIKE_LIKE:
|
case RE_LIKE_LIKE:
|
||||||
case RE_FLOORMASTER:
|
case RE_FLOORMASTER:
|
||||||
return CanDamage();
|
return CanDamage();
|
||||||
|
@ -645,8 +642,7 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal
|
||||||
// bow and sling can wake them and damage after they shed their armour, so could reduce ammo requirements for
|
// bow and sling can wake them and damage after they shed their armour, so could reduce ammo requirements for
|
||||||
// explosives to 10. requires 8 sticks to kill so would be a trick unless we apply higher stick bag logic
|
// explosives to 10. requires 8 sticks to kill so would be a trick unless we apply higher stick bag logic
|
||||||
case RE_IRON_KNUCKLE:
|
case RE_IRON_KNUCKLE:
|
||||||
return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) ||
|
return CanUseSword() || CanUse(RG_MEGATON_HAMMER) || HasExplosives();
|
||||||
CanUse(RG_MEGATON_HAMMER) || HasExplosives();
|
|
||||||
// To stun flare dancer with chus, you have to hit the flame under it while it is spinning. It should eventually
|
// To stun flare dancer with chus, you have to hit the flame under it while it is spinning. It should eventually
|
||||||
// return to spinning after dashing for a while if you miss the window it is possible to damage the core with
|
// return to spinning after dashing for a while if you miss the window it is possible to damage the core with
|
||||||
// explosives, but difficult to get all 4 hits in even with chus, and if it reconstructs the core heals, so it
|
// explosives, but difficult to get all 4 hits in even with chus, and if it reconstructs the core heals, so it
|
||||||
|
@ -695,8 +691,7 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal
|
||||||
CanUse(RG_STICKS) || HasExplosives() || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE) ||
|
CanUse(RG_STICKS) || HasExplosives() || CanUse(RG_HOOKSHOT) || CanUse(RG_DINS_FIRE) ||
|
||||||
CanUse(RG_FIRE_ARROWS);
|
CanUse(RG_FIRE_ARROWS);
|
||||||
case RE_SHELL_BLADE:
|
case RE_SHELL_BLADE:
|
||||||
return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) ||
|
return CanJumpslash() || HasExplosives() || CanUse(RG_HOOKSHOT) ||
|
||||||
CanUse(RG_MEGATON_HAMMER) || CanUse(RG_STICKS) || HasExplosives() || CanUse(RG_HOOKSHOT) ||
|
|
||||||
CanUse(RG_FAIRY_BOW) || CanUse(RG_DINS_FIRE);
|
CanUse(RG_FAIRY_BOW) || CanUse(RG_DINS_FIRE);
|
||||||
case RE_SPIKE:
|
case RE_SPIKE:
|
||||||
return CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MEGATON_HAMMER) ||
|
return CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_MEGATON_HAMMER) ||
|
||||||
|
@ -745,24 +740,20 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal
|
||||||
return HasBossSoul(RG_BARINADE_SOUL) && CanUse(RG_BOOMERANG) && CanJumpslashExceptHammer();
|
return HasBossSoul(RG_BARINADE_SOUL) && CanUse(RG_BOOMERANG) && CanJumpslashExceptHammer();
|
||||||
case RE_PHANTOM_GANON:
|
case RE_PHANTOM_GANON:
|
||||||
return HasBossSoul(RG_PHANTOM_GANON_SOUL) &&
|
return HasBossSoul(RG_PHANTOM_GANON_SOUL) &&
|
||||||
(CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) &&
|
CanUseSword() && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT));
|
||||||
(CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT));
|
|
||||||
case RE_VOLVAGIA:
|
case RE_VOLVAGIA:
|
||||||
return HasBossSoul(RG_VOLVAGIA_SOUL) && CanUse(RG_MEGATON_HAMMER);
|
return HasBossSoul(RG_VOLVAGIA_SOUL) && CanUse(RG_MEGATON_HAMMER);
|
||||||
case RE_MORPHA:
|
case RE_MORPHA:
|
||||||
return HasBossSoul(RG_MORPHA_SOUL) && CanUse(RG_HOOKSHOT) &&
|
return HasBossSoul(RG_MORPHA_SOUL) && CanUse(RG_HOOKSHOT) &&
|
||||||
(CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) ||
|
(CanUseSword() || CanUse(RG_MEGATON_HAMMER));
|
||||||
CanUse(RG_MEGATON_HAMMER));
|
|
||||||
case RE_BONGO_BONGO:
|
case RE_BONGO_BONGO:
|
||||||
return HasBossSoul(RG_BONGO_BONGO_SOUL) &&
|
return HasBossSoul(RG_BONGO_BONGO_SOUL) &&
|
||||||
(CanUse(RG_LENS_OF_TRUTH) || ctx->GetTrickOption(RT_LENS_BONGO)) &&
|
(CanUse(RG_LENS_OF_TRUTH) || ctx->GetTrickOption(RT_LENS_BONGO)) &&
|
||||||
(CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)) &&
|
CanUseSword() && (CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) ||
|
||||||
(CanUse(RG_HOOKSHOT) || CanUse(RG_FAIRY_BOW) || CanUse(RG_FAIRY_SLINGSHOT) ||
|
|
||||||
ctx->GetTrickOption(RT_SHADOW_BONGO));
|
ctx->GetTrickOption(RT_SHADOW_BONGO));
|
||||||
case RE_TWINROVA:
|
case RE_TWINROVA:
|
||||||
return HasBossSoul(RG_TWINROVA_SOUL) && CanUse(RG_MIRROR_SHIELD) &&
|
return HasBossSoul(RG_TWINROVA_SOUL) && CanUse(RG_MIRROR_SHIELD) &&
|
||||||
(CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) ||
|
(CanUseSword() || CanUse(RG_MEGATON_HAMMER));
|
||||||
CanUse(RG_MEGATON_HAMMER));
|
|
||||||
case RE_GANONDORF:
|
case RE_GANONDORF:
|
||||||
// RANDOTODO: Trick to use hammer (no jumpslash) or stick (only jumpslash) instead of a sword to reflect the
|
// RANDOTODO: Trick to use hammer (no jumpslash) or stick (only jumpslash) instead of a sword to reflect the
|
||||||
// energy ball and either of them regardless of jumpslashing to damage and kill ganondorf
|
// energy ball and either of them regardless of jumpslashing to damage and kill ganondorf
|
||||||
|
@ -771,8 +762,7 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal
|
||||||
// for killing ganondorf and all of those can reflect the energy ball
|
// for killing ganondorf and all of those can reflect the energy ball
|
||||||
// This will not be the case once ammo logic in taken into account as
|
// This will not be the case once ammo logic in taken into account as
|
||||||
// sticks are limited and using a bottle might become a requirement in that case
|
// sticks are limited and using a bottle might become a requirement in that case
|
||||||
return HasBossSoul(RG_GANON_SOUL) && CanUse(RG_LIGHT_ARROWS) &&
|
return HasBossSoul(RG_GANON_SOUL) && CanUse(RG_LIGHT_ARROWS) && CanUseSword();
|
||||||
(CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD));
|
|
||||||
case RE_GANON:
|
case RE_GANON:
|
||||||
return HasBossSoul(RG_GANON_SOUL) && CanUse(RG_MASTER_SWORD);
|
return HasBossSoul(RG_GANON_SOUL) && CanUse(RG_MASTER_SWORD);
|
||||||
case RE_DARK_LINK:
|
case RE_DARK_LINK:
|
||||||
|
@ -793,7 +783,7 @@ bool Logic::CanKillEnemy(RandomizerEnemy enemy, EnemyDistance distance, bool wal
|
||||||
case RE_BARI:
|
case RE_BARI:
|
||||||
return HookshotOrBoomerang() || CanUse(RG_FAIRY_BOW) || HasExplosives() || CanUse(RG_MEGATON_HAMMER) ||
|
return HookshotOrBoomerang() || CanUse(RG_FAIRY_BOW) || HasExplosives() || CanUse(RG_MEGATON_HAMMER) ||
|
||||||
CanUse(RG_STICKS) || CanUse(RG_DINS_FIRE) ||
|
CanUse(RG_STICKS) || CanUse(RG_DINS_FIRE) ||
|
||||||
(TakeDamage() && (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD)));
|
(TakeDamage() && CanUseSword());
|
||||||
case RE_SHABOM:
|
case RE_SHABOM:
|
||||||
// RANDOTODO when you add better damage logic, you can kill this by taking hits
|
// RANDOTODO when you add better damage logic, you can kill this by taking hits
|
||||||
return CanUse(RG_BOOMERANG) || CanUse(RG_NUTS) || CanJumpslash() || CanUse(RG_DINS_FIRE) ||
|
return CanUse(RG_BOOMERANG) || CanUse(RG_NUTS) || CanJumpslash() || CanUse(RG_DINS_FIRE) ||
|
||||||
|
@ -962,7 +952,7 @@ bool Logic::CanBreakMudWalls() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Logic::CanGetDekuBabaSticks() {
|
bool Logic::CanGetDekuBabaSticks() {
|
||||||
return (CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD) || CanUse(RG_BOOMERANG));
|
return CanUseSword() || CanUse(RG_BOOMERANG);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Logic::CanGetDekuBabaNuts() {
|
bool Logic::CanGetDekuBabaNuts() {
|
||||||
|
@ -1060,9 +1050,13 @@ bool Logic::HasBottle() {
|
||||||
return BottleCount() >= 1;
|
return BottleCount() >= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Logic::CanUseSword() {
|
||||||
|
return CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);
|
||||||
|
}
|
||||||
|
|
||||||
bool Logic::CanJumpslashExceptHammer() {
|
bool Logic::CanJumpslashExceptHammer() {
|
||||||
// Not including hammer as hammer jump attacks can be weird;
|
// Not including hammer as hammer jump attacks can be weird;
|
||||||
return CanUse(RG_STICKS) || CanUse(RG_KOKIRI_SWORD) || CanUse(RG_MASTER_SWORD) || CanUse(RG_BIGGORON_SWORD);
|
return CanUse(RG_STICKS) || CanUseSword();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Logic::CanJumpslash() {
|
bool Logic::CanJumpslash() {
|
||||||
|
|
|
@ -209,6 +209,7 @@ class Logic {
|
||||||
uint8_t BottleCount();
|
uint8_t BottleCount();
|
||||||
uint8_t OcarinaButtons();
|
uint8_t OcarinaButtons();
|
||||||
bool HasBottle();
|
bool HasBottle();
|
||||||
|
bool CanUseSword();
|
||||||
bool CanJumpslashExceptHammer();
|
bool CanJumpslashExceptHammer();
|
||||||
bool CanJumpslash();
|
bool CanJumpslash();
|
||||||
bool CanHitSwitch(EnemyDistance distance = ED_CLOSE, bool inWater = false);
|
bool CanHitSwitch(EnemyDistance distance = ED_CLOSE, bool inWater = false);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue