void ConfigureFOV() { static const double default_ratio = 4.0 / 3.0; const uint32_t width = HorizontalResolution; const uint32_t height = VerticalResolution; WriteJump(SetupScreen, SetupScreenFix); // Taking advantage of a nullsub call. WriteCall((void*)0x00513A88, DisplayVideoFrame_FixAspectRatio); // 4:3 and "tallscreen" (5:4, portrait, etc) // We don't need to do anything since these resolutions work fine with the default code. if ((height * default_ratio) == width || (height * default_ratio) > width) return; fov_rads = 0.96712852; // 55.412382 degrees fov_bams = NJM_RAD_ANG(fov_rads); // Function hooks WriteJump(njSetPerspective, njSetPerspective_hook); WriteJump(njSetScreenDist, njSetScreenDist_hook); // Code patches WriteJump((void*)0x0079124A, SetFOV); WriteData((float**)0x00781525, &dummy); // Dirty hack to disable a write to ClippingRelated and keep the floating point stack balanced. WriteData((Angle**)0x0040872B, &last_bams); // Fixes a case of direct access to HorizontalFOV_BAMS WriteData((Angle**)0x00402F01, &last_bams); // Changes return value of GetHorizontalFOV_BAMS njSetPerspective_hook(bams_default); // Stops the Pause Menu from using horizontal stretch in place of vertical stretch in coordinate calculation // Main Pause Menu WriteData((float**)0x00457F69, &VerticalStretch); // Elipse/Oval WriteData((float**)0x004584EE, &VerticalStretch); // Blue Transparent Box WriteData((float**)0x0045802F, &VerticalStretch); // Pause Menu Options // Camera options WriteData((float**)0x00458D5C, &VerticalStretch); // Blue Transparent Box WriteData((float**)0x00458DF4, &VerticalStretch); // Auto Cam WriteData((float**)0x00458E3A, &VerticalStretch); // Free Cam // Controls WriteData((float**)0x0045905A, &VerticalStretch); // Blue Transparent Box WriteData((float**)0x004590BB, &VerticalStretch); // Each Control Element WriteData((float**)0x00459133, &VerticalStretch); // Default Button }
static void DrawElement(Uint32 playerIndex, Uint32 textureIndex) { EntityData1* player = CharObj1Ptrs[playerIndex]; if (player == nullptr) return; Uint8 charid = MetalSonicFlag && player->CharID == Characters_Sonic ? Characters_MetalSonic : player->CharID; NJS_SPRITE* sp = &sprites[playerIndex]; NJS_POINT2 projected; NJS_VECTOR pos = player->Position; pos.y += PhysicsArray[charid].CollisionSize; njProjectScreen(nullptr, &pos, &projected); sp->p = { projected.x, projected.y - (sp->tanim[0].sy + sp->tanim[1].sy), 0.0f }; bool isVisible = sp->p.x < MARGIN_RIGHT && sp->p.x > MARGIN_LEFT && sp->p.y < MARGIN_BOTTOM && sp->p.y > MARGIN_TOP; ClampToScreen(sp->p); int flags = NJD_SPRITE_COLOR | NJD_SPRITE_ALPHA; sp->ang = 0; if (textureIndex == arrow) { if (!isVisible) { flags |= NJD_SPRITE_ANGLE; sp->ang = NJM_RAD_ANG(GetAngle((NJS_POINT2*)&sp->p, &projected)) - 0x4000; } // TODO: Ellipse rotation around player number sp->tanim[arrow].cy = Indicator_TEXANIM[arrow].cy - ((isVisible) ? 0 : 12); } SetSpriteColor(IsControllerEnabled((Uint8)playerIndex) ? &colors[charid] : &colors[9]); Draw2DSprite(sp, textureIndex, -1.0f, flags, 0); }