Files
Client_RPG/client.cs
T

540 lines
11 KiB
C#

// Client_RPG - top-down camera, click-to-move, and RPG windows for GameMode_RPG.
exec("./ui.cs");
// The server probes with RPG_Probe; reply with serverCmdRPG_Hello(2) to play.
$RPGClient::Version = 2;
$RPGClient::Active = 0;
$RPGClient::Yaw = 0;
$RPGClient::Dist = 14;
$RPGClient::HelloPending = 0;
$RPGClient::HelloLast = "";
$RPGClient::TopDownWatchSched = 0;
$RPGClient::CamSched = 0;
function RPGClient_NormPos(%ctrl, %pos)
{
if (!isObject(%ctrl))
{
return "0.5 0.5";
}
%ext = %ctrl.getExtent();
%w = getWord(%ext, 0);
%h = getWord(%ext, 1);
if (%w < 1)
{
%w = 1;
}
if (%h < 1)
{
%h = 1;
}
%x = getWord(%pos, 0) / %w;
%y = 1 - getWord(%pos, 1) / %h;
if (%x < 0)
{
%x = 0;
}
if (%x > 1)
{
%x = 1;
}
if (%y < 0)
{
%y = 0;
}
if (%y > 1)
{
%y = 1;
}
return %x SPC %y;
}
function RPGClient_Aspect()
{
if (!isObject(Canvas))
{
return 1.333;
}
%ext = Canvas.getExtent();
%w = getWord(%ext, 0);
%h = getWord(%ext, 1);
return %h > 0 ? %w / %h : 1.333;
}
function RPGClient_SendClick(%button, %pos)
{
if (!isObject(ServerConnection))
{
return;
}
%norm = RPGClient_NormPos(RPGClient_Mouse, %pos);
commandToServer('RPG_Click', %button, getWord(%norm, 0), getWord(%norm, 1), RPGClient_Aspect());
schedule(1, 0, RPGClient_ApplyCamera);
}
function RPGClient_Mouse::onMouseDown(%this, %mod, %pos, %clicks)
{
if (!$RPGClient::Active)
{
return;
}
RPGClient_SendClick(0, %pos);
}
function RPGClient_Mouse::onRightMouseDown(%this, %mod, %pos, %clicks)
{
if (!$RPGClient::Active)
{
return;
}
RPGClient_SendClick(1, %pos);
}
function RPGClient_Mouse::onWake(%this)
{
if (isObject(Canvas))
{
%ext = Canvas.getExtent();
%this.resize(0, 0, getWord(%ext, 0), getWord(%ext, 1));
}
}
function RPGClient_BlockMouse(%val)
{
}
function RPGClient_EnableOverlay()
{
if (!isObject(PlayGui) || isObject(RPGClient_Mouse))
{
return;
}
new GuiMouseEventCtrl(RPGClient_Mouse)
{
className = "RPGClient_Mouse";
horizSizing = "width";
vertSizing = "height";
position = "0 0";
extent = "640 480";
profile = "GuiDefaultProfile";
visible = "1";
enabled = "1";
};
PlayGui.add(RPGClient_Mouse);
PlayGui.pushToBack(RPGClient_Mouse);
if (isObject(RPGClient_KeyMap))
{
RPGClient_KeyMap.delete();
}
new ActionMap(RPGClient_KeyMap);
RPGClient_KeyMap.bind(keyboard0, a, RPGClient_YawLeft);
RPGClient_KeyMap.bind(keyboard0, d, RPGClient_YawRight);
RPGClient_KeyMap.bind(keyboard0, left, RPGClient_YawLeft);
RPGClient_KeyMap.bind(keyboard0, right, RPGClient_YawRight);
RPGClient_KeyMap.bind(keyboard0, "pageup", RPGClient_ZoomIn);
RPGClient_KeyMap.bind(keyboard0, "pagedown", RPGClient_ZoomOut);
RPGClient_KeyMap.bind(keyboard0, equals, RPGClient_ZoomIn);
RPGClient_KeyMap.bind(keyboard0, minus, RPGClient_ZoomOut);
RPGClient_KeyMap.bind(keyboard0, m, RPGClient_ToggleCursor);
RPGClient_KeyMap.bind(mouse0, button0, RPGClient_BlockMouse);
RPGClient_KeyMap.bind(mouse0, button1, RPGClient_BlockMouse);
RPGClient_KeyMap.push();
$mvFreeLook = 0;
$firstPerson = 0;
if (isObject(Canvas) && !Canvas.isCursorOn())
{
Canvas.cursorOn();
}
if (isObject(PlayGui))
{
PlayGui.killToolHud();
}
}
function RPGClient_ToggleCursor(%val)
{
if (!$RPGClient::Active || !%val)
{
return;
}
ToggleCursor(%val);
}
function RPGClient_DisableOverlay()
{
cancel($RPGClient::CamSched);
$RPGClient::CamSched = 0;
if (isObject(RPGClient_KeyMap))
{
RPGClient_KeyMap.pop();
}
if (isObject(RPGClient_Mouse))
{
RPGClient_Mouse.delete();
}
$RPGClient::Active = 0;
}
function RPGClient_ApplyCamera()
{
%conn = RPGClient_GetConn();
if (!isObject(%conn))
{
return;
}
%body = %conn.Player;
if (!isObject(%body))
{
%body = %conn.player;
}
if (!isObject(%body))
{
return;
}
%cam = %conn.getControlObject();
if (!isObject(%cam) || %cam.getClassName() !$= "Camera")
{
%cam = %conn.Camera;
if (!isObject(%cam))
{
%cam = %conn.camera;
}
}
if (!isObject(%cam))
{
return;
}
%conn.setControlObject(%cam);
$mvFreeLook = 0;
$firstPerson = 0;
%cam.unmountImage(0);
%cam.setMode("Corpse", %body);
%cam.setOrbitMode(%body, %cam.getTransform(), 0, 32, $RPGClient::Dist);
%cam.mode = "Corpse";
%cam.thirdPersonOnly = 1;
commandToServer('RPG_CamSync', $RPGClient::Yaw, $RPGClient::Dist);
}
function RPGClient_ScheduleCamera()
{
cancel($RPGClient::CamSched);
$RPGClient::CamSched = schedule(50, 0, RPGClient_ApplyCamera);
schedule(200, 0, RPGClient_ApplyCamera);
schedule(500, 0, RPGClient_ApplyCamera);
schedule(1200, 0, RPGClient_ApplyCamera);
schedule(2500, 0, RPGClient_ApplyCamera);
}
function RPGClient_YawLeft(%val)
{
if (!$RPGClient::Active || %val == 0)
{
return;
}
$RPGClient::Yaw = $RPGClient::Yaw - 0.06;
RPGClient_ApplyCamera();
}
function RPGClient_YawRight(%val)
{
if (!$RPGClient::Active || %val == 0)
{
return;
}
$RPGClient::Yaw = $RPGClient::Yaw + 0.06;
RPGClient_ApplyCamera();
}
function RPGClient_ZoomIn(%val)
{
if (!$RPGClient::Active || %val == 0)
{
return;
}
$RPGClient::Dist = getMax(6, $RPGClient::Dist - 0.6);
RPGClient_ApplyCamera();
}
function RPGClient_ZoomOut(%val)
{
if (!$RPGClient::Active || %val == 0)
{
return;
}
$RPGClient::Dist = getMin(32, $RPGClient::Dist + 0.6);
RPGClient_ApplyCamera();
}
function RPGClient_CanSendCmd()
{
return isObject(ServerConnection) || isObject(localClientConnection);
}
function RPGClient_GetConn()
{
if (isObject(ServerConnection))
{
return ServerConnection;
}
if (isObject(localClientConnection))
{
return localClientConnection;
}
return 0;
}
function RPGClient_SendHello()
{
if ($RPGClient::Server)
{
return;
}
if (!RPGClient_CanSendCmd())
{
return;
}
%now = getSimTime();
if ($RPGClient::HelloLast !$= "" && %now - $RPGClient::HelloLast < 900)
{
return;
}
$RPGClient::HelloLast = %now;
commandToServer('RPG_Hello', $RPGClient::Version);
commandToServer('RPGHello', $RPGClient::Version);
commandToServer('Message', "/rpg clienthello " @ $RPGClient::Version);
}
function clientCmdRPG_Probe()
{
RPGClient_SendHello();
}
function clientCmdRPG_Welcome(%serverProto, %accepted)
{
if (%accepted && %serverProto == $RPGClient::Version)
{
$RPGClient::HelloPending = 0;
schedule(2500, 0, RPGClient_TopDownWatch);
}
else if (!%accepted)
{
echo("Client_RPG: server rejected handshake (server proto " @ %serverProto @ ")");
schedule(1500, 0, RPGClient_SendHello);
}
}
function RPGClient_TopDownWatch()
{
$RPGClient::TopDownWatchSched = 0;
if ($RPGClient::Active || $RPGClient::Server || !RPGClient_CanSendCmd())
{
return;
}
$RPGClient::HelloLast = "";
RPGClient_SendHello();
$RPGClient::TopDownWatchSched = schedule(2500, 0, RPGClient_TopDownWatch);
}
function RPGClient_EnsurePlayGui()
{
if (!isObject(PlayGui) || !isObject(Canvas))
{
return 0;
}
if (Canvas.getContent() != PlayGui.getId())
{
Canvas.setContent(PlayGui);
}
return 1;
}
function clientCmdRPG_TopDown(%on, %yaw, %dist)
{
if (%on && !RPGClient_EnsurePlayGui())
{
schedule(200, 0, clientCmdRPG_TopDown, %on, %yaw, %dist);
return;
}
if (%on)
{
cancel($RPGClient::TopDownWatchSched);
$RPGClient::TopDownWatchSched = 0;
$RPGClient::Server = 1;
$RPGClient::Active = 1;
$RPGClient::Yaw = %yaw;
$RPGClient::Dist = %dist > 0 ? %dist : 14;
RPGClient_EnableOverlay();
RPGClient_BindKeys();
RPGClient_ScheduleCamera();
}
else
{
RPGClient_DisableOverlay();
RPGClient_UnbindKeys();
}
}
function clientCmdRPG_Hud(%hp, %maxHp, %silver, %load, %cap, %skillId, %skillValue, %blocking, %tHp, %tMax)
{
RPGClient_Hud_Update(%hp, %maxHp, %silver, %load, %cap, %skillId, %skillValue, %tHp, %tMax);
}
function clientCmdRPG_HudOff()
{
RPGClient_Hud_Hide();
}
function clientCmdRPG_Notify(%text, %sec)
{
if (%text !$= "")
{
RPGClient_Notify_Show(%text, %sec);
}
}
function clientCmdRPG_Dialog(%title, %body, %sec)
{
RPGClient_Dialog_Show(%title, %body, %sec);
}
function clientCmdRPG_ListBegin(%title, %page, %pages)
{
RPGClient_List_Begin(%title, %page, %pages);
}
function clientCmdRPG_ListRow(%row)
{
RPGClient_List_Row(%row);
}
function clientCmdRPG_ListEnd()
{
RPGClient_List_End();
}
// --- HUD / list / dialog (Phase 4): thin windows on PlayGui ---
function RPGClient_Hud_Ensure()
{
if (isObject(RPGClient_Hud))
{
return;
}
new GuiTextCtrl(RPGClient_Hud)
{
horizSizing = "width";
vertSizing = "top";
position = "8 8";
extent = "600 24";
profile = "ChatHudMessageProfile";
text = "";
};
PlayGui.add(RPGClient_Hud);
}
function RPGClient_Hud_Update(%hp, %maxHp, %silver, %load, %cap, %skillId, %skillValue, %tHp, %tMax)
{
if (!$RPGClient::Active)
{
return;
}
RPGClient_Hud_Ensure();
%t = "";
if (%tMax > 0)
{
%t = " | Target " @ %tHp @ "/" @ %tMax;
}
RPGClient_Hud.setText("HP " @ %hp @ "/" @ %maxHp @ %t @ " | " @ %silver @ " silver | load " @ %load @ "/" @ %cap @ " | " @ %skillId @ " " @ %skillValue);
}
function RPGClient_Hud_Hide()
{
if (isObject(RPGClient_Hud))
{
RPGClient_Hud.setText("");
}
}
function RPGClient_Notify_Show(%text, %sec)
{
RPGClient_Hud_Ensure();
RPGClient_Hud.setText(%text);
if (%sec > 0)
{
schedule(%sec * 1000, RPGClient_Hud, setText, "");
}
}
function RPGClient_Dialog_Show(%title, %body, %sec)
{
messageBoxOK(%title, %body, "");
}
function RPGClient_List_Begin(%title, %page, %pages)
{
$RPGClient::ListBody = "";
$RPGClient::ListTitle = %title @ " (" @ (%page + 1) @ "/" @ %pages @ ")";
}
function RPGClient_List_Row(%row)
{
$RPGClient::ListBody = $RPGClient::ListBody @ %row @ "\n";
}
function RPGClient_List_End()
{
if ($RPGClient::ListBody !$= "")
{
messageBoxOK($RPGClient::ListTitle, $RPGClient::ListBody, "");
}
}
package RPGClient_BlockMouseFire
{
function mouseFire(%val)
{
if ($RPGClient::Active)
{
return;
}
Parent::mouseFire(%val);
}
function altTrigger(%val)
{
if ($RPGClient::Active)
{
return;
}
Parent::altTrigger(%val);
}
};
activatePackage(RPGClient_BlockMouseFire);
package RPGClient_Cleanup
{
function disconnectedCleanup(%doReconnect)
{
RPGClient_DisableOverlay();
RPGClient_UnbindKeys();
$RPGClient::Server = 0;
$RPGClient::HelloPending = 0;
$RPGClient::HelloLast = "";
cancel($RPGClient::TopDownWatchSched);
$RPGClient::TopDownWatchSched = 0;
Parent::disconnectedCleanup(%doReconnect);
}
};
activatePackage(RPGClient_Cleanup);
package RPGClient_Mission
{
function onMissionDownloadComplete()
{
Parent::onMissionDownloadComplete();
schedule(250, 0, RPGClient_SendHello);
}
};
activatePackage(RPGClient_Mission);
echo("Client_RPG loaded (protocol " @ $RPGClient::Version @ ")");