mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-19 01:02:20 +00:00
Compare commits
19 commits
73be564540
...
8ef01fcbaf
Author | SHA1 | Date | |
---|---|---|---|
8ef01fcbaf | |||
306d3c7b58 | |||
9832288983 | |||
fc058fa432 | |||
3b22a3e02f | |||
ed1ef4e694 | |||
9103332e36 | |||
0948a53648 | |||
bbd34c9452 | |||
e4282f100a | |||
eb9e73f68b | |||
e0a95d14a6 | |||
fa28ed77a6 | |||
5335813629 | |||
796fa4275f | |||
5b0163d069 | |||
c9e7e0f01b | |||
4df4fa237e | |||
5d4e6cf86a |
|
@ -1845,6 +1845,7 @@ set(EXPECTED_DATA
|
||||||
themes/winter.png
|
themes/winter.png
|
||||||
themes/winter_day.map
|
themes/winter_day.map
|
||||||
themes/winter_night.map
|
themes/winter_night.map
|
||||||
|
touch_controls.json
|
||||||
wordlist.txt
|
wordlist.txt
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -2399,6 +2400,8 @@ if(CLIENT)
|
||||||
components/statboard.h
|
components/statboard.h
|
||||||
components/tooltips.cpp
|
components/tooltips.cpp
|
||||||
components/tooltips.h
|
components/tooltips.h
|
||||||
|
components/touch_controls.cpp
|
||||||
|
components/touch_controls.h
|
||||||
components/voting.cpp
|
components/voting.cpp
|
||||||
components/voting.h
|
components/voting.h
|
||||||
gameclient.cpp
|
gameclient.cpp
|
||||||
|
|
305
data/touch_controls.json
Normal file
305
data/touch_controls.json
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
{
|
||||||
|
"direct-touch-ingame": true,
|
||||||
|
"direct-touch-spectate": true,
|
||||||
|
"touch-buttons": [
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 833333,
|
||||||
|
"w": 200000,
|
||||||
|
"h": 166667,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"ingame"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Move left",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "+left"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 200000,
|
||||||
|
"y": 833333,
|
||||||
|
"w": 200000,
|
||||||
|
"h": 166667,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"ingame"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Move right",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "+right"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 100000,
|
||||||
|
"y": 666667,
|
||||||
|
"w": 200000,
|
||||||
|
"h": 166667,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"ingame"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Jump",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "+jump"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 116667,
|
||||||
|
"y": 16667,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 83333,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"ingame"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Prev. weapon",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "+prevweapon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 200000,
|
||||||
|
"y": 16667,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 83333,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"ingame"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Next weapon",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "+nextweapon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 16667,
|
||||||
|
"y": 16667,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 83333,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "predefined",
|
||||||
|
"id": "extra-menu"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 300000,
|
||||||
|
"y": 16667,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 83333,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"extra-menu",
|
||||||
|
"zoom-allowed"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Zoom out",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "zoom-"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 383333,
|
||||||
|
"y": 16667,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 83333,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"extra-menu",
|
||||||
|
"zoom-allowed"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Default zoom",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "zoom"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 466666,
|
||||||
|
"y": 16667,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 83333,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"extra-menu",
|
||||||
|
"zoom-allowed"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Zoom in",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "zoom+"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 16667,
|
||||||
|
"y": 133333,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 66667,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"extra-menu"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Scoreboard",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "+scoreboard"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 116667,
|
||||||
|
"y": 133333,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 66667,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"ingame",
|
||||||
|
"extra-menu"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "predefined",
|
||||||
|
"id": "emoticon"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 116667,
|
||||||
|
"y": 133333,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 66667,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"-ingame",
|
||||||
|
"extra-menu"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "predefined",
|
||||||
|
"id": "spectate"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 216667,
|
||||||
|
"y": 133333,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 66667,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"extra-menu"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Chat",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "chat all"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 316667,
|
||||||
|
"y": 133333,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 66667,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"extra-menu"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Team chat",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "chat team"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 16667,
|
||||||
|
"y": 333333,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 66667,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"extra-menu",
|
||||||
|
"vote-active"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Vote yes",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "vote yes"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 116667,
|
||||||
|
"y": 333333,
|
||||||
|
"w": 83333,
|
||||||
|
"h": 66667,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"extra-menu",
|
||||||
|
"vote-active"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Vote no",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "vote no"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 766667,
|
||||||
|
"y": 16667,
|
||||||
|
"w": 100000,
|
||||||
|
"h": 100000,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"dummy-connected"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "bind",
|
||||||
|
"label": "Toggle dummy",
|
||||||
|
"label-type": "localized",
|
||||||
|
"command": "toggle cl_dummy 0 1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 883333,
|
||||||
|
"y": 16667,
|
||||||
|
"w": 100000,
|
||||||
|
"h": 100000,
|
||||||
|
"shape": "rect",
|
||||||
|
"visibilities": [
|
||||||
|
"ingame"
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "predefined",
|
||||||
|
"id": "swap-action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 755000,
|
||||||
|
"y": 580000,
|
||||||
|
"w": 225000,
|
||||||
|
"h": 400000,
|
||||||
|
"shape": "circle",
|
||||||
|
"visibilities": [
|
||||||
|
],
|
||||||
|
"behavior": {
|
||||||
|
"type": "predefined",
|
||||||
|
"id": "joystick-action"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,15 +1,40 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:installLocation="auto">
|
||||||
|
|
||||||
<!-- Vulkan 1.1.0 is used if supported -->
|
<!-- Vulkan 1.1.0 is used if supported -->
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.vulkan.version"
|
android:name="android.hardware.vulkan.version"
|
||||||
android:required="false"
|
android:required="false"
|
||||||
android:version="0x00401000" />
|
android:version="0x00401000" />
|
||||||
<!-- android:glEsVersion is not specified as OpenGL ES 1.0 is supported as fallback -->
|
<!-- android:glEsVersion is not specified as OpenGL ES 1.0 is supported as fallback -->
|
||||||
|
|
||||||
|
<!-- Only playable in landscape mode -->
|
||||||
<uses-feature
|
<uses-feature
|
||||||
android:name="android.hardware.screen.landscape"
|
android:name="android.hardware.screen.landscape"
|
||||||
android:required="true" />
|
android:required="true" />
|
||||||
|
|
||||||
|
<!-- Touchscreen support -->
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.touchscreen"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
|
<!-- Game controller support -->
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.bluetooth"
|
||||||
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.gamepad"
|
||||||
|
android:required="false" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.usb.host"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
|
<!-- External mouse input events -->
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.type.pc"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
<!-- Teeworlds does broadcasts over local networks -->
|
<!-- Teeworlds does broadcasts over local networks -->
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
|
||||||
|
@ -25,17 +50,24 @@
|
||||||
android:isGame="true"
|
android:isGame="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||||
|
android:hardwareAccelerated="true">
|
||||||
<activity
|
<activity
|
||||||
android:name="org.ddnet.client.NativeMain"
|
android:name="org.ddnet.client.NativeMain"
|
||||||
|
android:alwaysRetainTaskState="true"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
|
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
|
||||||
|
android:preferMinimalPostProcessing="true"
|
||||||
android:screenOrientation="landscape"
|
android:screenOrientation="landscape"
|
||||||
android:launchMode="singleInstance">
|
android:launchMode="singleInstance">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<!-- Let Android know that we can handle some USB devices and should receive this event -->
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||||
|
</intent-filter>
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.app.lib_name"
|
android:name="android.app.lib_name"
|
||||||
android:value="DDNet" />
|
android:value="DDNet" />
|
||||||
|
|
|
@ -668,10 +668,7 @@ void CClient::DisconnectWithReason(const char *pReason)
|
||||||
m_CurrentServerCurrentPingTime = -1;
|
m_CurrentServerCurrentPingTime = -1;
|
||||||
m_CurrentServerNextPingTime = -1;
|
m_CurrentServerNextPingTime = -1;
|
||||||
|
|
||||||
ResetMapDownload();
|
ResetMapDownload(true);
|
||||||
m_aMapdownloadFilename[0] = '\0';
|
|
||||||
m_aMapdownloadFilenameTemp[0] = '\0';
|
|
||||||
m_aMapdownloadName[0] = '\0';
|
|
||||||
|
|
||||||
// clear the current server info
|
// clear the current server info
|
||||||
mem_zero(&m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
|
mem_zero(&m_CurrentServerInfo, sizeof(m_CurrentServerInfo));
|
||||||
|
@ -1528,7 +1525,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
|
||||||
DummyDisconnect(0);
|
DummyDisconnect(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetMapDownload();
|
ResetMapDownload(true);
|
||||||
|
|
||||||
SHA256_DIGEST *pMapSha256 = nullptr;
|
SHA256_DIGEST *pMapSha256 = nullptr;
|
||||||
const char *pMapUrl = nullptr;
|
const char *pMapUrl = nullptr;
|
||||||
|
@ -2196,7 +2193,7 @@ int CClient::UnpackAndValidateSnapshot(CSnapshot *pFrom, CSnapshot *pTo)
|
||||||
return Builder.Finish(pTo);
|
return Builder.Finish(pTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::ResetMapDownload()
|
void CClient::ResetMapDownload(bool ResetActive)
|
||||||
{
|
{
|
||||||
if(m_pMapdownloadTask)
|
if(m_pMapdownloadTask)
|
||||||
{
|
{
|
||||||
|
@ -2215,19 +2212,24 @@ void CClient::ResetMapDownload()
|
||||||
Storage()->RemoveFile(m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE);
|
Storage()->RemoveFile(m_aMapdownloadFilenameTemp, IStorage::TYPE_SAVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_MapdownloadChunk = 0;
|
if(ResetActive)
|
||||||
m_MapdownloadSha256Present = false;
|
{
|
||||||
m_MapdownloadSha256 = SHA256_ZEROED;
|
m_MapdownloadChunk = 0;
|
||||||
m_MapdownloadCrc = 0;
|
m_MapdownloadSha256Present = false;
|
||||||
m_MapdownloadTotalsize = -1;
|
m_MapdownloadSha256 = SHA256_ZEROED;
|
||||||
m_MapdownloadAmount = 0;
|
m_MapdownloadCrc = 0;
|
||||||
|
m_MapdownloadTotalsize = -1;
|
||||||
|
m_MapdownloadAmount = 0;
|
||||||
|
m_aMapdownloadFilename[0] = '\0';
|
||||||
|
m_aMapdownloadFilenameTemp[0] = '\0';
|
||||||
|
m_aMapdownloadName[0] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CClient::FinishMapDownload()
|
void CClient::FinishMapDownload()
|
||||||
{
|
{
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "download complete, loading map");
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "download complete, loading map");
|
||||||
|
|
||||||
const int PrevMapdownloadTotalsize = m_MapdownloadTotalsize;
|
|
||||||
SHA256_DIGEST *pSha256 = m_MapdownloadSha256Present ? &m_MapdownloadSha256 : nullptr;
|
SHA256_DIGEST *pSha256 = m_MapdownloadSha256Present ? &m_MapdownloadSha256 : nullptr;
|
||||||
|
|
||||||
bool FileSuccess = true;
|
bool FileSuccess = true;
|
||||||
|
@ -2236,7 +2238,6 @@ void CClient::FinishMapDownload()
|
||||||
FileSuccess &= Storage()->RenameFile(m_aMapdownloadFilenameTemp, m_aMapdownloadFilename, IStorage::TYPE_SAVE);
|
FileSuccess &= Storage()->RenameFile(m_aMapdownloadFilenameTemp, m_aMapdownloadFilename, IStorage::TYPE_SAVE);
|
||||||
if(!FileSuccess)
|
if(!FileSuccess)
|
||||||
{
|
{
|
||||||
ResetMapDownload();
|
|
||||||
char aError[128 + IO_MAX_PATH_LENGTH];
|
char aError[128 + IO_MAX_PATH_LENGTH];
|
||||||
str_format(aError, sizeof(aError), Localize("Could not save downloaded map. Try manually deleting this file: %s"), m_aMapdownloadFilename);
|
str_format(aError, sizeof(aError), Localize("Could not save downloaded map. Try manually deleting this file: %s"), m_aMapdownloadFilename);
|
||||||
DisconnectWithReason(aError);
|
DisconnectWithReason(aError);
|
||||||
|
@ -2246,19 +2247,17 @@ void CClient::FinishMapDownload()
|
||||||
const char *pError = LoadMap(m_aMapdownloadName, m_aMapdownloadFilename, pSha256, m_MapdownloadCrc);
|
const char *pError = LoadMap(m_aMapdownloadName, m_aMapdownloadFilename, pSha256, m_MapdownloadCrc);
|
||||||
if(!pError)
|
if(!pError)
|
||||||
{
|
{
|
||||||
ResetMapDownload();
|
ResetMapDownload(true);
|
||||||
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done");
|
m_pConsole->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "client/network", "loading done");
|
||||||
SendReady(CONN_MAIN);
|
SendReady(CONN_MAIN);
|
||||||
}
|
}
|
||||||
else if(m_pMapdownloadTask) // fallback
|
else if(m_pMapdownloadTask) // fallback
|
||||||
{
|
{
|
||||||
ResetMapDownload();
|
ResetMapDownload(false);
|
||||||
m_MapdownloadTotalsize = PrevMapdownloadTotalsize;
|
|
||||||
SendMapRequest();
|
SendMapRequest();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ResetMapDownload();
|
|
||||||
DisconnectWithReason(pError);
|
DisconnectWithReason(pError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2784,7 +2783,7 @@ void CClient::Update()
|
||||||
else if(m_pMapdownloadTask->State() == EHttpState::ERROR || m_pMapdownloadTask->State() == EHttpState::ABORTED)
|
else if(m_pMapdownloadTask->State() == EHttpState::ERROR || m_pMapdownloadTask->State() == EHttpState::ABORTED)
|
||||||
{
|
{
|
||||||
dbg_msg("webdl", "http failed, falling back to gameserver");
|
dbg_msg("webdl", "http failed, falling back to gameserver");
|
||||||
ResetMapDownload();
|
ResetMapDownload(false);
|
||||||
SendMapRequest();
|
SendMapRequest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -360,7 +360,7 @@ public:
|
||||||
|
|
||||||
int UnpackAndValidateSnapshot(CSnapshot *pFrom, CSnapshot *pTo);
|
int UnpackAndValidateSnapshot(CSnapshot *pFrom, CSnapshot *pTo);
|
||||||
|
|
||||||
void ResetMapDownload();
|
void ResetMapDownload(bool ResetActive);
|
||||||
void FinishMapDownload();
|
void FinishMapDownload();
|
||||||
|
|
||||||
void RequestDDNetInfo() override;
|
void RequestDDNetInfo() override;
|
||||||
|
|
|
@ -300,6 +300,14 @@ const std::vector<IInput::CTouchFingerState> &CInput::TouchFingerStates() const
|
||||||
return m_vTouchFingerStates;
|
return m_vTouchFingerStates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CInput::ClearTouchDeltas()
|
||||||
|
{
|
||||||
|
for(CTouchFingerState &TouchFingerState : m_vTouchFingerStates)
|
||||||
|
{
|
||||||
|
TouchFingerState.m_Delta = vec2(0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string CInput::GetClipboardText()
|
std::string CInput::GetClipboardText()
|
||||||
{
|
{
|
||||||
char *pClipboardText = SDL_GetClipboardText();
|
char *pClipboardText = SDL_GetClipboardText();
|
||||||
|
@ -347,10 +355,7 @@ void CInput::Clear()
|
||||||
mem_zero(m_aInputState, sizeof(m_aInputState));
|
mem_zero(m_aInputState, sizeof(m_aInputState));
|
||||||
mem_zero(m_aInputCount, sizeof(m_aInputCount));
|
mem_zero(m_aInputCount, sizeof(m_aInputCount));
|
||||||
m_vInputEvents.clear();
|
m_vInputEvents.clear();
|
||||||
for(CTouchFingerState &TouchFingerState : m_vTouchFingerStates)
|
ClearTouchDeltas();
|
||||||
{
|
|
||||||
TouchFingerState.m_Delta = vec2(0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float CInput::GetUpdateTime() const
|
float CInput::GetUpdateTime() const
|
||||||
|
|
|
@ -144,6 +144,7 @@ public:
|
||||||
bool NativeMousePressed(int Index) const override;
|
bool NativeMousePressed(int Index) const override;
|
||||||
|
|
||||||
const std::vector<CTouchFingerState> &TouchFingerStates() const override;
|
const std::vector<CTouchFingerState> &TouchFingerStates() const override;
|
||||||
|
void ClearTouchDeltas() override;
|
||||||
|
|
||||||
std::string GetClipboardText() override;
|
std::string GetClipboardText() override;
|
||||||
void SetClipboardText(const char *pText) override;
|
void SetClipboardText(const char *pText) override;
|
||||||
|
|
|
@ -27,9 +27,6 @@
|
||||||
#include <engine/http.h>
|
#include <engine/http.h>
|
||||||
#include <engine/storage.h>
|
#include <engine/storage.h>
|
||||||
|
|
||||||
static constexpr const char *COMMUNITY_COUNTRY_NONE = "none";
|
|
||||||
static constexpr const char *COMMUNITY_TYPE_NONE = "None";
|
|
||||||
|
|
||||||
class CSortWrap
|
class CSortWrap
|
||||||
{
|
{
|
||||||
typedef bool (CServerBrowser::*SortFunc)(int, int) const;
|
typedef bool (CServerBrowser::*SortFunc)(int, int) const;
|
||||||
|
|
|
@ -137,6 +137,12 @@ public:
|
||||||
* @return vector of all touch finger states
|
* @return vector of all touch finger states
|
||||||
*/
|
*/
|
||||||
virtual const std::vector<CTouchFingerState> &TouchFingerStates() const = 0;
|
virtual const std::vector<CTouchFingerState> &TouchFingerStates() const = 0;
|
||||||
|
/**
|
||||||
|
* Must be called after the touch finger states have been used during the client update to ensure that
|
||||||
|
* touch deltas are only accumulated until the next update. If the touch states are only used during
|
||||||
|
* rendering, i.e. for user interfaces, then this is called automatically by calling @link Clear @endlink.
|
||||||
|
*/
|
||||||
|
virtual void ClearTouchDeltas() = 0;
|
||||||
|
|
||||||
// clipboard
|
// clipboard
|
||||||
virtual std::string GetClipboardText() = 0;
|
virtual std::string GetClipboardText() = 0;
|
||||||
|
|
|
@ -309,6 +309,9 @@ public:
|
||||||
|
|
||||||
static constexpr const char *COMMUNITY_DDNET = "ddnet";
|
static constexpr const char *COMMUNITY_DDNET = "ddnet";
|
||||||
static constexpr const char *COMMUNITY_NONE = "none";
|
static constexpr const char *COMMUNITY_NONE = "none";
|
||||||
|
|
||||||
|
static constexpr const char *COMMUNITY_COUNTRY_NONE = "none";
|
||||||
|
static constexpr const char *COMMUNITY_TYPE_NONE = "None";
|
||||||
/**
|
/**
|
||||||
* Special community value for country/type filters that
|
* Special community value for country/type filters that
|
||||||
* affect all communities.
|
* affect all communities.
|
||||||
|
|
|
@ -22,6 +22,11 @@ MACRO_CONFIG_INT(ClAntiPingSmooth, cl_antiping_smooth, 0, 0, 1, CFGFLAG_CLIENT |
|
||||||
MACRO_CONFIG_INT(ClAntiPingGunfire, cl_antiping_gunfire, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict gunfire and show predicted weapon physics (with cl_antiping_grenade 1 and cl_antiping_weapons 1)")
|
MACRO_CONFIG_INT(ClAntiPingGunfire, cl_antiping_gunfire, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict gunfire and show predicted weapon physics (with cl_antiping_grenade 1 and cl_antiping_weapons 1)")
|
||||||
MACRO_CONFIG_INT(ClPredictionMargin, cl_prediction_margin, 10, 1, 300, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Prediction margin in ms (adds latency, can reduce lag from ping jumps)")
|
MACRO_CONFIG_INT(ClPredictionMargin, cl_prediction_margin, 10, 1, 300, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Prediction margin in ms (adds latency, can reduce lag from ping jumps)")
|
||||||
MACRO_CONFIG_INT(ClSubTickAiming, cl_sub_tick_aiming, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Send aiming data at sub-tick accuracy")
|
MACRO_CONFIG_INT(ClSubTickAiming, cl_sub_tick_aiming, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Send aiming data at sub-tick accuracy")
|
||||||
|
#if defined(CONF_PLATFORM_ANDROID)
|
||||||
|
MACRO_CONFIG_INT(ClTouchControls, cl_touch_controls, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Enable ingame touch controls")
|
||||||
|
#else
|
||||||
|
MACRO_CONFIG_INT(ClTouchControls, cl_touch_controls, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Enable ingame touch controls")
|
||||||
|
#endif
|
||||||
|
|
||||||
MACRO_CONFIG_INT(ClNameplates, cl_nameplates, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show name plates")
|
MACRO_CONFIG_INT(ClNameplates, cl_nameplates, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show name plates")
|
||||||
MACRO_CONFIG_INT(ClAfkEmote, cl_afk_emote, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show zzz emote next to afk players")
|
MACRO_CONFIG_INT(ClAfkEmote, cl_afk_emote, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show zzz emote next to afk players")
|
||||||
|
@ -105,6 +110,7 @@ MACRO_CONFIG_INT(EdZoomTarget, ed_zoom_target, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG
|
||||||
MACRO_CONFIG_INT(EdShowkeys, ed_showkeys, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show pressed keys")
|
MACRO_CONFIG_INT(EdShowkeys, ed_showkeys, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show pressed keys")
|
||||||
MACRO_CONFIG_INT(EdAlignQuads, ed_align_quads, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Enable/disable quad alignment. When enabled, red lines appear to show how quad/points are aligned and snapped to other quads/points when moving them")
|
MACRO_CONFIG_INT(EdAlignQuads, ed_align_quads, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Enable/disable quad alignment. When enabled, red lines appear to show how quad/points are aligned and snapped to other quads/points when moving them")
|
||||||
MACRO_CONFIG_INT(EdShowQuadsRect, ed_show_quads_rect, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show the bounds of the selected quad. In case of multiple quads, it shows the bounds of the englobing rect. Can be helpful when aligning a group of quads")
|
MACRO_CONFIG_INT(EdShowQuadsRect, ed_show_quads_rect, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show the bounds of the selected quad. In case of multiple quads, it shows the bounds of the englobing rect. Can be helpful when aligning a group of quads")
|
||||||
|
MACRO_CONFIG_INT(EdAutoMapReload, ed_auto_map_reload, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Run 'hot_reload' on the local server while rcon authed on map save")
|
||||||
|
|
||||||
MACRO_CONFIG_INT(ClShowWelcome, cl_show_welcome, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show welcome message indicating the first launch of the client")
|
MACRO_CONFIG_INT(ClShowWelcome, cl_show_welcome, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Show welcome message indicating the first launch of the client")
|
||||||
MACRO_CONFIG_INT(ClMotdTime, cl_motd_time, 10, 0, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE, "How long to show the server message of the day")
|
MACRO_CONFIG_INT(ClMotdTime, cl_motd_time, 10, 0, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE, "How long to show the server message of the day")
|
||||||
|
|
|
@ -136,7 +136,7 @@ int CConsole::ParseStart(CResult *pResult, const char *pString, int Length)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CConsole::ParseArgs(CResult *pResult, const char *pFormat, FCommandCallback pfnCallback)
|
int CConsole::ParseArgs(CResult *pResult, const char *pFormat, bool IsColor)
|
||||||
{
|
{
|
||||||
char Command = *pFormat;
|
char Command = *pFormat;
|
||||||
char *pStr;
|
char *pStr;
|
||||||
|
@ -235,7 +235,7 @@ int CConsole::ParseArgs(CResult *pResult, const char *pFormat, FCommandCallback
|
||||||
if(Command == 'i')
|
if(Command == 'i')
|
||||||
{
|
{
|
||||||
// don't validate colors here
|
// don't validate colors here
|
||||||
if(pfnCallback != &SColorConfigVariable::CommandCallback)
|
if(!IsColor)
|
||||||
{
|
{
|
||||||
int Value;
|
int Value;
|
||||||
if(!str_toint(pResult->GetString(pResult->NumArguments() - 1), &Value) ||
|
if(!str_toint(pResult->GetString(pResult->NumArguments() - 1), &Value) ||
|
||||||
|
@ -514,7 +514,7 @@ void CConsole::ExecuteLineStroked(int Stroke, const char *pStr, int ClientId, bo
|
||||||
|
|
||||||
if(Stroke || IsStrokeCommand)
|
if(Stroke || IsStrokeCommand)
|
||||||
{
|
{
|
||||||
if(int Error = ParseArgs(&Result, pCommand->m_pParams, pCommand->m_pfnCallback))
|
if(int Error = ParseArgs(&Result, pCommand->m_pParams, pCommand->m_pfnCallback == &SColorConfigVariable::CommandCallback))
|
||||||
{
|
{
|
||||||
char aBuf[CMDLINE_LENGTH + 64];
|
char aBuf[CMDLINE_LENGTH + 64];
|
||||||
if(Error == PARSEARGS_INVALID_INTEGER)
|
if(Error == PARSEARGS_INVALID_INTEGER)
|
||||||
|
|
|
@ -153,7 +153,7 @@ class CConsole : public IConsole
|
||||||
PARSEARGS_INVALID_FLOAT,
|
PARSEARGS_INVALID_FLOAT,
|
||||||
};
|
};
|
||||||
|
|
||||||
int ParseArgs(CResult *pResult, const char *pFormat, FCommandCallback pfnCallback = 0);
|
int ParseArgs(CResult *pResult, const char *pFormat, bool IsColor = false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this function will set pFormat to the next parameter (i,s,r,v,?) it contains and
|
this function will set pFormat to the next parameter (i,s,r,v,?) it contains and
|
||||||
|
|
|
@ -212,6 +212,14 @@ public:
|
||||||
* @param Event The input event.
|
* @param Event The input event.
|
||||||
*/
|
*/
|
||||||
virtual bool OnInput(const IInput::CEvent &Event) { return false; }
|
virtual bool OnInput(const IInput::CEvent &Event) { return false; }
|
||||||
|
/**
|
||||||
|
* Called with all current touch finger states.
|
||||||
|
*
|
||||||
|
* @param vTouchFingerStates The touch finger states to be handled.
|
||||||
|
*
|
||||||
|
* @return `true` if the component used the touch events, `false` otherwise
|
||||||
|
*/
|
||||||
|
virtual bool OnTouchState(const std::vector<IInput::CTouchFingerState> &vTouchFingerStates) { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
|
|
||||||
class CControls : public CComponent
|
class CControls : public CComponent
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
float GetMinMouseDistance() const;
|
float GetMinMouseDistance() const;
|
||||||
float GetMaxMouseDistance() const;
|
float GetMaxMouseDistance() const;
|
||||||
|
|
||||||
public:
|
|
||||||
vec2 m_aMousePos[NUM_DUMMIES];
|
vec2 m_aMousePos[NUM_DUMMIES];
|
||||||
vec2 m_aMousePosOnAction[NUM_DUMMIES];
|
vec2 m_aMousePosOnAction[NUM_DUMMIES];
|
||||||
vec2 m_aTargetPos[NUM_DUMMIES];
|
vec2 m_aTargetPos[NUM_DUMMIES];
|
||||||
|
|
|
@ -474,8 +474,12 @@ protected:
|
||||||
// found in menus_ingame.cpp
|
// found in menus_ingame.cpp
|
||||||
STextContainerIndex m_MotdTextContainerIndex;
|
STextContainerIndex m_MotdTextContainerIndex;
|
||||||
void RenderGame(CUIRect MainView);
|
void RenderGame(CUIRect MainView);
|
||||||
|
void RenderTouchControlsEditor(CUIRect MainView);
|
||||||
void PopupConfirmDisconnect();
|
void PopupConfirmDisconnect();
|
||||||
void PopupConfirmDisconnectDummy();
|
void PopupConfirmDisconnectDummy();
|
||||||
|
void PopupConfirmDiscardTouchControlsChanged();
|
||||||
|
void PopupConfirmResetTouchControls();
|
||||||
|
void PopupConfirmImportTouchControlsClipboard();
|
||||||
void RenderPlayers(CUIRect MainView);
|
void RenderPlayers(CUIRect MainView);
|
||||||
void RenderServerInfo(CUIRect MainView);
|
void RenderServerInfo(CUIRect MainView);
|
||||||
void RenderServerInfoMotd(CUIRect Motd);
|
void RenderServerInfoMotd(CUIRect Motd);
|
||||||
|
@ -637,7 +641,6 @@ protected:
|
||||||
static CUi::EPopupMenuFunctionResult PopupMapPicker(void *pContext, CUIRect View, bool Active);
|
static CUi::EPopupMenuFunctionResult PopupMapPicker(void *pContext, CUIRect View, bool Active);
|
||||||
|
|
||||||
void SetNeedSendInfo();
|
void SetNeedSendInfo();
|
||||||
void SetActive(bool Active);
|
|
||||||
void UpdateColors();
|
void UpdateColors();
|
||||||
|
|
||||||
IGraphics::CTextureHandle m_TextureBlob;
|
IGraphics::CTextureHandle m_TextureBlob;
|
||||||
|
@ -657,6 +660,8 @@ public:
|
||||||
bool IsInit() { return m_IsInit; }
|
bool IsInit() { return m_IsInit; }
|
||||||
|
|
||||||
bool IsActive() const { return m_MenuActive; }
|
bool IsActive() const { return m_MenuActive; }
|
||||||
|
void SetActive(bool Active);
|
||||||
|
|
||||||
void KillServer();
|
void KillServer();
|
||||||
|
|
||||||
virtual void OnInit() override;
|
virtual void OnInit() override;
|
||||||
|
|
|
@ -869,11 +869,14 @@ void CMenus::RenderServerbrowserDDNetFilter(CUIRect View,
|
||||||
{
|
{
|
||||||
if(Click == 1)
|
if(Click == 1)
|
||||||
{
|
{
|
||||||
// Left click: when all are active, only activate one
|
// Left click: when all are active, only activate one and none
|
||||||
for(int j = 0; j < MaxItems; ++j)
|
for(int j = 0; j < MaxItems; ++j)
|
||||||
{
|
{
|
||||||
if(j != ItemIndex)
|
if(const char *pItemName = GetItemName(j);
|
||||||
Filter.Add(GetItemName(j));
|
j != ItemIndex &&
|
||||||
|
!((&Filter == &ServerBrowser()->CountriesFilter() && str_comp(pItemName, IServerBrowser::COMMUNITY_COUNTRY_NONE) == 0) ||
|
||||||
|
(&Filter == &ServerBrowser()->TypesFilter() && str_comp(pItemName, IServerBrowser::COMMUNITY_TYPE_NONE) == 0)))
|
||||||
|
Filter.Add(pItemName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(Click == 2)
|
else if(Click == 2)
|
||||||
|
@ -890,7 +893,10 @@ void CMenus::RenderServerbrowserDDNetFilter(CUIRect View,
|
||||||
bool AllFilteredExceptUs = true;
|
bool AllFilteredExceptUs = true;
|
||||||
for(int j = 0; j < MaxItems; ++j)
|
for(int j = 0; j < MaxItems; ++j)
|
||||||
{
|
{
|
||||||
if(j != ItemIndex && !Filter.Filtered(GetItemName(j)))
|
if(const char *pItemName = GetItemName(j);
|
||||||
|
j != ItemIndex && !Filter.Filtered(pItemName) &&
|
||||||
|
!((&Filter == &ServerBrowser()->CountriesFilter() && str_comp(pItemName, IServerBrowser::COMMUNITY_COUNTRY_NONE) == 0) ||
|
||||||
|
(&Filter == &ServerBrowser()->TypesFilter() && str_comp(pItemName, IServerBrowser::COMMUNITY_TYPE_NONE) == 0)))
|
||||||
{
|
{
|
||||||
AllFilteredExceptUs = false;
|
AllFilteredExceptUs = false;
|
||||||
break;
|
break;
|
||||||
|
@ -898,7 +904,7 @@ void CMenus::RenderServerbrowserDDNetFilter(CUIRect View,
|
||||||
}
|
}
|
||||||
// When last one is removed, re-enable all currently selectable items.
|
// When last one is removed, re-enable all currently selectable items.
|
||||||
// Don't use Clear, to avoid enabling also currently unselectable items.
|
// Don't use Clear, to avoid enabling also currently unselectable items.
|
||||||
if(AllFilteredExceptUs)
|
if(AllFilteredExceptUs && Active)
|
||||||
{
|
{
|
||||||
for(int j = 0; j < MaxItems; ++j)
|
for(int j = 0; j < MaxItems; ++j)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include <game/client/animstate.h>
|
#include <game/client/animstate.h>
|
||||||
#include <game/client/components/countryflags.h>
|
#include <game/client/components/countryflags.h>
|
||||||
|
#include <game/client/components/touch_controls.h>
|
||||||
#include <game/client/gameclient.h>
|
#include <game/client/gameclient.h>
|
||||||
#include <game/client/render.h>
|
#include <game/client/render.h>
|
||||||
#include <game/client/ui.h>
|
#include <game/client/ui.h>
|
||||||
|
@ -40,21 +41,19 @@ using namespace std::chrono_literals;
|
||||||
|
|
||||||
void CMenus::RenderGame(CUIRect MainView)
|
void CMenus::RenderGame(CUIRect MainView)
|
||||||
{
|
{
|
||||||
CUIRect Button, ButtonBar, ButtonBar2;
|
CUIRect Button, ButtonBars, ButtonBar, ButtonBar2;
|
||||||
bool ShowDDRaceButtons = MainView.w > 855.0f;
|
bool ShowDDRaceButtons = MainView.w > 855.0f;
|
||||||
MainView.HSplitTop(45.0f, &ButtonBar, &MainView);
|
MainView.HSplitTop(45.0f + (g_Config.m_ClTouchControls ? 35.0f : 0.0f), &ButtonBars, &MainView);
|
||||||
ButtonBar.Draw(ms_ColorTabbarActive, IGraphics::CORNER_B, 10.0f);
|
ButtonBars.Draw(ms_ColorTabbarActive, IGraphics::CORNER_B, 10.0f);
|
||||||
|
ButtonBars.Margin(10.0f, &ButtonBars);
|
||||||
// button bar
|
ButtonBars.HSplitTop(25.0f, &ButtonBar, &ButtonBars);
|
||||||
ButtonBar.HSplitTop(10.0f, 0, &ButtonBar);
|
if(g_Config.m_ClTouchControls)
|
||||||
ButtonBar.HSplitTop(25.0f, &ButtonBar, 0);
|
{
|
||||||
ButtonBar.VMargin(10.0f, &ButtonBar);
|
ButtonBars.HSplitTop(10.0f, nullptr, &ButtonBars);
|
||||||
|
ButtonBars.HSplitTop(25.0f, &ButtonBar2, &ButtonBars);
|
||||||
ButtonBar.HSplitTop(30.0f, 0, &ButtonBar2);
|
}
|
||||||
ButtonBar2.HSplitTop(25.0f, &ButtonBar2, 0);
|
|
||||||
|
|
||||||
ButtonBar.VSplitRight(120.0f, &ButtonBar, &Button);
|
ButtonBar.VSplitRight(120.0f, &ButtonBar, &Button);
|
||||||
|
|
||||||
static CButtonContainer s_DisconnectButton;
|
static CButtonContainer s_DisconnectButton;
|
||||||
if(DoButton_Menu(&s_DisconnectButton, Localize("Disconnect"), 0, &Button))
|
if(DoButton_Menu(&s_DisconnectButton, Localize("Disconnect"), 0, &Button))
|
||||||
{
|
{
|
||||||
|
@ -214,6 +213,147 @@ void CMenus::RenderGame(CUIRect MainView)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(g_Config.m_ClTouchControls)
|
||||||
|
{
|
||||||
|
ButtonBar2.VSplitLeft(200.0f, &Button, &ButtonBar2);
|
||||||
|
static char s_TouchControlsEditCheckbox;
|
||||||
|
if(DoButton_CheckBox(&s_TouchControlsEditCheckbox, Localize("Edit touch controls"), GameClient()->m_TouchControls.IsEditingActive(), &Button))
|
||||||
|
{
|
||||||
|
GameClient()->m_TouchControls.SetEditingActive(!GameClient()->m_TouchControls.IsEditingActive());
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonBar2.VSplitRight(80.0f, &ButtonBar2, &Button);
|
||||||
|
static CButtonContainer s_CloseButton;
|
||||||
|
if(DoButton_Menu(&s_CloseButton, Localize("Close"), 0, &Button))
|
||||||
|
{
|
||||||
|
SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonBar2.VSplitRight(5.0f, &ButtonBar2, nullptr);
|
||||||
|
ButtonBar2.VSplitRight(160.0f, &ButtonBar2, &Button);
|
||||||
|
static CButtonContainer s_RemoveConsoleButton;
|
||||||
|
if(DoButton_Menu(&s_RemoveConsoleButton, Localize("Remote console"), 0, &Button))
|
||||||
|
{
|
||||||
|
Console()->ExecuteLine("toggle_remote_console");
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonBar2.VSplitRight(5.0f, &ButtonBar2, nullptr);
|
||||||
|
ButtonBar2.VSplitRight(120.0f, &ButtonBar2, &Button);
|
||||||
|
static CButtonContainer s_LocalConsoleButton;
|
||||||
|
if(DoButton_Menu(&s_LocalConsoleButton, Localize("Console"), 0, &Button))
|
||||||
|
{
|
||||||
|
Console()->ExecuteLine("toggle_local_console");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(GameClient()->m_TouchControls.IsEditingActive())
|
||||||
|
{
|
||||||
|
CUIRect TouchControlsEditor;
|
||||||
|
MainView.VMargin((MainView.w - 505.0f) / 2.0f, &TouchControlsEditor);
|
||||||
|
TouchControlsEditor.HMargin((TouchControlsEditor.h - 195.0f) / 2.0f, &TouchControlsEditor);
|
||||||
|
RenderTouchControlsEditor(TouchControlsEditor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMenus::RenderTouchControlsEditor(CUIRect MainView)
|
||||||
|
{
|
||||||
|
CUIRect Button, Row;
|
||||||
|
MainView.Draw(ms_ColorTabbarActive, IGraphics::CORNER_ALL, 10.0f);
|
||||||
|
MainView.Margin(10.0f, &MainView);
|
||||||
|
|
||||||
|
MainView.HSplitTop(25.0f, &Button, &MainView);
|
||||||
|
MainView.HSplitTop(5.0f, nullptr, &MainView);
|
||||||
|
Ui()->DoLabel(&Button, Localize("Edit touch controls"), 20.0f, TEXTALIGN_MC);
|
||||||
|
|
||||||
|
MainView.HSplitTop(25.0f, &Row, &MainView);
|
||||||
|
MainView.HSplitTop(5.0f, nullptr, &MainView);
|
||||||
|
|
||||||
|
Row.VSplitLeft(240.0f, &Button, &Row);
|
||||||
|
static CButtonContainer s_SaveConfigurationButton;
|
||||||
|
if(DoButton_Menu(&s_SaveConfigurationButton, Localize("Save changes"), GameClient()->m_TouchControls.HasEditingChanges() ? 0 : 1, &Button))
|
||||||
|
{
|
||||||
|
if(GameClient()->m_TouchControls.SaveConfigurationToFile())
|
||||||
|
{
|
||||||
|
GameClient()->m_TouchControls.SetEditingChanges(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SWarning Warning(Localize("Error saving touch controls"), Localize("Could not save touch controls to file. See local console for details."));
|
||||||
|
Warning.m_AutoHide = false;
|
||||||
|
Client()->AddWarning(Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row.VSplitLeft(5.0f, nullptr, &Row);
|
||||||
|
Row.VSplitLeft(240.0f, &Button, &Row);
|
||||||
|
if(GameClient()->m_TouchControls.HasEditingChanges())
|
||||||
|
{
|
||||||
|
TextRender()->TextColor(ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f));
|
||||||
|
Ui()->DoLabel(&Button, Localize("Unsaved changes"), 14.0f, TEXTALIGN_MC);
|
||||||
|
TextRender()->TextColor(TextRender()->DefaultTextColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
MainView.HSplitTop(25.0f, &Row, &MainView);
|
||||||
|
MainView.HSplitTop(5.0f, nullptr, &MainView);
|
||||||
|
|
||||||
|
Row.VSplitLeft(240.0f, &Button, &Row);
|
||||||
|
static CButtonContainer s_DiscardChangesButton;
|
||||||
|
if(DoButton_Menu(&s_DiscardChangesButton, Localize("Discard changes"), GameClient()->m_TouchControls.HasEditingChanges() ? 0 : 1, &Button))
|
||||||
|
{
|
||||||
|
PopupConfirm(Localize("Discard changes"),
|
||||||
|
Localize("Are you sure that you want to discard the current changes to the touch controls?"),
|
||||||
|
Localize("Yes"), Localize("No"),
|
||||||
|
&CMenus::PopupConfirmDiscardTouchControlsChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
Row.VSplitLeft(5.0f, nullptr, &Row);
|
||||||
|
Row.VSplitLeft(240.0f, &Button, &Row);
|
||||||
|
static CButtonContainer s_ResetButton;
|
||||||
|
if(DoButton_Menu(&s_ResetButton, Localize("Reset to default"), 0, &Button))
|
||||||
|
{
|
||||||
|
PopupConfirm(Localize("Reset to default"),
|
||||||
|
Localize("Are you sure that you want to reset the touch controls to default?"),
|
||||||
|
Localize("Yes"), Localize("No"),
|
||||||
|
&CMenus::PopupConfirmResetTouchControls);
|
||||||
|
}
|
||||||
|
|
||||||
|
MainView.HSplitTop(25.0f, &Row, &MainView);
|
||||||
|
MainView.HSplitTop(5.0f, nullptr, &MainView);
|
||||||
|
|
||||||
|
Row.VSplitLeft(240.0f, &Button, &Row);
|
||||||
|
static CButtonContainer s_ClipboardImportButton;
|
||||||
|
if(DoButton_Menu(&s_ClipboardImportButton, Localize("Import from clipboard"), 0, &Button))
|
||||||
|
{
|
||||||
|
PopupConfirm(Localize("Import from clipboard"),
|
||||||
|
Localize("Are you sure that you want to import the touch controls from the clipboard? The will overwrite your current touch controls."),
|
||||||
|
Localize("Yes"), Localize("No"),
|
||||||
|
&CMenus::PopupConfirmImportTouchControlsClipboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
Row.VSplitLeft(5.0f, nullptr, &Row);
|
||||||
|
Row.VSplitLeft(240.0f, &Button, &Row);
|
||||||
|
static CButtonContainer s_ClipboardExportButton;
|
||||||
|
if(DoButton_Menu(&s_ClipboardExportButton, Localize("Export to clipboard"), 0, &Button))
|
||||||
|
{
|
||||||
|
GameClient()->m_TouchControls.SaveConfigurationToClipboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainView.HSplitTop(25.0f, &Button, &MainView);
|
||||||
|
MainView.HSplitTop(5.0f, nullptr, &MainView);
|
||||||
|
static char s_DirectTouchIngameButton;
|
||||||
|
if(DoButton_CheckBox(&s_DirectTouchIngameButton, Localize("Direct touch input while ingame"), GameClient()->m_TouchControls.IsDirectTouchIngame(), &Button))
|
||||||
|
{
|
||||||
|
GameClient()->m_TouchControls.SetDirectTouchIngame(!GameClient()->m_TouchControls.IsDirectTouchIngame());
|
||||||
|
}
|
||||||
|
|
||||||
|
MainView.HSplitTop(25.0f, &Button, &MainView);
|
||||||
|
MainView.HSplitTop(5.0f, nullptr, &MainView);
|
||||||
|
static char s_DirectTouchSpectateButton;
|
||||||
|
if(DoButton_CheckBox(&s_DirectTouchSpectateButton, Localize("Direct touch input while spectate"), GameClient()->m_TouchControls.IsDirectTouchSpectate(), &Button))
|
||||||
|
{
|
||||||
|
GameClient()->m_TouchControls.SetDirectTouchSpectate(!GameClient()->m_TouchControls.IsDirectTouchSpectate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMenus::PopupConfirmDisconnect()
|
void CMenus::PopupConfirmDisconnect()
|
||||||
|
@ -227,6 +367,57 @@ void CMenus::PopupConfirmDisconnectDummy()
|
||||||
SetActive(false);
|
SetActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMenus::PopupConfirmDiscardTouchControlsChanged()
|
||||||
|
{
|
||||||
|
if(GameClient()->m_TouchControls.LoadConfigurationFromFile(IStorage::TYPE_ALL))
|
||||||
|
{
|
||||||
|
GameClient()->m_TouchControls.SetEditingChanges(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SWarning Warning(Localize("Error loading touch controls"), Localize("Could not load touch controls from file. See local console for details."));
|
||||||
|
Warning.m_AutoHide = false;
|
||||||
|
Client()->AddWarning(Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMenus::PopupConfirmResetTouchControls()
|
||||||
|
{
|
||||||
|
bool Success = false;
|
||||||
|
for(int StorageType = 1; StorageType < Storage()->NumPaths(); ++StorageType)
|
||||||
|
{
|
||||||
|
if(GameClient()->m_TouchControls.LoadConfigurationFromFile(StorageType))
|
||||||
|
{
|
||||||
|
Success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Success)
|
||||||
|
{
|
||||||
|
GameClient()->m_TouchControls.SetEditingChanges(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SWarning Warning(Localize("Error loading touch controls"), Localize("Could not load default touch controls from file. See local console for details."));
|
||||||
|
Warning.m_AutoHide = false;
|
||||||
|
Client()->AddWarning(Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMenus::PopupConfirmImportTouchControlsClipboard()
|
||||||
|
{
|
||||||
|
if(GameClient()->m_TouchControls.LoadConfigurationFromClipboard())
|
||||||
|
{
|
||||||
|
GameClient()->m_TouchControls.SetEditingChanges(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SWarning Warning(Localize("Error loading touch controls"), Localize("Could not load touch controls from clipboard. See local console for details."));
|
||||||
|
Warning.m_AutoHide = false;
|
||||||
|
Client()->AddWarning(Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CMenus::RenderPlayers(CUIRect MainView)
|
void CMenus::RenderPlayers(CUIRect MainView)
|
||||||
{
|
{
|
||||||
CUIRect Button, Button2, ButtonBar, PlayerList, Player;
|
CUIRect Button, Button2, ButtonBar, PlayerList, Player;
|
||||||
|
@ -1292,6 +1483,9 @@ void CMenus::RenderGhost(CUIRect MainView)
|
||||||
|
|
||||||
void CMenus::RenderIngameHint()
|
void CMenus::RenderIngameHint()
|
||||||
{
|
{
|
||||||
|
if(g_Config.m_ClTouchControls)
|
||||||
|
return;
|
||||||
|
|
||||||
float Width = 300 * Graphics()->ScreenAspect();
|
float Width = 300 * Graphics()->ScreenAspect();
|
||||||
Graphics()->MapScreen(0, 0, Width, 300);
|
Graphics()->MapScreen(0, 0, Width, 300);
|
||||||
TextRender()->TextColor(1, 1, 1, 1);
|
TextRender()->TextColor(1, 1, 1, 1);
|
||||||
|
|
1234
src/game/client/components/touch_controls.cpp
Normal file
1234
src/game/client/components/touch_controls.cpp
Normal file
File diff suppressed because it is too large
Load diff
402
src/game/client/components/touch_controls.h
Normal file
402
src/game/client/components/touch_controls.h
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
#ifndef GAME_CLIENT_COMPONENTS_TOUCH_CONTROLS_H
|
||||||
|
#define GAME_CLIENT_COMPONENTS_TOUCH_CONTROLS_H
|
||||||
|
|
||||||
|
#include <base/vmath.h>
|
||||||
|
|
||||||
|
#include <engine/input.h>
|
||||||
|
|
||||||
|
#include <game/client/component.h>
|
||||||
|
#include <game/client/ui_rect.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class CJsonWriter;
|
||||||
|
typedef struct _json_value json_value;
|
||||||
|
|
||||||
|
class CTouchControls : public CComponent
|
||||||
|
{
|
||||||
|
enum class EButtonShape
|
||||||
|
{
|
||||||
|
RECT,
|
||||||
|
CIRCLE,
|
||||||
|
NUM_SHAPES
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr const char *SHAPE_NAMES[(int)EButtonShape::NUM_SHAPES] = {"rect", "circle"};
|
||||||
|
|
||||||
|
enum class EButtonVisibility
|
||||||
|
{
|
||||||
|
INGAME,
|
||||||
|
EXTRA_MENU,
|
||||||
|
ZOOM_ALLOWED,
|
||||||
|
VOTE_ACTIVE,
|
||||||
|
DUMMY_ALLOWED,
|
||||||
|
DUMMY_CONNECTED,
|
||||||
|
RCON_AUTHED,
|
||||||
|
NUM_VISIBILITIES
|
||||||
|
};
|
||||||
|
|
||||||
|
class CButtonVisibility
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EButtonVisibility m_Type;
|
||||||
|
bool m_Parity;
|
||||||
|
|
||||||
|
CButtonVisibility(EButtonVisibility Type, bool Parity) :
|
||||||
|
m_Type(Type), m_Parity(Parity) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CButtonVisibilityData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char *m_pId;
|
||||||
|
std::function<bool()> m_Function;
|
||||||
|
};
|
||||||
|
|
||||||
|
CButtonVisibilityData m_aVisibilityFunctions[(int)EButtonVisibility::NUM_VISIBILITIES];
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ACTION_FIRE,
|
||||||
|
ACTION_HOOK,
|
||||||
|
NUM_ACTIONS
|
||||||
|
};
|
||||||
|
|
||||||
|
class CButtonLabel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class EType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Label is used as is.
|
||||||
|
*/
|
||||||
|
PLAIN,
|
||||||
|
/**
|
||||||
|
* Label is localized. Only usable for default button labels for which there must be
|
||||||
|
* corresponding `Localizable`-calls in code and string in the translation files.
|
||||||
|
*/
|
||||||
|
LOCALIZED,
|
||||||
|
/**
|
||||||
|
* Icon font is used for the label.
|
||||||
|
*/
|
||||||
|
ICON,
|
||||||
|
/**
|
||||||
|
* Number of label types.
|
||||||
|
*/
|
||||||
|
NUM_TYPES
|
||||||
|
};
|
||||||
|
|
||||||
|
EType m_Type;
|
||||||
|
const char *m_pLabel;
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr const char *LABEL_TYPE_NAMES[(int)CButtonLabel::EType::NUM_TYPES] = {"plain", "localized", "icon"};
|
||||||
|
|
||||||
|
class CUnitRect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int m_X;
|
||||||
|
int m_Y;
|
||||||
|
int m_W;
|
||||||
|
int m_H;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CTouchButtonBehavior;
|
||||||
|
|
||||||
|
class CTouchButton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CTouchButton(CTouchControls *pTouchControls);
|
||||||
|
CTouchButton(CTouchButton &&Other) noexcept;
|
||||||
|
CTouchButton(const CTouchButton &Other) = delete;
|
||||||
|
|
||||||
|
CTouchButton &operator=(const CTouchButton &Other) = delete;
|
||||||
|
CTouchButton &operator=(CTouchButton &&Other) noexcept;
|
||||||
|
|
||||||
|
CTouchControls *m_pTouchControls;
|
||||||
|
|
||||||
|
CUnitRect m_UnitRect;
|
||||||
|
CUIRect m_ScreenRect;
|
||||||
|
|
||||||
|
EButtonShape m_Shape;
|
||||||
|
int m_BackgroundCorners; // only used with EButtonShape::RECT
|
||||||
|
|
||||||
|
std::vector<CButtonVisibility> m_vVisibilities;
|
||||||
|
std::unique_ptr<CTouchButtonBehavior> m_pBehavior;
|
||||||
|
|
||||||
|
void UpdatePointers();
|
||||||
|
void UpdateScreenFromUnitRect();
|
||||||
|
void UpdateUnitFromScreenRect();
|
||||||
|
void UpdateBackgroundCorners();
|
||||||
|
|
||||||
|
vec2 ClampTouchPosition(vec2 TouchPosition) const;
|
||||||
|
bool IsInside(vec2 TouchPosition) const;
|
||||||
|
bool IsVisible() const;
|
||||||
|
void Render() const;
|
||||||
|
void WriteToConfiguration(CJsonWriter *pWriter);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CTouchButtonBehavior
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CTouchButton *m_pTouchButton;
|
||||||
|
CTouchControls *m_pTouchControls;
|
||||||
|
|
||||||
|
bool m_Active; // variables below must only be used when active
|
||||||
|
IInput::CTouchFinger m_Finger;
|
||||||
|
vec2 m_ActivePosition;
|
||||||
|
vec2 m_AccumulatedDelta;
|
||||||
|
std::chrono::nanoseconds m_ActivationStartTime;
|
||||||
|
|
||||||
|
virtual ~CTouchButtonBehavior() = default;
|
||||||
|
virtual void Init(CTouchButton *pTouchButton);
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
void SetActive(const IInput::CTouchFingerState &FingerState);
|
||||||
|
void SetInactive();
|
||||||
|
bool IsActive() const;
|
||||||
|
bool IsActive(const IInput::CTouchFinger &Finger) const;
|
||||||
|
|
||||||
|
virtual CButtonLabel GetLabel() const = 0;
|
||||||
|
virtual void OnActivate() {}
|
||||||
|
virtual void OnDeactivate() {}
|
||||||
|
virtual void OnUpdate() {}
|
||||||
|
virtual void WriteToConfiguration(CJsonWriter *pWriter) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class for predefined behaviors.
|
||||||
|
*
|
||||||
|
* This implements the serialization for predefined behaviors.
|
||||||
|
*
|
||||||
|
* Subclasses must implemented the actual behavior and provide the label.
|
||||||
|
*/
|
||||||
|
class CPredefinedTouchButtonBehavior : public CTouchButtonBehavior
|
||||||
|
{
|
||||||
|
const char *m_pId;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr const char *BEHAVIOR_TYPE = "predefined";
|
||||||
|
|
||||||
|
CPredefinedTouchButtonBehavior(const char *pId) :
|
||||||
|
m_pId(pId) {}
|
||||||
|
|
||||||
|
void WriteToConfiguration(CJsonWriter *pWriter) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CExtraMenuTouchButtonBehavior : public CPredefinedTouchButtonBehavior
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr const char *BEHAVIOR_ID = "extra-menu";
|
||||||
|
|
||||||
|
CExtraMenuTouchButtonBehavior() :
|
||||||
|
CPredefinedTouchButtonBehavior(BEHAVIOR_ID) {}
|
||||||
|
|
||||||
|
CButtonLabel GetLabel() const override;
|
||||||
|
void OnDeactivate() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CEmoticonTouchButtonBehavior : public CPredefinedTouchButtonBehavior
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr const char *BEHAVIOR_ID = "emoticon";
|
||||||
|
|
||||||
|
CEmoticonTouchButtonBehavior() :
|
||||||
|
CPredefinedTouchButtonBehavior(BEHAVIOR_ID) {}
|
||||||
|
|
||||||
|
CButtonLabel GetLabel() const override;
|
||||||
|
void OnDeactivate() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSpectateTouchButtonBehavior : public CPredefinedTouchButtonBehavior
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr const char *BEHAVIOR_ID = "spectate";
|
||||||
|
|
||||||
|
CSpectateTouchButtonBehavior() :
|
||||||
|
CPredefinedTouchButtonBehavior(BEHAVIOR_ID) {}
|
||||||
|
|
||||||
|
CButtonLabel GetLabel() const override;
|
||||||
|
void OnDeactivate() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSwapActionTouchButtonBehavior : public CPredefinedTouchButtonBehavior
|
||||||
|
{
|
||||||
|
int m_ActiveAction = NUM_ACTIONS;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr const char *BEHAVIOR_ID = "swap-action";
|
||||||
|
|
||||||
|
CSwapActionTouchButtonBehavior() :
|
||||||
|
CPredefinedTouchButtonBehavior(BEHAVIOR_ID) {}
|
||||||
|
|
||||||
|
CButtonLabel GetLabel() const override;
|
||||||
|
void OnActivate() override;
|
||||||
|
void OnDeactivate() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CUseActionTouchButtonBehavior : public CPredefinedTouchButtonBehavior
|
||||||
|
{
|
||||||
|
int m_ActiveAction = NUM_ACTIONS;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr const char *BEHAVIOR_ID = "use-action";
|
||||||
|
|
||||||
|
CUseActionTouchButtonBehavior() :
|
||||||
|
CPredefinedTouchButtonBehavior(BEHAVIOR_ID) {}
|
||||||
|
|
||||||
|
CButtonLabel GetLabel() const override;
|
||||||
|
void OnActivate() override;
|
||||||
|
void OnDeactivate() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CJoystickTouchButtonBehavior : public CPredefinedTouchButtonBehavior
|
||||||
|
{
|
||||||
|
int m_ActiveAction = NUM_ACTIONS;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CJoystickTouchButtonBehavior(const char *pId) :
|
||||||
|
CPredefinedTouchButtonBehavior(pId) {}
|
||||||
|
|
||||||
|
CButtonLabel GetLabel() const override;
|
||||||
|
void OnActivate() override;
|
||||||
|
void OnDeactivate() override;
|
||||||
|
void OnUpdate() override;
|
||||||
|
int ActiveAction() const { return m_ActiveAction; }
|
||||||
|
virtual int SelectedAction() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CJoystickActionTouchButtonBehavior : public CJoystickTouchButtonBehavior
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr const char *BEHAVIOR_ID = "joystick-action";
|
||||||
|
|
||||||
|
CJoystickActionTouchButtonBehavior() :
|
||||||
|
CJoystickTouchButtonBehavior(BEHAVIOR_ID) {}
|
||||||
|
~CJoystickActionTouchButtonBehavior();
|
||||||
|
|
||||||
|
void Init(CTouchButton *pTouchButton) override;
|
||||||
|
int SelectedAction() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CJoystickFireTouchButtonBehavior : public CJoystickTouchButtonBehavior
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr const char *BEHAVIOR_ID = "joystick-fire";
|
||||||
|
|
||||||
|
CJoystickFireTouchButtonBehavior() :
|
||||||
|
CJoystickTouchButtonBehavior(BEHAVIOR_ID) {}
|
||||||
|
|
||||||
|
int SelectedAction() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CJoystickHookTouchButtonBehavior : public CJoystickTouchButtonBehavior
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr const char *BEHAVIOR_ID = "joystick-hook";
|
||||||
|
|
||||||
|
CJoystickHookTouchButtonBehavior() :
|
||||||
|
CJoystickTouchButtonBehavior(BEHAVIOR_ID) {}
|
||||||
|
|
||||||
|
int SelectedAction() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic behavior implementation that executes a console command like a bind.
|
||||||
|
*/
|
||||||
|
class CBindTouchButtonBehavior : public CTouchButtonBehavior
|
||||||
|
{
|
||||||
|
std::string m_Label;
|
||||||
|
CButtonLabel::EType m_LabelType;
|
||||||
|
std::string m_Command;
|
||||||
|
|
||||||
|
bool m_Repeating = false;
|
||||||
|
std::chrono::nanoseconds m_LastUpdateTime;
|
||||||
|
std::chrono::nanoseconds m_AccumulatedRepeatingTime;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr const char *BEHAVIOR_TYPE = "bind";
|
||||||
|
|
||||||
|
CBindTouchButtonBehavior(const char *pLabel, CButtonLabel::EType LabelType, const char *pCommand) :
|
||||||
|
m_Label(pLabel),
|
||||||
|
m_LabelType(LabelType),
|
||||||
|
m_Command(pCommand) {}
|
||||||
|
|
||||||
|
CButtonLabel GetLabel() const override;
|
||||||
|
void OnActivate() override;
|
||||||
|
void OnDeactivate() override;
|
||||||
|
void OnUpdate() override;
|
||||||
|
void WriteToConfiguration(CJsonWriter *pWriter) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool m_DirectTouchIngame = true;
|
||||||
|
bool m_DirectTouchSpectate = true;
|
||||||
|
|
||||||
|
std::vector<CTouchButton> m_vTouchButtons;
|
||||||
|
|
||||||
|
bool m_ExtraMenuActive = false;
|
||||||
|
|
||||||
|
class CActionState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool m_Active = false;
|
||||||
|
IInput::CTouchFinger m_Finger;
|
||||||
|
};
|
||||||
|
|
||||||
|
int m_ActionSelected = ACTION_FIRE;
|
||||||
|
int m_ActionLastActivated = ACTION_FIRE;
|
||||||
|
CActionState m_aActionStates[NUM_ACTIONS];
|
||||||
|
CJoystickActionTouchButtonBehavior *m_pPrimaryJoystickTouchButtonBehavior;
|
||||||
|
|
||||||
|
bool m_EditingActive = false;
|
||||||
|
bool m_EditingChanges = false;
|
||||||
|
|
||||||
|
void InitVisibilityFunctions();
|
||||||
|
void UpdateButtons(const std::vector<IInput::CTouchFingerState> &vTouchFingerStates);
|
||||||
|
void RenderButtons();
|
||||||
|
vec2 CalculateScreenSize() const;
|
||||||
|
|
||||||
|
std::unique_ptr<CPredefinedTouchButtonBehavior> ParsePredefinedBehavior(const json_value *pBehaviorObject);
|
||||||
|
std::unique_ptr<CBindTouchButtonBehavior> ParseBindBehavior(const json_value *pBehaviorObject);
|
||||||
|
std::unique_ptr<CTouchButtonBehavior> ParseBehavior(const json_value *pBehaviorObject);
|
||||||
|
std::optional<CTouchButton> ParseButton(const json_value *pButtonObject);
|
||||||
|
bool ParseConfiguration(const void *pFileData, unsigned FileLength);
|
||||||
|
void WriteConfiguration(CJsonWriter *pWriter);
|
||||||
|
|
||||||
|
public:
|
||||||
|
int Sizeof() const override { return sizeof(*this); }
|
||||||
|
void OnInit() override;
|
||||||
|
void OnReset() override;
|
||||||
|
void OnWindowResize() override;
|
||||||
|
bool OnTouchState(const std::vector<IInput::CTouchFingerState> &vTouchFingerStates) override;
|
||||||
|
void OnRender() override;
|
||||||
|
|
||||||
|
bool LoadConfigurationFromFile(int StorageType);
|
||||||
|
bool LoadConfigurationFromClipboard();
|
||||||
|
bool SaveConfigurationToFile();
|
||||||
|
void SaveConfigurationToClipboard();
|
||||||
|
|
||||||
|
bool IsDirectTouchIngame() const { return m_DirectTouchIngame; }
|
||||||
|
void SetDirectTouchIngame(bool DirectTouchIngame)
|
||||||
|
{
|
||||||
|
m_DirectTouchIngame = DirectTouchIngame;
|
||||||
|
m_EditingChanges = true;
|
||||||
|
}
|
||||||
|
bool IsDirectTouchSpectate() const { return m_DirectTouchSpectate; }
|
||||||
|
void SetDirectTouchSpectate(bool DirectTouchSpectate)
|
||||||
|
{
|
||||||
|
m_DirectTouchSpectate = DirectTouchSpectate;
|
||||||
|
m_EditingChanges = true;
|
||||||
|
}
|
||||||
|
bool IsEditingActive() const { return m_EditingActive; }
|
||||||
|
void SetEditingActive(bool EditingActive) { m_EditingActive = EditingActive; }
|
||||||
|
bool HasEditingChanges() const { return m_EditingChanges; }
|
||||||
|
void SetEditingChanges(bool EditingChanges) { m_EditingChanges = EditingChanges; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -145,6 +145,7 @@ void CGameClient::OnConsoleInit()
|
||||||
&m_Chat,
|
&m_Chat,
|
||||||
&m_Broadcast,
|
&m_Broadcast,
|
||||||
&m_DebugHud,
|
&m_DebugHud,
|
||||||
|
&m_TouchControls,
|
||||||
&m_Scoreboard,
|
&m_Scoreboard,
|
||||||
&m_Statboard,
|
&m_Statboard,
|
||||||
&m_Motd,
|
&m_Motd,
|
||||||
|
@ -164,6 +165,7 @@ void CGameClient::OnConsoleInit()
|
||||||
&m_Emoticon,
|
&m_Emoticon,
|
||||||
&m_Menus,
|
&m_Menus,
|
||||||
&m_Controls,
|
&m_Controls,
|
||||||
|
&m_TouchControls,
|
||||||
&m_Binds});
|
&m_Binds});
|
||||||
|
|
||||||
// add basic console commands
|
// add basic console commands
|
||||||
|
@ -443,6 +445,23 @@ void CGameClient::OnUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle touch events
|
||||||
|
const std::vector<IInput::CTouchFingerState> &vTouchFingerStates = Input()->TouchFingerStates();
|
||||||
|
bool TouchHandled = false;
|
||||||
|
for(auto &pComponent : m_vpInput)
|
||||||
|
{
|
||||||
|
if(TouchHandled)
|
||||||
|
{
|
||||||
|
// Also update inactive components so they can handle touch fingers being released.
|
||||||
|
pComponent->OnTouchState({});
|
||||||
|
}
|
||||||
|
else if(pComponent->OnTouchState(vTouchFingerStates))
|
||||||
|
{
|
||||||
|
Input()->ClearTouchDeltas();
|
||||||
|
TouchHandled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// handle key presses
|
// handle key presses
|
||||||
Input()->ConsumeEvents([&](const IInput::CEvent &Event) {
|
Input()->ConsumeEvents([&](const IInput::CEvent &Event) {
|
||||||
for(auto &pComponent : m_vpInput)
|
for(auto &pComponent : m_vpInput)
|
||||||
|
|
|
@ -58,6 +58,7 @@
|
||||||
#include "components/spectator.h"
|
#include "components/spectator.h"
|
||||||
#include "components/statboard.h"
|
#include "components/statboard.h"
|
||||||
#include "components/tooltips.h"
|
#include "components/tooltips.h"
|
||||||
|
#include "components/touch_controls.h"
|
||||||
#include "components/voting.h"
|
#include "components/voting.h"
|
||||||
|
|
||||||
class CGameInfo
|
class CGameInfo
|
||||||
|
@ -146,6 +147,7 @@ public:
|
||||||
CSounds m_Sounds;
|
CSounds m_Sounds;
|
||||||
CEmoticon m_Emoticon;
|
CEmoticon m_Emoticon;
|
||||||
CDamageInd m_DamageInd;
|
CDamageInd m_DamageInd;
|
||||||
|
CTouchControls m_TouchControls;
|
||||||
CVoting m_Voting;
|
CVoting m_Voting;
|
||||||
CSpectator m_Spectator;
|
CSpectator m_Spectator;
|
||||||
|
|
||||||
|
|
|
@ -7691,7 +7691,7 @@ void CEditor::RenderMenubar(CUIRect MenuBar)
|
||||||
if(DoButton_Ex(&s_SettingsButton, "Settings", 0, &SettingsButton, 0, nullptr, IGraphics::CORNER_T, EditorFontSizes::MENU, TEXTALIGN_ML))
|
if(DoButton_Ex(&s_SettingsButton, "Settings", 0, &SettingsButton, 0, nullptr, IGraphics::CORNER_T, EditorFontSizes::MENU, TEXTALIGN_ML))
|
||||||
{
|
{
|
||||||
static SPopupMenuId s_PopupMenuEntitiesId;
|
static SPopupMenuId s_PopupMenuEntitiesId;
|
||||||
Ui()->DoPopupMenu(&s_PopupMenuEntitiesId, SettingsButton.x, SettingsButton.y + SettingsButton.h - 1.0f, 200.0f, 92.0f, this, PopupMenuSettings, PopupProperties);
|
Ui()->DoPopupMenu(&s_PopupMenuEntitiesId, SettingsButton.x, SettingsButton.y + SettingsButton.h - 1.0f, 200.0f, 106.0f, this, PopupMenuSettings, PopupProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
CUIRect ChangedIndicator, Info, Help, Close;
|
CUIRect ChangedIndicator, Info, Help, Close;
|
||||||
|
@ -8592,7 +8592,7 @@ void CEditor::HandleWriterFinishJobs()
|
||||||
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "editor/save", aBuf);
|
Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "editor/save", aBuf);
|
||||||
|
|
||||||
// send rcon.. if we can
|
// send rcon.. if we can
|
||||||
if(Client()->RconAuthed())
|
if(Client()->RconAuthed() && g_Config.m_EdAutoMapReload)
|
||||||
{
|
{
|
||||||
CServerInfo CurrentServerInfo;
|
CServerInfo CurrentServerInfo;
|
||||||
Client()->GetServerInfo(&CurrentServerInfo);
|
Client()->GetServerInfo(&CurrentServerInfo);
|
||||||
|
|
|
@ -371,6 +371,30 @@ CUi::EPopupMenuFunctionResult CEditor::PopupMenuSettings(void *pContext, CUIRect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
View.HSplitTop(2.0f, nullptr, &View);
|
||||||
|
View.HSplitTop(12.0f, &Slot, &View);
|
||||||
|
{
|
||||||
|
Slot.VMargin(5.0f, &Slot);
|
||||||
|
|
||||||
|
CUIRect Label, Selector;
|
||||||
|
Slot.VSplitMid(&Label, &Selector);
|
||||||
|
CUIRect No, Yes;
|
||||||
|
Selector.VSplitMid(&No, &Yes);
|
||||||
|
|
||||||
|
pEditor->Ui()->DoLabel(&Label, "Auto map reload", 10.0f, TEXTALIGN_ML);
|
||||||
|
|
||||||
|
static int s_ButtonNo = 0;
|
||||||
|
static int s_ButtonYes = 0;
|
||||||
|
if(pEditor->DoButton_Ex(&s_ButtonNo, "No", !g_Config.m_EdAutoMapReload, &No, 0, "Do not run 'hot_reload' on the local server while rcon authed on map save", IGraphics::CORNER_L))
|
||||||
|
{
|
||||||
|
g_Config.m_EdAutoMapReload = false;
|
||||||
|
}
|
||||||
|
if(pEditor->DoButton_Ex(&s_ButtonYes, "Yes", g_Config.m_EdAutoMapReload, &Yes, 0, "Run 'hot_reload' on the local server while rcon authed on map save", IGraphics::CORNER_R))
|
||||||
|
{
|
||||||
|
g_Config.m_EdAutoMapReload = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return CUi::POPUP_KEEP_OPEN;
|
return CUi::POPUP_KEEP_OPEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,13 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos)
|
||||||
delete GameServer()->m_apSavedTees[m_pPlayer->GetCid()];
|
delete GameServer()->m_apSavedTees[m_pPlayer->GetCid()];
|
||||||
GameServer()->m_apSavedTees[m_pPlayer->GetCid()] = nullptr;
|
GameServer()->m_apSavedTees[m_pPlayer->GetCid()] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(GameServer()->m_apSavedTeleTees[m_pPlayer->GetCid()])
|
||||||
|
{
|
||||||
|
m_pPlayer->m_LastTeleTee = *GameServer()->m_apSavedTeleTees[m_pPlayer->GetCid()];
|
||||||
|
delete GameServer()->m_apSavedTeleTees[m_pPlayer->GetCid()];
|
||||||
|
GameServer()->m_apSavedTeleTees[m_pPlayer->GetCid()] = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -108,6 +108,9 @@ void CGameContext::Construct(int Resetting)
|
||||||
for(auto &pSavedTee : m_apSavedTees)
|
for(auto &pSavedTee : m_apSavedTees)
|
||||||
pSavedTee = nullptr;
|
pSavedTee = nullptr;
|
||||||
|
|
||||||
|
for(auto &pSavedTeleTee : m_apSavedTeleTees)
|
||||||
|
pSavedTeleTee = nullptr;
|
||||||
|
|
||||||
for(auto &pSavedTeam : m_apSavedTeams)
|
for(auto &pSavedTeam : m_apSavedTeams)
|
||||||
pSavedTeam = nullptr;
|
pSavedTeam = nullptr;
|
||||||
|
|
||||||
|
@ -131,6 +134,9 @@ void CGameContext::Destruct(int Resetting)
|
||||||
for(auto &pSavedTee : m_apSavedTees)
|
for(auto &pSavedTee : m_apSavedTees)
|
||||||
delete pSavedTee;
|
delete pSavedTee;
|
||||||
|
|
||||||
|
for(auto &pSavedTeleTee : m_apSavedTeleTees)
|
||||||
|
delete pSavedTeleTee;
|
||||||
|
|
||||||
for(auto &pSavedTeam : m_apSavedTeams)
|
for(auto &pSavedTeam : m_apSavedTeams)
|
||||||
delete pSavedTeam;
|
delete pSavedTeam;
|
||||||
|
|
||||||
|
@ -773,7 +779,6 @@ void CGameContext::StartVote(const char *pDesc, const char *pCommand, const char
|
||||||
{
|
{
|
||||||
// reset votes
|
// reset votes
|
||||||
m_VoteEnforce = VOTE_ENFORCE_UNKNOWN;
|
m_VoteEnforce = VOTE_ENFORCE_UNKNOWN;
|
||||||
m_VoteEnforcer = -1;
|
|
||||||
for(auto &pPlayer : m_apPlayers)
|
for(auto &pPlayer : m_apPlayers)
|
||||||
{
|
{
|
||||||
if(pPlayer)
|
if(pPlayer)
|
||||||
|
@ -1204,7 +1209,7 @@ void CGameContext::OnTick()
|
||||||
}
|
}
|
||||||
else if(m_VoteEnforce == VOTE_ENFORCE_YES_ADMIN)
|
else if(m_VoteEnforce == VOTE_ENFORCE_YES_ADMIN)
|
||||||
{
|
{
|
||||||
Console()->ExecuteLine(m_aVoteCommand, m_VoteEnforcer);
|
Console()->ExecuteLine(m_aVoteCommand, m_VoteCreator);
|
||||||
SendChat(-1, TEAM_ALL, "Vote passed enforced by authorized player", -1, FLAG_SIX);
|
SendChat(-1, TEAM_ALL, "Vote passed enforced by authorized player", -1, FLAG_SIX);
|
||||||
EndVote();
|
EndVote();
|
||||||
}
|
}
|
||||||
|
@ -1712,6 +1717,9 @@ void CGameContext::OnClientDrop(int ClientId, const char *pReason)
|
||||||
delete m_apSavedTees[ClientId];
|
delete m_apSavedTees[ClientId];
|
||||||
m_apSavedTees[ClientId] = nullptr;
|
m_apSavedTees[ClientId] = nullptr;
|
||||||
|
|
||||||
|
delete m_apSavedTeleTees[ClientId];
|
||||||
|
m_apSavedTeleTees[ClientId] = nullptr;
|
||||||
|
|
||||||
m_aTeamMapping[ClientId] = -1;
|
m_aTeamMapping[ClientId] = -1;
|
||||||
|
|
||||||
m_VoteUpdate = true;
|
m_VoteUpdate = true;
|
||||||
|
@ -3208,12 +3216,19 @@ void CGameContext::ConHotReload(IConsole::IResult *pResult, void *pUserData)
|
||||||
if(!pSelf->GetPlayerChar(i))
|
if(!pSelf->GetPlayerChar(i))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
CCharacter *pChar = pSelf->GetPlayerChar(i);
|
||||||
|
|
||||||
// Save the tee individually
|
// Save the tee individually
|
||||||
pSelf->m_apSavedTees[i] = new CSaveTee();
|
pSelf->m_apSavedTees[i] = new CSaveTee();
|
||||||
pSelf->m_apSavedTees[i]->Save(pSelf->GetPlayerChar(i), false);
|
pSelf->m_apSavedTees[i]->Save(pChar, false);
|
||||||
|
|
||||||
|
if(pSelf->m_apPlayers[i])
|
||||||
|
pSelf->m_apSavedTeleTees[i] = new CSaveTee(pSelf->m_apPlayers[i]->m_LastTeleTee);
|
||||||
|
|
||||||
// Save the team state
|
// Save the team state
|
||||||
pSelf->m_aTeamMapping[i] = pSelf->GetDDRaceTeam(i);
|
pSelf->m_aTeamMapping[i] = pSelf->GetDDRaceTeam(i);
|
||||||
|
if(pSelf->m_aTeamMapping[i] == TEAM_SUPER)
|
||||||
|
pSelf->m_aTeamMapping[i] = pChar->m_TeamBeforeSuper;
|
||||||
|
|
||||||
if(pSelf->m_apSavedTeams[pSelf->m_aTeamMapping[i]])
|
if(pSelf->m_apSavedTeams[pSelf->m_aTeamMapping[i]])
|
||||||
continue;
|
continue;
|
||||||
|
@ -3778,7 +3793,7 @@ void CGameContext::RegisterChatCommands()
|
||||||
Console()->Register("rescuemode", "?r['auto'|'manual']", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConRescueMode, this, "Sets one of the two rescue modes (auto or manual). Prints current mode if no arguments provided");
|
Console()->Register("rescuemode", "?r['auto'|'manual']", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConRescueMode, this, "Sets one of the two rescue modes (auto or manual). Prints current mode if no arguments provided");
|
||||||
Console()->Register("tp", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConTeleTo, this, "Depending on the number of supplied arguments, teleport yourself to; (0.) where you are spectating or aiming; (1.) the specified player name");
|
Console()->Register("tp", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConTeleTo, this, "Depending on the number of supplied arguments, teleport yourself to; (0.) where you are spectating or aiming; (1.) the specified player name");
|
||||||
Console()->Register("teleport", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConTeleTo, this, "Depending on the number of supplied arguments, teleport yourself to; (0.) where you are spectating or aiming; (1.) the specified player name");
|
Console()->Register("teleport", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConTeleTo, this, "Depending on the number of supplied arguments, teleport yourself to; (0.) where you are spectating or aiming; (1.) the specified player name");
|
||||||
Console()->Register("tpxy", "f[x] f[y]", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConTeleXY, this, "Teleport yourself to the specified coordinates. A tilde (~) can be used to denote your current position, e.g. '/tpxy ~1 ~' to teleport one tile to the right");
|
Console()->Register("tpxy", "s[x] s[y]", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConTeleXY, this, "Teleport yourself to the specified coordinates. A tilde (~) can be used to denote your current position, e.g. '/tpxy ~1 ~' to teleport one tile to the right");
|
||||||
Console()->Register("lasttp", "", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConLastTele, this, "Teleport yourself to the last location you teleported to");
|
Console()->Register("lasttp", "", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConLastTele, this, "Teleport yourself to the last location you teleported to");
|
||||||
Console()->Register("tc", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConTeleCursor, this, "Teleport yourself to player or to where you are spectating/or looking if no player name is given");
|
Console()->Register("tc", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConTeleCursor, this, "Teleport yourself to player or to where you are spectating/or looking if no player name is given");
|
||||||
Console()->Register("telecursor", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConTeleCursor, this, "Teleport yourself to player or to where you are spectating/or looking if no player name is given");
|
Console()->Register("telecursor", "?r[player name]", CFGFLAG_CHAT | CFGFLAG_SERVER | CMDFLAG_PRACTICE, ConTeleCursor, this, "Teleport yourself to player or to where you are spectating/or looking if no player name is given");
|
||||||
|
@ -4820,7 +4835,6 @@ void CGameContext::ForceVote(int EnforcerId, bool Success)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_VoteEnforce = Success ? CGameContext::VOTE_ENFORCE_YES_ADMIN : CGameContext::VOTE_ENFORCE_NO_ADMIN;
|
m_VoteEnforce = Success ? CGameContext::VOTE_ENFORCE_YES_ADMIN : CGameContext::VOTE_ENFORCE_NO_ADMIN;
|
||||||
m_VoteEnforcer = EnforcerId;
|
|
||||||
|
|
||||||
char aBuf[256];
|
char aBuf[256];
|
||||||
const char *pOption = Success ? "yes" : "no";
|
const char *pOption = Success ? "yes" : "no";
|
||||||
|
|
|
@ -183,6 +183,7 @@ public:
|
||||||
bool m_aPlayerHasInput[MAX_CLIENTS];
|
bool m_aPlayerHasInput[MAX_CLIENTS];
|
||||||
CSaveTeam *m_apSavedTeams[MAX_CLIENTS];
|
CSaveTeam *m_apSavedTeams[MAX_CLIENTS];
|
||||||
CSaveTee *m_apSavedTees[MAX_CLIENTS];
|
CSaveTee *m_apSavedTees[MAX_CLIENTS];
|
||||||
|
CSaveTee *m_apSavedTeleTees[MAX_CLIENTS];
|
||||||
int m_aTeamMapping[MAX_CLIENTS];
|
int m_aTeamMapping[MAX_CLIENTS];
|
||||||
|
|
||||||
// returns last input if available otherwise nulled PlayerInput object
|
// returns last input if available otherwise nulled PlayerInput object
|
||||||
|
@ -575,7 +576,6 @@ public:
|
||||||
VOTE_TYPE_SPECTATE,
|
VOTE_TYPE_SPECTATE,
|
||||||
};
|
};
|
||||||
int m_VoteVictim;
|
int m_VoteVictim;
|
||||||
int m_VoteEnforcer;
|
|
||||||
|
|
||||||
inline bool IsOptionVote() const { return m_VoteType == VOTE_TYPE_OPTION; }
|
inline bool IsOptionVote() const { return m_VoteType == VOTE_TYPE_OPTION; }
|
||||||
inline bool IsKickVote() const { return m_VoteType == VOTE_TYPE_KICK; }
|
inline bool IsKickVote() const { return m_VoteType == VOTE_TYPE_KICK; }
|
||||||
|
|
Loading…
Reference in a new issue