diff --git a/client.cs b/client.cs index e1190d5..9fd497b 100644 --- a/client.cs +++ b/client.cs @@ -26,6 +26,8 @@ $RPGClient::YawSpeed = 0.045; $RPGClient::ZoomSpeed = 0.12; $RPGClient::CamTickSched = 0; $RPGClient::LastCamSync = 0; +$RPGClient::CamSyncMs = 100; +$RPGClient::TopDownFov = 0.85; $RPGClient::MvF = 0; $RPGClient::MvB = 0; $RPGClient::MvL = 0; @@ -135,6 +137,113 @@ function RPGClient_Aspect() return %h > 0 ? %w / %h : 1.333; } +function RPGClient_V3Len(%x, %y, %z) +{ + return mSqrt(%x * %x + %y * %y + %z * %z); +} + +function RPGClient_V3Norm(%x, %y, %z) +{ + %l = RPGClient_V3Len(%x, %y, %z); + if (%l < 0.0001) + { + return "0 0 0"; + } + return (%x / %l) @ " " @ (%y / %l) @ " " @ (%z / %l); +} + +function RPGClient_V3Cross(%ax, %ay, %az, %bx, %by, %bz) +{ + return (%ay * %bz - %az * %by) @ " " @ (%az * %bx - %ax * %bz) @ " " @ (%ax * %by - %ay * %bx); +} + +function RPGClient_EyeRay(%nx, %ny) +{ + %conn = RPGClient_GetConn(); + %body = RPGClient_BodyForCamera(%conn); + if (!isObject(%body)) + { + return ""; + } + %p = %body.getPosition(); + %cx = getWord(%p, 0) + $RPGClient::PanX; + %cy = getWord(%p, 1) + $RPGClient::PanY; + %cz = getWord(%p, 2) + 1.5; + %yaw = $RPGClient::Yaw; + %dist = $RPGClient::Dist; + %pitch = $RPGClient::Pitch > 0 ? $RPGClient::Pitch : $RPGClient::TopDownPitch; + %bx = -mCos(%yaw) * mCos(%pitch) * %dist; + %by = -mSin(%yaw) * mCos(%pitch) * %dist; + %bz = mSin(%pitch) * %dist; + %ex = %cx + %bx; + %ey = %cy + %by; + %ez = %cz + %bz; + %fx = %cx - %ex; + %fy = %cy - %ey; + %fz = %cz - %ez; + %fwd = RPGClient_V3Norm(%fx, %fy, %fz); + %fw = getWord(%fwd, 0); + %fh = getWord(%fwd, 1); + %ff = getWord(%fwd, 2); + %right = RPGClient_V3Norm(getWord(RPGClient_V3Cross(%fw, %fh, %ff, 0, 0, 1), 0), getWord(RPGClient_V3Cross(%fw, %fh, %ff, 0, 0, 1), 1), getWord(RPGClient_V3Cross(%fw, %fh, %ff, 0, 0, 1), 2)); + %rw = getWord(%right, 0); + %rh = getWord(%right, 1); + %rf = getWord(%right, 2); + %up = RPGClient_V3Norm(getWord(RPGClient_V3Cross(%rw, %rh, %rf, %fw, %fh, %ff), 0), getWord(RPGClient_V3Cross(%rw, %rh, %rf, %fw, %fh, %ff), 1), getWord(RPGClient_V3Cross(%rw, %rh, %rf, %fw, %fh, %ff), 2)); + %uw = getWord(%up, 0); + %uh = getWord(%up, 1); + %uf = getWord(%up, 2); + %fov = mTan($RPGClient::TopDownFov * 0.5); + %aspect = RPGClient_Aspect(); + %rx = (%nx - 0.5) * 2 * %fov * %aspect; + %ry = (0.5 - %ny) * 2 * %fov; + %dx = %fw + %rw * %rx + %uw * %ry; + %dy = %fh + %rh * %rx + %uh * %ry; + %dz = %ff + %rf * %rx + %uf * %ry; + %dir = RPGClient_V3Norm(%dx, %dy, %dz); + %dw = getWord(%dir, 0); + %dh = getWord(%dir, 1); + %df = getWord(%dir, 2); + %eye = %ex @ " " @ %ey @ " " @ %ez; + return %eye TAB (%ex + %dw * 250) @ " " @ (%ey + %dh * 250) @ " " @ (%ez + %df * 250); +} + +function RPGClient_PickGround(%nx, %ny) +{ + %conn = RPGClient_GetConn(); + %body = RPGClient_BodyForCamera(%conn); + if (!isObject(%body)) + { + return ""; + } + %ray = RPGClient_EyeRay(%nx, %ny); + if (%ray $= "") + { + return ""; + } + %eye = getField(%ray, 0) SPC getField(%ray, 1) SPC getField(%ray, 2); + %end = getField(%ray, 3) SPC getField(%ray, 4) SPC getField(%ray, 5); + %ex = getWord(%eye, 0); + %ey = getWord(%eye, 1); + %ez = getWord(%eye, 2); + %dx = getWord(%end, 0) - %ex; + %dy = getWord(%end, 1) - %ey; + %dz = getWord(%end, 2) - %ez; + %dir = RPGClient_V3Norm(%dx, %dy, %dz); + %dzw = getWord(%dir, 2); + %refZ = getWord(%body.getPosition(), 2); + if (mAbs(%dzw) < 0.02) + { + return ""; + } + %t = (%refZ - %ez) / %dzw; + if (%t < 0 || %t > 400) + { + return ""; + } + return (%ex + getWord(%dir, 0) * %t) @ " " @ (%ey + getWord(%dir, 1) * %t) @ " " @ %refZ; +} + function RPGClient_SendClick(%button, %pos) { if (!isObject(ServerConnection)) @@ -148,8 +257,18 @@ function RPGClient_SendClick(%button, %pos) } $RPGClient::LastClickTime = %now; %norm = RPGClient_NormScreenPos(%pos); - commandToServer('RPG_Click', %button, getWord(%norm, 0), getWord(%norm, 1), RPGClient_Aspect()); - schedule(1, 0, RPGClient_ApplyCamera, 1); + %nx = getWord(%norm, 0); + %ny = getWord(%norm, 1); + if (%button == 0) + { + %gnd = RPGClient_PickGround(%nx, %ny); + if (%gnd !$= "") + { + commandToServer('RPG_Go', getWord(%gnd, 0), getWord(%gnd, 1), getWord(%gnd, 2)); + return; + } + } + commandToServer('RPG_Click', %button, %nx, %ny, RPGClient_Aspect(), $RPGClient::Yaw, $RPGClient::Dist, $RPGClient::Pitch, $RPGClient::PanX, $RPGClient::PanY); } function RPGClient_Mouse::onMouseDown(%this, %mod, %pos, %clicks) @@ -250,26 +369,6 @@ function RPGClient_CameraTick() %tilt = $RPGClient::PitchSpeed * 2.5; %zoom = $RPGClient::ZoomSpeed * 2.5; %changed = 0; - if ($mvLeftAction > 0) - { - $RPGClient::Yaw = $RPGClient::Yaw - %spin * $mvLeftAction; - %changed = 1; - } - if ($mvRightAction > 0) - { - $RPGClient::Yaw = $RPGClient::Yaw + %spin * $mvRightAction; - %changed = 1; - } - if ($mvForwardAction > 0) - { - $RPGClient::Pitch = getMin($RPGClient::PitchMax, $RPGClient::Pitch + %tilt * $mvForwardAction); - %changed = 1; - } - if ($mvBackwardAction > 0) - { - $RPGClient::Pitch = getMax($RPGClient::PitchMin, $RPGClient::Pitch - %tilt * $mvBackwardAction); - %changed = 1; - } if ($RPGClient::MvL > 0) { $RPGClient::Yaw = $RPGClient::Yaw - %spin * $RPGClient::MvL; @@ -290,14 +389,17 @@ function RPGClient_CameraTick() $RPGClient::Pitch = getMax($RPGClient::PitchMin, $RPGClient::Pitch - %tilt * $RPGClient::MvB); %changed = 1; } - RPGClient_ApplyCamera(%changed || $RPGClient::MvF || $RPGClient::MvB || $RPGClient::MvL || $RPGClient::MvR); - $RPGClient::CamTickSched = schedule(32, 0, RPGClient_CameraTick); + if (%changed || $RPGClient::MvF || $RPGClient::MvB || $RPGClient::MvL || $RPGClient::MvR) + { + RPGClient_ApplyCamera(0); + } + $RPGClient::CamTickSched = schedule(50, 0, RPGClient_CameraTick); } function RPGClient_StartCameraTick() { cancel($RPGClient::CamTickSched); - $RPGClient::CamTickSched = schedule(32, 0, RPGClient_CameraTick); + $RPGClient::CamTickSched = schedule(50, 0, RPGClient_CameraTick); } function RPGClient_InPlay() @@ -383,10 +485,6 @@ function RPGClient_KeyMvForward(%val) return; } $RPGClient::MvF = %val; - if (%val) - { - RPGClient_ApplyCamera(1); - } } function RPGClient_KeyMvBackward(%val) @@ -405,10 +503,6 @@ function RPGClient_KeyMvBackward(%val) return; } $RPGClient::MvB = %val; - if (%val) - { - RPGClient_ApplyCamera(1); - } } function RPGClient_KeyMvLeft(%val) @@ -427,10 +521,6 @@ function RPGClient_KeyMvLeft(%val) return; } $RPGClient::MvL = %val; - if (%val) - { - RPGClient_ApplyCamera(1); - } } function RPGClient_KeyMvRight(%val) @@ -449,10 +539,6 @@ function RPGClient_KeyMvRight(%val) return; } $RPGClient::MvR = %val; - if (%val) - { - RPGClient_ApplyCamera(1); - } } function RPGClient_StockMoveMapBinds() @@ -597,7 +683,7 @@ function RPGClient_Hud_Place() function RPGClient_ApplyCamera(%forceSync) { %now = getSimTime(); - %doSync = %forceSync || %now - $RPGClient::LastCamSync >= 40; + %doSync = %forceSync || %now - $RPGClient::LastCamSync >= $RPGClient::CamSyncMs; if (!%doSync || !isObject(ServerConnection)) { return; @@ -647,11 +733,7 @@ function RPGClient_ApplyCamera(%forceSync) function RPGClient_ScheduleCamera() { cancel($RPGClient::CamSched); - $RPGClient::CamSched = schedule(50, 0, RPGClient_ApplyCamera, 0); - schedule(200, 0, RPGClient_ApplyCamera, 0); - schedule(500, 0, RPGClient_ApplyCamera, 0); - schedule(1200, 0, RPGClient_ApplyCamera, 0); - schedule(2500, 0, RPGClient_ApplyCamera, 0); + RPGClient_ApplyCamera(1); } function RPGClient_YawLeft(%val) @@ -665,10 +747,6 @@ function RPGClient_YawLeft(%val) return; } $RPGClient::MvL = %val; - if (%val) - { - RPGClient_ApplyCamera(1); - } } function RPGClient_YawRight(%val) @@ -682,10 +760,6 @@ function RPGClient_YawRight(%val) return; } $RPGClient::MvR = %val; - if (%val) - { - RPGClient_ApplyCamera(1); - } } function RPGClient_ZoomIn(%val) @@ -883,7 +957,6 @@ function clientCmdRPG_TopDown(%on, %yaw, %dist) RPGClient_StartCameraTick(); schedule(500, 0, RPGClient_EnsureOverlay); schedule(1500, 0, RPGClient_EnsureOverlay); - RPGClient_ScheduleCamera(); RPGClient_EnsureCursor(); RPGClient_Hud_Ensure(); } @@ -1156,7 +1229,7 @@ package RPGClient_Input { %sens = $pref::Input::MouseSensitivity; $RPGClient::Yaw = $RPGClient::Yaw + %val * %sens * 0.004; - RPGClient_ApplyCamera(1); + RPGClient_ApplyCamera(0); return; } Parent::yaw(%val);