diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua
index 925623f9f..e8258f161 100644
--- a/autogen/lua_definitions/functions.lua
+++ b/autogen/lua_definitions/functions.lua
@@ -2997,6 +2997,12 @@ function position_based_random_float_position()
-- ...
end
+--- @return boolean
+--- Checks if the draw distance scalar is infinite
+function draw_distance_scalar_is_infinite()
+ -- ...
+end
+
--- @return number
--- Gets the draw distance scalar
function draw_distance_scalar()
diff --git a/docs/lua/functions-3.md b/docs/lua/functions-3.md
index 2aab0ab14..ec32aed47 100644
--- a/docs/lua/functions-3.md
+++ b/docs/lua/functions-3.md
@@ -139,6 +139,27 @@ Sets the current object's position to random floats between 0.0 and 1.0
+## [draw_distance_scalar_is_infinite](#draw_distance_scalar_is_infinite)
+
+### Description
+Checks if the draw distance scalar is infinite
+
+### Lua Example
+`local booleanValue = draw_distance_scalar_is_infinite()`
+
+### Parameters
+- None
+
+### Returns
+- `boolean`
+
+### C Prototype
+`bool draw_distance_scalar_is_infinite(void);`
+
+[:arrow_up_small:](#)
+
+
+
## [draw_distance_scalar](#draw_distance_scalar)
### Description
diff --git a/docs/lua/functions.md b/docs/lua/functions.md
index bb2cd05d3..24dc305d0 100644
--- a/docs/lua/functions.md
+++ b/docs/lua/functions.md
@@ -623,6 +623,7 @@
- [obj_update_gfx_pos_and_angle](functions-3.md#obj_update_gfx_pos_and_angle)
- [position_based_random_u16](functions-3.md#position_based_random_u16)
- [position_based_random_float_position](functions-3.md#position_based_random_float_position)
+ - [draw_distance_scalar_is_infinite](functions-3.md#draw_distance_scalar_is_infinite)
- [draw_distance_scalar](functions-3.md#draw_distance_scalar)
diff --git a/lang/Czech.ini b/lang/Czech.ini
index e025a5e4e..21934b00a 100644
--- a/lang/Czech.ini
+++ b/lang/Czech.ini
@@ -167,6 +167,7 @@ D1P5X = "1.5x"
D3X = "3x"
D10X = "10x"
D100X = "100x"
+INFINITE = "Nekonečno"
DRAW_DISTANCE = "Vzdálenost vykreslování"
DYNOS_PACKS = "DynOS packy"
ANTIALIASING = "Anti-aliasing"
diff --git a/lang/Dutch.ini b/lang/Dutch.ini
index dc22bb586..3e4cbe5eb 100644
--- a/lang/Dutch.ini
+++ b/lang/Dutch.ini
@@ -167,6 +167,7 @@ D1P5X = "1.5x"
D3X = "3x"
D10X = "10x"
D100X = "100x"
+INFINITE = "Oneindig"
DRAW_DISTANCE = "Teken afstand"
DYNOS_PACKS = "DynOS Packs"
ANTIALIASING = "Anti-aliasing"
diff --git a/lang/English.ini b/lang/English.ini
index 3a0061d4d..0e51e68d9 100644
--- a/lang/English.ini
+++ b/lang/English.ini
@@ -167,6 +167,7 @@ D1P5X = "1.5x"
D3X = "3x"
D10X = "10x"
D100X = "100x"
+INFINITE = "Infinite"
DRAW_DISTANCE = "Draw Distance"
DYNOS_PACKS = "DynOS Packs"
ANTIALIASING = "Anti-aliasing"
diff --git a/lang/French.ini b/lang/French.ini
index 863306e82..2f8cf7143 100644
--- a/lang/French.ini
+++ b/lang/French.ini
@@ -167,6 +167,7 @@ D1P5X = "x1.5"
D3X = "x3"
D10X = "x10"
D100X = "x100"
+INFINITE = "Infini"
DRAW_DISTANCE = "Distance d'affichage"
DYNOS_PACKS = "Packs DynOS"
ANTIALIASING = "Anti-aliasing"
diff --git a/lang/German.ini b/lang/German.ini
index 90127de7b..9a2c3da44 100644
--- a/lang/German.ini
+++ b/lang/German.ini
@@ -167,6 +167,7 @@ D1P5X = "1.5x"
D3X = "3x"
D10X = "10x"
D100X = "100x"
+INFINITE = "Unendlich"
DRAW_DISTANCE = "Sichtweite"
DYNOS_PACKS = "DynOS-Pakete"
ANTIALIASING = "Kantenglättung"
diff --git a/lang/Italian.ini b/lang/Italian.ini
index 3f75a5686..ee36b2939 100644
--- a/lang/Italian.ini
+++ b/lang/Italian.ini
@@ -165,6 +165,7 @@ D1P5X = "1.5x"
D3X = "3x"
D10X = "10x"
D100X = "100x"
+INFINITE = "Infinito"
DRAW_DISTANCE = "Distanza di Simulazione"
DYNOS_PACKS = "Pacchetti DynOS"
ANTIALIASING = "Anti-aliasing"
diff --git a/lang/Japanese.ini b/lang/Japanese.ini
index 06a9e2800..e9d1e125b 100644
--- a/lang/Japanese.ini
+++ b/lang/Japanese.ini
@@ -167,6 +167,7 @@ D1P5X = "1.5x"
D3X = "3x"
D10X = "10x"
D100X = "100x"
+INFINITE = "無限"
DRAW_DISTANCE = "描画距離"
DYNOS_PACKS = "DynOSパック"
ANTIALIASING = "アンチエイリアス"
diff --git a/lang/Polish.ini b/lang/Polish.ini
index 0989080ad..571b35444 100644
--- a/lang/Polish.ini
+++ b/lang/Polish.ini
@@ -167,6 +167,7 @@ D1P5X = "1,5x"
D3X = "3x"
D10X = "10x"
D100X = "100x"
+INFINITE = "Nieskończony"
DRAW_DISTANCE = "Odległość Renderowania"
DYNOS_PACKS = "Paczki DynOS"
ANTIALIASING = "Anti-aliasing"
diff --git a/lang/Portuguese.ini b/lang/Portuguese.ini
index 750f6cb5c..275ff2b02 100644
--- a/lang/Portuguese.ini
+++ b/lang/Portuguese.ini
@@ -167,6 +167,7 @@ D1P5X = "1.5x"
D3X = "3x"
D10X = "10x"
D100X = "100x"
+INFINITE = "Infinito"
DRAW_DISTANCE = "Distância de renderização"
DYNOS_PACKS = "Pacotes DynOS"
ANTIALIASING = "Antisserrilhamento"
diff --git a/lang/Russian.ini b/lang/Russian.ini
index f04fdbd49..569f7ee33 100644
--- a/lang/Russian.ini
+++ b/lang/Russian.ini
@@ -166,6 +166,7 @@ D1P5X = "1.5x"
D3X = "3x"
D10X = "10x"
D100X = "100x"
+INFINITE = "Бесконечный"
DRAW_DISTANCE = "Дальность прорисовки"
DYNOS_PACKS = "Пакеты DynOS"
ANTIALIASING = "Анизотропная фильтрация"
diff --git a/lang/Spanish.ini b/lang/Spanish.ini
index b0129ad60..f525ea49b 100644
--- a/lang/Spanish.ini
+++ b/lang/Spanish.ini
@@ -167,6 +167,7 @@ D1P5X = "1.5x"
D3X = "3x"
D10X = "10x"
D100X = "100x"
+INFINITE = "Infinito"
DRAW_DISTANCE = "Distancia de dibujado"
DYNOS_PACKS = "Packs DynOS"
ANTIALIASING = "Anti-aliasing"
diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c
index 054e773f4..316b5b82d 100644
--- a/src/engine/behavior_script.c
+++ b/src/engine/behavior_script.c
@@ -1438,7 +1438,9 @@ cur_obj_update_begin:;
} else if ((objFlags & OBJ_FLAG_COMPUTE_DIST_TO_MARIO) && gCurrentObject->collisionData == NULL) {
if (!(objFlags & OBJ_FLAG_ACTIVE_FROM_AFAR)) {
// If the object has a render distance, check if it should be shown.
- if (distanceFromMario > gCurrentObject->oDrawingDistance * draw_distance_scalar()) {
+ if (!draw_distance_scalar_is_infinite() &&
+ distanceFromMario > gCurrentObject->oDrawingDistance * draw_distance_scalar()
+ ) {
// Out of render distance, hide the object.
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
@@ -1486,6 +1488,13 @@ f32 position_based_random_float_position(void) {
return rnd / (double)0x10000;
}
+bool draw_distance_scalar_is_infinite(void) {
+ if (!gBehaviorValues.InfiniteRenderDistance) {
+ return false;
+ }
+ return configDrawDistance == 6; // Expecting this to be "Infinite"
+}
+
f32 draw_distance_scalar(void) {
if (!gBehaviorValues.InfiniteRenderDistance) { return 1.0f; }
diff --git a/src/engine/behavior_script.h b/src/engine/behavior_script.h
index c3af4e0ed..43b0769d2 100644
--- a/src/engine/behavior_script.h
+++ b/src/engine/behavior_script.h
@@ -37,6 +37,8 @@ void obj_update_gfx_pos_and_angle(struct Object *obj);
u16 position_based_random_u16(void);
/* |description|Sets the current object's position to random floats between 0.0 and 1.0|descriptionEnd| */
f32 position_based_random_float_position(void);
+/* |description|Checks if the draw distance scalar is infinite|descriptionEnd| */
+bool draw_distance_scalar_is_infinite(void);
/* |description|Gets the draw distance scalar|descriptionEnd| */
f32 draw_distance_scalar(void);
diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c
index c611750b0..5fbda2faf 100644
--- a/src/engine/surface_load.c
+++ b/src/engine/surface_load.c
@@ -1045,7 +1045,9 @@ static void load_object_collision_model_internal(bool isSOC) {
if (!isSOC) {
f32 marioDist = dist_between_objects(gCurrentObject, gMarioStates[0].marioObj);
- if (marioDist < gCurrentObject->oDrawingDistance * draw_distance_scalar()) {
+ if (draw_distance_scalar_is_infinite() ||
+ marioDist < gCurrentObject->oDrawingDistance * draw_distance_scalar()
+ ) {
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
} else {
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
diff --git a/src/game/behaviors/king_bobomb.inc.c b/src/game/behaviors/king_bobomb.inc.c
index 80945aca1..0ff0d7b56 100644
--- a/src/game/behaviors/king_bobomb.inc.c
+++ b/src/game/behaviors/king_bobomb.inc.c
@@ -230,7 +230,7 @@ void king_bobomb_act_7(void) {
void king_bobomb_act_8(void) {
if (!(o->header.gfx.node.flags & GRAPH_RENDER_INVISIBLE)) {
struct Object *star = NULL;
-
+
create_sound_spawner(SOUND_OBJ_KING_WHOMP_DEATH);
cur_obj_hide();
cur_obj_become_intangible();
@@ -367,6 +367,10 @@ void king_bobomb_move(void) {
cur_obj_move_using_fvel_and_gravity();
CUR_OBJ_CALL_ACTION_FUNCTION(sKingBobombActions);
exec_anim_sound_state(sKingBobombSoundStates, sizeof(sKingBobombSoundStates) / sizeof(struct SoundState));
+ if (draw_distance_scalar_is_infinite()) {
+ cur_obj_enable_rendering();
+ return;
+ }
s32 distanceToPlayer = dist_between_objects(o, gMarioStates[0].marioObj);
if (distanceToPlayer < 5000.0f * draw_distance_scalar())
cur_obj_enable_rendering();
diff --git a/src/game/behaviors/piranha_plant.inc.c b/src/game/behaviors/piranha_plant.inc.c
index 628bfcb01..f986c4eb4 100644
--- a/src/game/behaviors/piranha_plant.inc.c
+++ b/src/game/behaviors/piranha_plant.inc.c
@@ -375,12 +375,16 @@ void bhv_piranha_plant_loop(void) {
CUR_OBJ_CALL_ACTION_FUNCTION(TablePiranhaPlantActions);
// In WF, hide all Piranha Plants once high enough up.
if (gCurrLevelNum == LEVEL_WF) {
- struct Object* player = gMarioStates[0].marioObj;
- f32 scalar = max(draw_distance_scalar(), 1.0f);
- if (player->oPosY > 3400.0f * scalar)
- cur_obj_hide();
- else
+ if (draw_distance_scalar_is_infinite()) {
cur_obj_unhide();
+ } else {
+ struct Object* player = gMarioStates[0].marioObj;
+ f32 scalar = max(draw_distance_scalar(), 1.0f);
+ if (player->oPosY > 3400.0f * scalar)
+ cur_obj_hide();
+ else
+ cur_obj_unhide();
+ }
}
o->oInteractStatus = 0;
}
diff --git a/src/game/behaviors/whirlpool.inc.c b/src/game/behaviors/whirlpool.inc.c
index a5646f0c1..7034e4f0f 100644
--- a/src/game/behaviors/whirlpool.inc.c
+++ b/src/game/behaviors/whirlpool.inc.c
@@ -44,11 +44,15 @@ void bhv_whirlpool_loop(void) {
o->oWhirlpoolTimeout = 30;
}
- f32 marioDist = dist_between_objects(o, gMarioStates[0].marioObj);
- if (marioDist < 5000.0f * draw_distance_scalar()) {
+ if (draw_distance_scalar_is_infinite()) {
o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
} else {
- o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
+ f32 marioDist = dist_between_objects(o, gMarioStates[0].marioObj);
+ if (marioDist < 5000.0f * draw_distance_scalar()) {
+ o->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
+ } else {
+ o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE;
+ }
}
// not sure if actually an array
diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c
index fc38d0a15..26b04be76 100644
--- a/src/game/obj_behaviors.c
+++ b/src/game/obj_behaviors.c
@@ -701,6 +701,10 @@ s8 is_point_close_to_object(struct Object *obj, f32 x, f32 y, f32 z, s32 dist) {
/* |description|Sets an object as visible if within a certain distance of Mario's graphical position|descriptionEnd| */
void set_object_visibility(struct Object *obj, s32 dist) {
if (!obj) { return; }
+ if (draw_distance_scalar_is_infinite()) {
+ obj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
+ return;
+ }
s32 distanceToPlayer = dist_between_objects(obj, gMarioStates[0].marioObj);
if (distanceToPlayer < dist * draw_distance_scalar()) {
obj->header.gfx.node.flags &= ~GRAPH_RENDER_INVISIBLE;
diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c
index 3d600d10d..8705b804a 100644
--- a/src/game/object_helpers.c
+++ b/src/game/object_helpers.c
@@ -3010,7 +3010,9 @@ void cur_obj_if_hit_wall_bounce_away(void) {
s32 cur_obj_hide_if_mario_far_away_y(f32 distY) {
if (!o) { return 0; }
if (!gMarioStates[0].marioObj) { return FALSE; }
- if (absf(o->oPosY - gMarioStates[0].marioObj->oPosY) < distY * draw_distance_scalar()) {
+ if (draw_distance_scalar_is_infinite() ||
+ absf(o->oPosY - gMarioStates[0].marioObj->oPosY) < distY * draw_distance_scalar()
+ ) {
cur_obj_unhide();
return FALSE;
}
diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c
index 07089fea5..82d0da8f7 100644
--- a/src/game/rendering_graph_node.c
+++ b/src/game/rendering_graph_node.c
@@ -50,6 +50,8 @@
#define DISPLAY_LIST_HEAP_SIZE 32000
+#define MAX_FAR_PLANE_DIST 1000000.f
+
f32 gProjectionMaxNearValue = 5;
s16 gProjectionVanillaNearValue = 100;
s16 gProjectionVanillaFarValue = 1000;
@@ -310,6 +312,10 @@ void patch_mtx_interpolated(f32 delta) {
f32 fovInterpolated = delta_interpolate_f32(sPerspectiveNode->prevFov, sPerspectiveNode->fov, delta);
f32 near = get_first_person_enabled() ? 1.f : replace_value_if_not_zero(MIN(sPerspectiveNode->near, gProjectionMaxNearValue), gOverrideNear);
f32 far = replace_value_if_not_zero(sPerspectiveNode->far, gOverrideFar);
+
+ // "infinite" draw distance
+ if (gOverrideFar == 0 && configDrawDistance == 6) { far = max(far, MAX_FAR_PLANE_DIST); }
+
guPerspective(sPerspectiveMtx, &perspNorm, fovInterpolated, sPerspectiveAspect, near, far, 1.0f);
gSPMatrix(sPerspectivePos, VIRTUAL_TO_PHYSICAL(sPerspectiveNode), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH);
}
@@ -650,6 +656,10 @@ static void geo_process_perspective(struct GraphNodePerspective *node) {
gProjectionVanillaFarValue = node->far;
f32 near = get_first_person_enabled() ? 1.f : replace_value_if_not_zero(MIN(node->near, gProjectionMaxNearValue), gOverrideNear);
f32 far = replace_value_if_not_zero(node->far, gOverrideFar);
+
+ // "infinite" draw distance
+ if (gOverrideFar == 0 && configDrawDistance == 6) { far = max(far, MAX_FAR_PLANE_DIST); }
+
guPerspective(mtx, &perspNorm, node->prevFov, aspect, near, far, 1.0f);
sPerspectiveNode = node;
@@ -1139,7 +1149,7 @@ static void anim_process(Vec3f translation, Vec3s rotation, Vec3f scale, u8 *ani
scale[2] *= ((f32) scaleZ) / 256.0f;
}
}
-
+
if (gCurAnim->flags & ANIM_FLAG_BONE_TRANS) {
*animType = ANIM_TYPE_TRANSLATION;
}
@@ -1459,7 +1469,7 @@ static s32 obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) {
// makes PU travel safe when the camera is locked on the main map.
// If Mario were rendered with a depth over 65536 it would cause overflow
// when converting the transformation matrix to a fixed point matrix.
- if (matrix[3][2] < -20000.0f - cullingRadius) {
+ if (configDrawDistance != 6 && matrix[3][2] < -20000.0f - cullingRadius) {
return FALSE;
}
diff --git a/src/pc/configfile.c b/src/pc/configfile.c
index 8873966f7..7f210a52c 100644
--- a/src/pc/configfile.c
+++ b/src/pc/configfile.c
@@ -89,7 +89,7 @@ bool configShowPing = false;
enum RefreshRateMode configFramerateMode = RRM_AUTO;
unsigned int configFrameLimit = 60;
unsigned int configInterpolationMode = 1;
-unsigned int configDrawDistance = 4;
+unsigned int configDrawDistance = 6;
// sound settings
unsigned int configMasterVolume = 80; // 0 - MAX_VOLUME
unsigned int configMusicVolume = MAX_VOLUME;
diff --git a/src/pc/djui/djui_panel_display.c b/src/pc/djui/djui_panel_display.c
index fccf76752..d12e0f3ba 100644
--- a/src/pc/djui/djui_panel_display.c
+++ b/src/pc/djui/djui_panel_display.c
@@ -129,8 +129,16 @@ void djui_panel_display_create(struct DjuiBase* caller) {
djui_selectionbox_create(body, DLANG(DISPLAY, ANTIALIASING), msaaChoices, choiceCount, &sMsaaSelection, djui_panel_display_msaa_change);
}
- char* drawDistanceChoices[6] = { DLANG(DISPLAY, D0P5X), DLANG(DISPLAY, D1X), DLANG(DISPLAY, D1P5X), DLANG(DISPLAY, D3X), DLANG(DISPLAY, D10X), DLANG(DISPLAY, D100X) };
- djui_selectionbox_create(body, DLANG(DISPLAY, DRAW_DISTANCE), drawDistanceChoices, 6, &configDrawDistance, NULL);
+ char* drawDistanceChoices[] = {
+ DLANG(DISPLAY, D0P5X),
+ DLANG(DISPLAY, D1X),
+ DLANG(DISPLAY, D1P5X),
+ DLANG(DISPLAY, D3X),
+ DLANG(DISPLAY, D10X),
+ DLANG(DISPLAY, D100X),
+ DLANG(DISPLAY, INFINITE),
+ };
+ djui_selectionbox_create(body, DLANG(DISPLAY, DRAW_DISTANCE), drawDistanceChoices, ARRAY_COUNT(drawDistanceChoices), &configDrawDistance, NULL);
djui_button_create(body, DLANG(MENU, BACK), DJUI_BUTTON_STYLE_BACK, djui_panel_menu_back);
diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c
index 86c6d90df..b0c76d8e3 100644
--- a/src/pc/lua/smlua_functions_autogen.c
+++ b/src/pc/lua/smlua_functions_autogen.c
@@ -9889,6 +9889,21 @@ int smlua_func_position_based_random_float_position(UNUSED lua_State* L) {
return 1;
}
+int smlua_func_draw_distance_scalar_is_infinite(UNUSED lua_State* L) {
+ if (L == NULL) { return 0; }
+
+ int top = lua_gettop(L);
+ if (top != 0) {
+ LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "draw_distance_scalar_is_infinite", 0, top);
+ return 0;
+ }
+
+
+ lua_pushboolean(L, draw_distance_scalar_is_infinite());
+
+ return 1;
+}
+
int smlua_func_draw_distance_scalar(UNUSED lua_State* L) {
if (L == NULL) { return 0; }
@@ -37695,6 +37710,7 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "obj_update_gfx_pos_and_angle", smlua_func_obj_update_gfx_pos_and_angle);
smlua_bind_function(L, "position_based_random_u16", smlua_func_position_based_random_u16);
smlua_bind_function(L, "position_based_random_float_position", smlua_func_position_based_random_float_position);
+ smlua_bind_function(L, "draw_distance_scalar_is_infinite", smlua_func_draw_distance_scalar_is_infinite);
smlua_bind_function(L, "draw_distance_scalar", smlua_func_draw_distance_scalar);
// behavior_table.h