Client_RPG v1: top-down overlay, protocol 2, HUD hotkeys
This commit is contained in:
1 parent
a70b400ccd
commit
3d6815ae9f
4 files changed
+457
-1
No files matched your search
@@ -1,3 +1,18 @@
|
|||||||
# Client_RPG
|
# Client_RPG
|
||||||
|
|
||||||
Top-down client for GameMode_RPG
|
Required client add-on for **GameMode_RPG**: top-down orbit camera, click-to-move/combat, HUD and `/rpg` window hotkeys.
|
||||||
|
|
||||||
|
Install into `Add-Ons/Client_RPG` (same folder name as on the server).
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
| Input | Action |
|
||||||
|
|---|---|
|
||||||
|
| Left click | Walk / attack / interact (server resolves the ray) |
|
||||||
|
| Right click | Talk / context |
|
||||||
|
| A/D, arrows | Rotate camera |
|
||||||
|
| PgUp/PgDn, +/- | Zoom |
|
||||||
|
| B / K / E | Bag / skills / equip lists |
|
||||||
|
| R | Toggle auto-retaliate |
|
||||||
|
|
||||||
|
Protocol version **2** — must match `GameMode_RPG` ui/protocol.cs.
|
||||||
@@ -0,0 +1,367 @@
|
|||||||
|
// 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;
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_Mouse::onMouseDown(%this, %modifier, %mouseClick, %mousePos, %button)
|
||||||
|
{
|
||||||
|
if (!$RPGClient::Active)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RPGClient_SendClick(%button, %mousePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_Mouse::onRightMouseDown(%this, %modifier, %mouseClick, %mousePos, %button)
|
||||||
|
{
|
||||||
|
if (!$RPGClient::Active)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RPGClient_SendClick(1, %mousePos);
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_EnableOverlay()
|
||||||
|
{
|
||||||
|
if (!isObject(PlayGui) || isObject(RPGClient_Mouse))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RPGClient_Mouse = new GuiMouseEventCtrl(RPGClient_Mouse)
|
||||||
|
{
|
||||||
|
horizSizing = "width";
|
||||||
|
vertSizing = "height";
|
||||||
|
position = "0 0";
|
||||||
|
extent = "640 480";
|
||||||
|
profile = "GuiDefaultProfile";
|
||||||
|
visible = "1";
|
||||||
|
enabled = "1";
|
||||||
|
};
|
||||||
|
PlayGui.add(RPGClient_Mouse);
|
||||||
|
RPGClient_Mouse.pushToBack();
|
||||||
|
if (isObject(RPGClient_KeyMap))
|
||||||
|
{
|
||||||
|
RPGClient_KeyMap.delete();
|
||||||
|
}
|
||||||
|
RPGClient_KeyMap = 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, pgup, RPGClient_ZoomIn);
|
||||||
|
RPGClient_KeyMap.bind(keyboard0, pgdn, RPGClient_ZoomOut);
|
||||||
|
RPGClient_KeyMap.bind(keyboard0, equals, RPGClient_ZoomIn);
|
||||||
|
RPGClient_KeyMap.bind(keyboard0, minus, RPGClient_ZoomOut);
|
||||||
|
Canvas.pushDialog(RPGClient_Mouse, 0);
|
||||||
|
RPGClient_KeyMap.push();
|
||||||
|
if (isObject(PlayGui))
|
||||||
|
{
|
||||||
|
PlayGui.killToolHud();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_DisableOverlay()
|
||||||
|
{
|
||||||
|
if (isObject(RPGClient_KeyMap))
|
||||||
|
{
|
||||||
|
RPGClient_KeyMap.pop();
|
||||||
|
}
|
||||||
|
if (isObject(RPGClient_Mouse))
|
||||||
|
{
|
||||||
|
Canvas.popDialog(RPGClient_Mouse);
|
||||||
|
RPGClient_Mouse.delete();
|
||||||
|
}
|
||||||
|
$RPGClient::Active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_ApplyCamera()
|
||||||
|
{
|
||||||
|
if (!isObject(localClientConnection) || !isObject(localClientConnection.player))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
%body = localClientConnection.player;
|
||||||
|
%cam = localClientConnection.getControlObject();
|
||||||
|
if (!isObject(%cam) || %cam.getClassName() !$= "Camera")
|
||||||
|
{
|
||||||
|
%cam = localClientConnection.camera;
|
||||||
|
}
|
||||||
|
if (!isObject(%cam))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
localClientConnection.setControlObject(%cam);
|
||||||
|
%rot = "0 0" SPC mSin($RPGClient::Yaw / 2) SPC mCos($RPGClient::Yaw / 2);
|
||||||
|
%cam.setOrbitMode(%body, %body.getTransform(), 4, 32, $RPGClient::Dist);
|
||||||
|
%cam.thirdPersonOnly = 1;
|
||||||
|
commandToServer('RPG_CamSync', $RPGClient::Yaw, $RPGClient::Dist);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 clientCmdRPG_Probe()
|
||||||
|
{
|
||||||
|
if (isObject(serverConnection))
|
||||||
|
{
|
||||||
|
commandToServer('RPG_Hello', $RPGClient::Version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clientCmdRPG_Welcome(%serverProto, %accepted)
|
||||||
|
{
|
||||||
|
if (%accepted && %serverProto == $RPGClient::Version)
|
||||||
|
{
|
||||||
|
$RPGClient::Server = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clientCmdRPG_TopDown(%on, %yaw, %dist)
|
||||||
|
{
|
||||||
|
if (%on)
|
||||||
|
{
|
||||||
|
$RPGClient::Active = 1;
|
||||||
|
$RPGClient::Yaw = %yaw;
|
||||||
|
$RPGClient::Dist = %dist > 0 ? %dist : 14;
|
||||||
|
RPGClient_EnableOverlay();
|
||||||
|
RPGClient_BindKeys();
|
||||||
|
schedule(50, 0, RPGClient_ApplyCamera);
|
||||||
|
schedule(200, 0, RPGClient_ApplyCamera);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
RPGClient_Hud = new GuiTextCtrl()
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (isObject(RPGClient_List))
|
||||||
|
{
|
||||||
|
RPGClient_List.delete();
|
||||||
|
}
|
||||||
|
RPGClient_List = "";
|
||||||
|
RPGClient_ListTitle = %title @ " (" @ (%page + 1) @ "/" @ %pages @ ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_List_Row(%row)
|
||||||
|
{
|
||||||
|
RPGClient_List = RPGClient_List @ %row @ "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_List_End()
|
||||||
|
{
|
||||||
|
if (RPGClient_List !$= "")
|
||||||
|
{
|
||||||
|
messageBoxOK(RPGClient_ListTitle, RPGClient_List, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package RPGClient_Disconnect
|
||||||
|
{
|
||||||
|
function disconnect()
|
||||||
|
{
|
||||||
|
RPGClient_DisableOverlay();
|
||||||
|
Parent::disconnect();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
activatePackage(RPGClient_Disconnect);
|
||||||
|
|
||||||
|
echo("Client_RPG loaded (protocol " @ $RPGClient::Version @ ")");
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Client_RPG
|
||||||
|
Required client add-on for the GameMode_RPG realm: top-down camera, click-to-move and combat, and the RPG windows. Without it you can only spectate on an RPG server.
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// Client windows: hotkeys open /rpg lists; the server still validates every command.
|
||||||
|
|
||||||
|
$RPGClient::MenuOpen = 0;
|
||||||
|
|
||||||
|
function RPGClient_RunCmd(%cmd)
|
||||||
|
{
|
||||||
|
if (!isObject(serverConnection))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
commandToServer('message', "/rpg " @ %cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_ToggleMenu(%name, %cmd)
|
||||||
|
{
|
||||||
|
if ($RPGClient::MenuOpen $= %name)
|
||||||
|
{
|
||||||
|
$RPGClient::MenuOpen = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$RPGClient::MenuOpen = %name;
|
||||||
|
RPGClient_RunCmd(%cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_Menu_Bag()
|
||||||
|
{
|
||||||
|
RPGClient_ToggleMenu("bag", "bag");
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_Menu_Skills()
|
||||||
|
{
|
||||||
|
RPGClient_ToggleMenu("skills", "skills");
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_Menu_Equip()
|
||||||
|
{
|
||||||
|
RPGClient_ToggleMenu("equip", "equip");
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_Menu_Help()
|
||||||
|
{
|
||||||
|
RPGClient_RunCmd("help");
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_Menu_Retaliate()
|
||||||
|
{
|
||||||
|
RPGClient_RunCmd("retaliate");
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_BindKeys()
|
||||||
|
{
|
||||||
|
if (isObject(RPGClient_MenuMap))
|
||||||
|
{
|
||||||
|
RPGClient_MenuMap.delete();
|
||||||
|
}
|
||||||
|
RPGClient_MenuMap = new ActionMap("RPGClient_MenuMap");
|
||||||
|
RPGClient_MenuMap.bind(keyboard0, b, RPGClient_Menu_Bag);
|
||||||
|
RPGClient_MenuMap.bind(keyboard0, k, RPGClient_Menu_Skills);
|
||||||
|
RPGClient_MenuMap.bind(keyboard0, e, RPGClient_Menu_Equip);
|
||||||
|
RPGClient_MenuMap.bind(keyboard0, f1, RPGClient_Menu_Help);
|
||||||
|
RPGClient_MenuMap.bind(keyboard0, r, RPGClient_Menu_Retaliate);
|
||||||
|
RPGClient_MenuMap.push();
|
||||||
|
}
|
||||||
|
|
||||||
|
function RPGClient_UnbindKeys()
|
||||||
|
{
|
||||||
|
if (isObject(RPGClient_MenuMap))
|
||||||
|
{
|
||||||
|
RPGClient_MenuMap.pop();
|
||||||
|
RPGClient_MenuMap.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user