Compare commits

...

14 commits

Author SHA1 Message Date
Dennis Felsing 5407db0236
Merge pull request #8987 from Robyt3/Client-Skins-Randomize-Function
Move `CMenus::RandomSkin` function to `CSkins::RandomizeSkin`
2024-09-18 16:28:00 +00:00
Dennis Felsing d2348b2e06
Merge pull request #8986 from Robyt3/Client-Localize-Hz
Localize `Hz` unit of refresh rate settings
2024-09-18 15:44:02 +00:00
Robert Müller 96cc8c5830 Move CMenus::RandomSkin function to CSkins::RandomizeSkin
This function is independent from the menus and this also makes it consistent with the `CSkins7::RandomizeSkin` function.
2024-09-18 17:36:42 +02:00
Robert Müller 45808841ac Localize Hz unit of refresh rate settings 2024-09-18 17:20:31 +02:00
Dennis Felsing 78d702d3b7
Merge pull request #8981 from ChillerDragon/pr_qa_md
Add quick action "Map details"
2024-09-18 13:04:09 +00:00
Dennis Felsing cbc21fab4a
Merge pull request #8984 from ChillerDragon/pr_qa_afl
Add quick action "Add front layer"
2024-09-18 13:03:00 +00:00
ChillerDragon 3781f95190 Add quick action "Add front layer" 2024-09-18 20:07:00 +08:00
ChillerDragon 32e8bb1f05 Add quick action "Map details" 2024-09-18 19:27:39 +08:00
Robert Müller a2e0ab2dbe
Merge pull request #8973 from furo321/improve-annoucements
Various improvements to announcements
2024-09-18 10:34:53 +00:00
Robert Müller 255694c061
Merge pull request #8975 from furo321/android-save-minimized
Save the config file when the app is minimized on Android
2024-09-18 10:29:09 +00:00
furo b475c67039 Various improvements to announcements 2024-09-18 12:16:29 +02:00
furo a266cd2f70 Save the config file when the app is minimized on Android 2024-09-18 12:10:25 +02:00
Robert Müller 2c77e79061
Merge pull request #8980 from ChillerDragon/pr_fix_team_colors_sixup
Fix 0.7 client team colors (Closed #8977)
2024-09-18 09:51:35 +00:00
ChillerDragon 46c5344d71 Fix 0.7 client team colors (Closed #8977) 2024-09-18 16:50:23 +08:00
23 changed files with 174 additions and 103 deletions

View file

@ -996,6 +996,7 @@ endif()
########################################################################
set(EXPECTED_DATA
announcement.txt
arrow.png
assets/entities/comfort/ddnet.png
assets/entities/license.txt

0
data/announcement.txt Normal file
View file

View file

@ -80,10 +80,10 @@ sv_rescue_delay 5
# Message on chat displayed when joining
sv_welcome "Welcome to my server!"
# File which will have the announcements (each one in new line)
# File which contains the announcements (One on each line)
sv_announcement_filename "announcement.txt"
# Number of minutes before next announcement will be displayed (from the announcement file)
# Number of minutes before the next announcement will be displayed (from the announcement file)
sv_announcement_interval 120
# Whether announcements will be displayed in their order or chosen randomly

View file

@ -80,6 +80,7 @@ void CInput::Init()
m_pGraphics = Kernel()->RequestInterface<IEngineGraphics>();
m_pConsole = Kernel()->RequestInterface<IConsole>();
m_pConfigManager = Kernel()->RequestInterface<IConfigManager>();
MouseModeRelative();
@ -824,6 +825,9 @@ int CInput::Update()
}
break;
case SDL_WINDOWEVENT_MINIMIZED:
#if defined(CONF_PLATFORM_ANDROID) // Save the config when minimized on Android.
m_pConfigManager->Save();
#endif
Graphics()->WindowDestroyNtf(Event.window.windowID);
break;

View file

@ -14,6 +14,7 @@
#include <vector>
class IEngineGraphics;
class IConfigManager;
class CInput : public IEngineInput
{
@ -59,6 +60,7 @@ public:
private:
IEngineGraphics *m_pGraphics;
IConsole *m_pConsole;
IConfigManager *m_pConfigManager;
IEngineGraphics *Graphics() const { return m_pGraphics; }
IConsole *Console() const { return m_pConsole; }

View file

@ -273,7 +273,8 @@ public:
virtual bool DnsblWhite(int ClientId) = 0;
virtual bool DnsblPending(int ClientId) = 0;
virtual bool DnsblBlack(int ClientId) = 0;
virtual const char *GetAnnouncementLine(const char *pFileName) = 0;
virtual const char *GetAnnouncementLine() = 0;
virtual void ReadAnnouncementsFile(const char *pFileName) = 0;
virtual bool ClientPrevIngame(int ClientId) = 0;
virtual const char *GetNetErrorString(int ClientId) = 0;
virtual void ResetNetErrorString(int ClientId) = 0;

View file

@ -537,8 +537,7 @@ int CServer::Init()
m_CurrentGameTick = MIN_TICK;
m_AnnouncementLastLine = 0;
m_aAnnouncementFile[0] = '\0';
m_AnnouncementLastLine = -1;
mem_zero(m_aPrevStates, sizeof(m_aPrevStates));
return 0;
@ -2783,6 +2782,8 @@ int CServer::Run()
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
}
ReadAnnouncementsFile(g_Config.m_SvAnnouncementFileName);
// process pending commands
m_pConsole->StoreCommands(false);
m_pRegister->OnConfigChange();
@ -3809,6 +3810,17 @@ void CServer::ConchainStdoutOutputLevel(IConsole::IResult *pResult, void *pUserD
}
}
void CServer::ConchainAnnouncementFileName(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
CServer *pSelf = (CServer *)pUserData;
bool Changed = pResult->NumArguments() && str_comp(pResult->GetString(0), g_Config.m_SvAnnouncementFileName);
pfnCallback(pResult, pCallbackUserData);
if(Changed)
{
pSelf->ReadAnnouncementsFile(g_Config.m_SvAnnouncementFileName);
}
}
#if defined(CONF_FAMILY_UNIX)
void CServer::ConchainConnLoggingServerChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
@ -3887,6 +3899,8 @@ void CServer::RegisterCommands()
Console()->Chain("loglevel", ConchainLoglevel, this);
Console()->Chain("stdout_output_level", ConchainStdoutOutputLevel, this);
Console()->Chain("sv_announcement_filename", ConchainAnnouncementFileName, this);
#if defined(CONF_FAMILY_UNIX)
Console()->Chain("sv_conn_logging_server", ConchainConnLoggingServerChange, this);
#endif
@ -3930,27 +3944,30 @@ void CServer::GetClientAddr(int ClientId, NETADDR *pAddr) const
}
}
const char *CServer::GetAnnouncementLine(const char *pFileName)
void CServer::ReadAnnouncementsFile(const char *pFileName)
{
if(str_comp(pFileName, m_aAnnouncementFile) != 0)
{
str_copy(m_aAnnouncementFile, pFileName);
m_vAnnouncements.clear();
m_vAnnouncements.clear();
CLineReader LineReader;
if(!LineReader.OpenFile(m_pStorage->OpenFile(pFileName, IOFLAG_READ, IStorage::TYPE_ALL)))
if(pFileName[0] == '\0')
return;
CLineReader LineReader;
if(!LineReader.OpenFile(m_pStorage->OpenFile(pFileName, IOFLAG_READ, IStorage::TYPE_ALL)))
{
dbg_msg("announcements", "failed to open '%s'", pFileName);
return;
}
while(const char *pLine = LineReader.Get())
{
if(str_length(pLine) && pLine[0] != '#')
{
return 0;
}
while(const char *pLine = LineReader.Get())
{
if(str_length(pLine) && pLine[0] != '#')
{
m_vAnnouncements.emplace_back(pLine);
}
m_vAnnouncements.emplace_back(pLine);
}
}
}
const char *CServer::GetAnnouncementLine()
{
if(m_vAnnouncements.empty())
{
return 0;
@ -3959,7 +3976,7 @@ const char *CServer::GetAnnouncementLine(const char *pFileName)
{
m_AnnouncementLastLine = 0;
}
else if(!Config()->m_SvAnnouncementRandom)
else if(!g_Config.m_SvAnnouncementRandom)
{
if(++m_AnnouncementLastLine >= m_vAnnouncements.size())
m_AnnouncementLastLine %= m_vAnnouncements.size();

View file

@ -259,7 +259,6 @@ public:
size_t m_AnnouncementLastLine;
std::vector<std::string> m_vAnnouncements;
char m_aAnnouncementFile[IO_MAX_PATH_LENGTH];
std::shared_ptr<ILogger> m_pFileLogger = nullptr;
std::shared_ptr<ILogger> m_pStdoutLogger = nullptr;
@ -427,6 +426,7 @@ public:
static void ConchainSixupUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainLoglevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainStdoutOutputLevel(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
static void ConchainAnnouncementFileName(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
#if defined(CONF_FAMILY_UNIX)
static void ConchainConnLoggingServerChange(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
@ -443,7 +443,8 @@ public:
void GetClientAddr(int ClientId, NETADDR *pAddr) const override;
int m_aPrevStates[MAX_CLIENTS];
const char *GetAnnouncementLine(const char *pFileName) override;
const char *GetAnnouncementLine() override;
void ReadAnnouncementsFile(const char *pFileName) override;
int *GetIdMap(int ClientId) override;

View file

@ -548,8 +548,8 @@ MACRO_CONFIG_INT(SvMinTeamSize, sv_min_team_size, 2, 1, MAX_CLIENTS, CFGFLAG_SER
MACRO_CONFIG_INT(SvMaxTeamSize, sv_max_team_size, MAX_CLIENTS, 1, MAX_CLIENTS, CFGFLAG_SERVER | CFGFLAG_GAME, "Maximum team size")
MACRO_CONFIG_INT(SvMapVote, sv_map_vote, 1, 0, 1, CFGFLAG_SERVER, "Whether to allow /map")
MACRO_CONFIG_STR(SvAnnouncementFileName, sv_announcement_filename, 24, "announcement.txt", CFGFLAG_SERVER, "file which will have the announcement, each one at a line")
MACRO_CONFIG_INT(SvAnnouncementInterval, sv_announcement_interval, 300, 1, 9999, CFGFLAG_SERVER, "time(minutes) in which the announcement will be displayed from the announcement file")
MACRO_CONFIG_STR(SvAnnouncementFileName, sv_announcement_filename, IO_MAX_PATH_LENGTH, "announcement.txt", CFGFLAG_SERVER, "File which contains the announcements, one on each line")
MACRO_CONFIG_INT(SvAnnouncementInterval, sv_announcement_interval, 120, 1, 9999, CFGFLAG_SERVER, "The time (minutes) for how often an announcement will be displayed from the announcement file")
MACRO_CONFIG_INT(SvAnnouncementRandom, sv_announcement_random, 1, 0, 1, CFGFLAG_SERVER, "Whether announcements are sequential or random")
MACRO_CONFIG_INT(SvOldLaser, sv_old_laser, 0, 0, 1, CFGFLAG_SERVER | CFGFLAG_GAME, "Whether lasers can hit you if you shot them and that they pull you towards the bounce origin (0 for all new maps) or lasers can't hit you if you shot them, and they pull others towards the shooter")

View file

@ -95,7 +95,6 @@ class CMenus : public CComponent
void DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, bool Active);
bool m_SkinListNeedsUpdate = false;
void RandomSkin();
// menus_settings_assets.cpp
public:

View file

@ -152,7 +152,9 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
Left.HSplitTop(10.0f, nullptr, &Left);
Left.HSplitTop(20.0f, &Button, &Left);
Ui()->DoScrollbarOption(&g_Config.m_ClRefreshRate, &g_Config.m_ClRefreshRate, &Button, Localize("Refresh Rate"), 10, 10000, &CUi::ms_LogarithmicScrollbarScale, CUi::SCROLLBAR_OPTION_INFINITE, " Hz");
str_copy(aBuf, " ");
str_append(aBuf, Localize("Hz", "Hertz"));
Ui()->DoScrollbarOption(&g_Config.m_ClRefreshRate, &g_Config.m_ClRefreshRate, &Button, Localize("Refresh Rate"), 10, 10000, &CUi::ms_LogarithmicScrollbarScale, CUi::SCROLLBAR_OPTION_INFINITE, aBuf);
Left.HSplitTop(5.0f, nullptr, &Left);
Left.HSplitTop(20.0f, &Button, &Left);
static int s_LowerRefreshRate;
@ -404,50 +406,6 @@ void CMenus::OnRefreshSkins()
m_SkinListNeedsUpdate = true;
}
void CMenus::RandomSkin()
{
static const float s_aSchemes[] = {1.0f / 2.0f, 1.0f / 3.0f, 1.0f / -3.0f, 1.0f / 12.0f, 1.0f / -12.0f}; // complementary, triadic, analogous
const bool UseCustomColor = !m_Dummy ? g_Config.m_ClPlayerUseCustomColor : g_Config.m_ClDummyUseCustomColor;
if(UseCustomColor)
{
float GoalSat = random_float(0.3f, 1.0f);
float MaxBodyLht = 1.0f - GoalSat * GoalSat; // max allowed lightness before we start losing saturation
ColorHSLA Body;
Body.h = random_float();
Body.l = random_float(0.0f, MaxBodyLht);
Body.s = clamp(GoalSat * GoalSat / (1.0f - Body.l), 0.0f, 1.0f);
ColorHSLA Feet;
Feet.h = std::fmod(Body.h + s_aSchemes[rand() % std::size(s_aSchemes)], 1.0f);
Feet.l = random_float();
Feet.s = clamp(GoalSat * GoalSat / (1.0f - Feet.l), 0.0f, 1.0f);
unsigned *pColorBody = !m_Dummy ? &g_Config.m_ClPlayerColorBody : &g_Config.m_ClDummyColorBody;
unsigned *pColorFeet = !m_Dummy ? &g_Config.m_ClPlayerColorFeet : &g_Config.m_ClDummyColorFeet;
*pColorBody = Body.Pack(false);
*pColorFeet = Feet.Pack(false);
}
const size_t SkinNameSize = !m_Dummy ? sizeof(g_Config.m_ClPlayerSkin) : sizeof(g_Config.m_ClDummySkin);
char aRandomSkinName[24];
str_copy(aRandomSkinName, "default", SkinNameSize);
if(!m_pClient->m_Skins.GetSkinsUnsafe().empty())
{
do
{
auto it = m_pClient->m_Skins.GetSkinsUnsafe().begin();
std::advance(it, rand() % m_pClient->m_Skins.GetSkinsUnsafe().size());
str_copy(aRandomSkinName, (*it).second->GetName(), SkinNameSize);
} while(!str_comp(aRandomSkinName, "x_ninja") || !str_comp(aRandomSkinName, "x_spec"));
}
char *pSkinName = !m_Dummy ? g_Config.m_ClPlayerSkin : g_Config.m_ClDummySkin;
str_copy(pSkinName, aRandomSkinName, SkinNameSize);
SetNeedSendInfo();
}
void CMenus::Con_AddFavoriteSkin(IConsole::IResult *pResult, void *pUserData)
{
auto *pSelf = (CMenus *)pUserData;
@ -673,7 +631,8 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_PIXEL_ALIGMENT | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
if(DoButton_Menu(&s_RandomSkinButton, s_apDice[s_CurrentDie], 0, &RandomSkinButton, nullptr, IGraphics::CORNER_ALL, 5.0f, -0.2f))
{
RandomSkin();
GameClient()->m_Skins.RandomizeSkin(m_Dummy);
SetNeedSendInfo();
s_CurrentDie = rand() % std::size(s_apDice);
}
TextRender()->SetRenderFlags(0);
@ -1628,7 +1587,9 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
}
MainView.HSplitTop(20.0f, &Button, &MainView);
Ui()->DoScrollbarOption(&g_Config.m_GfxRefreshRate, &g_Config.m_GfxRefreshRate, &Button, Localize("Refresh Rate"), 10, 1000, &CUi::ms_LinearScrollbarScale, CUi::SCROLLBAR_OPTION_INFINITE | CUi::SCROLLBAR_OPTION_NOCLAMPVALUE, " Hz");
str_copy(aBuf, " ");
str_append(aBuf, Localize("Hz", "Hertz"));
Ui()->DoScrollbarOption(&g_Config.m_GfxRefreshRate, &g_Config.m_GfxRefreshRate, &Button, Localize("Refresh Rate"), 10, 1000, &CUi::ms_LinearScrollbarScale, CUi::SCROLLBAR_OPTION_INFINITE | CUi::SCROLLBAR_OPTION_NOCLAMPVALUE, aBuf);
MainView.HSplitTop(2.0f, nullptr, &MainView);
static CButtonContainer s_UiColorResetId;

View file

@ -433,3 +433,45 @@ const CSkin *CSkins::FindImpl(const char *pName)
return nullptr;
}
void CSkins::RandomizeSkin(int Dummy)
{
static const float s_aSchemes[] = {1.0f / 2.0f, 1.0f / 3.0f, 1.0f / -3.0f, 1.0f / 12.0f, 1.0f / -12.0f}; // complementary, triadic, analogous
const bool UseCustomColor = Dummy ? g_Config.m_ClDummyUseCustomColor : g_Config.m_ClPlayerUseCustomColor;
if(UseCustomColor)
{
float GoalSat = random_float(0.3f, 1.0f);
float MaxBodyLht = 1.0f - GoalSat * GoalSat; // max allowed lightness before we start losing saturation
ColorHSLA Body;
Body.h = random_float();
Body.l = random_float(0.0f, MaxBodyLht);
Body.s = clamp(GoalSat * GoalSat / (1.0f - Body.l), 0.0f, 1.0f);
ColorHSLA Feet;
Feet.h = std::fmod(Body.h + s_aSchemes[rand() % std::size(s_aSchemes)], 1.0f);
Feet.l = random_float();
Feet.s = clamp(GoalSat * GoalSat / (1.0f - Feet.l), 0.0f, 1.0f);
unsigned *pColorBody = Dummy ? &g_Config.m_ClDummyColorBody : &g_Config.m_ClPlayerColorBody;
unsigned *pColorFeet = Dummy ? &g_Config.m_ClDummyColorFeet : &g_Config.m_ClPlayerColorFeet;
*pColorBody = Body.Pack(false);
*pColorFeet = Feet.Pack(false);
}
const size_t SkinNameSize = Dummy ? sizeof(g_Config.m_ClDummySkin) : sizeof(g_Config.m_ClPlayerSkin);
char aRandomSkinName[24];
str_copy(aRandomSkinName, "default", SkinNameSize);
if(!m_pClient->m_Skins.GetSkinsUnsafe().empty())
{
do
{
auto it = m_pClient->m_Skins.GetSkinsUnsafe().begin();
std::advance(it, rand() % m_pClient->m_Skins.GetSkinsUnsafe().size());
str_copy(aRandomSkinName, (*it).second->GetName(), SkinNameSize);
} while(!str_comp(aRandomSkinName, "x_ninja") || !str_comp(aRandomSkinName, "x_spec"));
}
char *pSkinName = Dummy ? g_Config.m_ClDummySkin : g_Config.m_ClPlayerSkin;
str_copy(pSkinName, aRandomSkinName, SkinNameSize);
}

View file

@ -66,6 +66,7 @@ public:
std::unordered_map<std::string_view, std::unique_ptr<CSkin>> &GetSkinsUnsafe() { return m_Skins; }
const CSkin *FindOrNullptr(const char *pName, bool IgnorePrefix = false);
const CSkin *Find(const char *pName);
void RandomizeSkin(int Dummy);
bool IsDownloadingSkins() { return m_DownloadingSkins; }

View file

@ -1565,7 +1565,7 @@ void CGameClient::OnNewSnapshot()
pClient->m_SkinInfo.m_ColorFeet = ColorRGBA(1, 1, 1);
}
pClient->UpdateRenderInfo(IsTeamPlay(), g_Config.m_ClDummy);
pClient->UpdateRenderInfo(IsTeamPlay());
}
}
else if(Item.m_Type == NETOBJTYPE_PLAYERINFO)
@ -2388,7 +2388,7 @@ void CGameClient::CClientStats::Reset()
m_FlagCaptures = 0;
}
void CGameClient::CClientData::UpdateRenderInfo(bool IsTeamPlay, int Conn)
void CGameClient::CClientData::UpdateRenderInfo(bool IsTeamPlay)
{
m_RenderInfo = m_SkinInfo;
@ -2403,6 +2403,7 @@ void CGameClient::CClientData::UpdateRenderInfo(bool IsTeamPlay, int Conn)
m_RenderInfo.m_ColorFeet = color_cast<ColorRGBA>(ColorHSLA(aTeamColors[m_Team]));
// 0.7
for(auto &Sixup : m_RenderInfo.m_aSixup)
{
const ColorRGBA aTeamColorsSixup[2] = {
ColorRGBA(0.753f, 0.318f, 0.318f, 1.0f),
@ -2410,19 +2411,20 @@ void CGameClient::CClientData::UpdateRenderInfo(bool IsTeamPlay, int Conn)
const ColorRGBA aMarkingColorsSixup[2] = {
ColorRGBA(0.824f, 0.345f, 0.345f, 1.0f),
ColorRGBA(0.345f, 0.514f, 0.824f, 1.0f)};
float MarkingAlpha = m_RenderInfo.m_aSixup[Conn].m_aColors[protocol7::SKINPART_MARKING].a;
for(auto &Color : m_RenderInfo.m_aSixup[Conn].m_aColors)
float MarkingAlpha = Sixup.m_aColors[protocol7::SKINPART_MARKING].a;
for(auto &Color : Sixup.m_aColors)
Color = aTeamColorsSixup[m_Team];
if(MarkingAlpha > 0.1f)
m_RenderInfo.m_aSixup[Conn].m_aColors[protocol7::SKINPART_MARKING] = aMarkingColorsSixup[m_Team];
Sixup.m_aColors[protocol7::SKINPART_MARKING] = aMarkingColorsSixup[m_Team];
}
}
else
{
m_RenderInfo.m_ColorBody = color_cast<ColorRGBA>(ColorHSLA(12829350));
m_RenderInfo.m_ColorFeet = color_cast<ColorRGBA>(ColorHSLA(12829350));
for(auto &Color : m_RenderInfo.m_aSixup[Conn].m_aColors)
Color = color_cast<ColorRGBA>(ColorHSLA(12829350));
for(auto &Sixup : m_RenderInfo.m_aSixup)
for(auto &Color : Sixup.m_aColors)
Color = color_cast<ColorRGBA>(ColorHSLA(12829350));
}
}
}
@ -3757,8 +3759,7 @@ void CGameClient::RefreshSkins()
Client.m_SkinInfo.m_OriginalRenderSkin.Reset();
Client.m_SkinInfo.m_ColorableRenderSkin.Reset();
}
for(int Dummy = 0; Dummy < NUM_DUMMIES; Dummy++)
Client.UpdateRenderInfo(IsTeamPlay(), Dummy);
Client.UpdateRenderInfo(IsTeamPlay());
}
for(auto &pComponent : m_vpAll)

View file

@ -438,7 +438,7 @@ public:
bool m_SpecCharPresent;
vec2 m_SpecChar;
void UpdateRenderInfo(bool IsTeamPlay, int Conn);
void UpdateRenderInfo(bool IsTeamPlay);
void Reset();
class CSixup

View file

@ -196,7 +196,7 @@ void *CGameClient::TranslateGameMsg(int *pMsgId, CUnpacker *pUnpacker, int Conn)
{
m_aClients[pMsg7->m_ClientId].m_Team = pMsg7->m_Team;
m_pClient->m_TranslationContext.m_aClients[pMsg7->m_ClientId].m_Team = pMsg7->m_Team;
m_aClients[pMsg7->m_ClientId].UpdateRenderInfo(IsTeamPlay(), Conn);
m_aClients[pMsg7->m_ClientId].UpdateRenderInfo(IsTeamPlay());
// if(pMsg7->m_ClientId == m_LocalClientId)
// {

View file

@ -328,8 +328,10 @@ public:
bool CanFillGameTiles() const;
void AddGroup();
void AddTileLayer();
void AddFrontLayer();
void LayerSelectImage();
bool IsNonGameTileLayerSelected() const;
void MapDetails();
#define REGISTER_QUICK_ACTION(name, text, callback, disabled, active, button_color, description) CQuickAction m_QuickAction##name;
#include <game/editor/quick_actions.h>
#undef REGISTER_QUICK_ACTION

View file

@ -32,7 +32,6 @@ CUi::EPopupMenuFunctionResult CEditor::PopupMenuFile(void *pContext, CUIRect Vie
static int s_OpenButton = 0;
static int s_OpenCurrentMapButton = 0;
static int s_AppendButton = 0;
static int s_MapInfoButton = 0;
static int s_ExitButton = 0;
CUIRect Slot;
@ -115,15 +114,9 @@ CUi::EPopupMenuFunctionResult CEditor::PopupMenuFile(void *pContext, CUIRect Vie
View.HSplitTop(10.0f, nullptr, &View);
View.HSplitTop(12.0f, &Slot, &View);
if(pEditor->DoButton_MenuItem(&s_MapInfoButton, "Map details", 0, &Slot, 0, "Adjust the map details of the current map"))
if(pEditor->DoButton_MenuItem(&pEditor->m_QuickActionMapDetails, pEditor->m_QuickActionMapDetails.Label(), 0, &Slot, 0, pEditor->m_QuickActionMapDetails.Description()))
{
const CUIRect *pScreen = pEditor->Ui()->Screen();
pEditor->m_Map.m_MapInfoTmp.Copy(pEditor->m_Map.m_MapInfo);
static SPopupMenuId s_PopupMapInfoId;
constexpr float PopupWidth = 400.0f;
constexpr float PopupHeight = 170.0f;
pEditor->Ui()->DoPopupMenu(&s_PopupMapInfoId, pScreen->w / 2.0f - PopupWidth / 2.0f, pScreen->h / 2.0f - PopupHeight / 2.0f, PopupWidth, PopupHeight, pEditor, PopupMapInfo);
pEditor->Ui()->SetActiveItem(nullptr);
pEditor->m_QuickActionMapDetails.Call();
return CUi::POPUP_CLOSE_CURRENT;
}
@ -543,16 +536,9 @@ CUi::EPopupMenuFunctionResult CEditor::PopupGroup(void *pContext, CUIRect View,
// new front layer
View.HSplitBottom(5.0f, &View, nullptr);
View.HSplitBottom(12.0f, &View, &Button);
static int s_NewFrontLayerButton = 0;
if(pEditor->DoButton_Editor(&s_NewFrontLayerButton, "Add front layer", 0, &Button, 0, "Creates a new item layer"))
if(pEditor->DoButton_Editor(&pEditor->m_QuickActionAddFrontLayer, pEditor->m_QuickActionAddFrontLayer.Label(), 0, &Button, 0, pEditor->m_QuickActionAddFrontLayer.Description()))
{
std::shared_ptr<CLayer> pFrontLayer = std::make_shared<CLayerFront>(pEditor, pEditor->m_Map.m_pGameLayer->m_Width, pEditor->m_Map.m_pGameLayer->m_Height);
pEditor->m_Map.MakeFrontLayer(pFrontLayer);
pEditor->m_Map.m_vpGroups[pEditor->m_SelectedGroup]->AddLayer(pFrontLayer);
int LayerIndex = pEditor->m_Map.m_vpGroups[pEditor->m_SelectedGroup]->m_vpLayers.size() - 1;
pEditor->SelectLayer(LayerIndex);
pEditor->m_pBrush->Clear();
pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionAddLayer>(pEditor, pEditor->m_SelectedGroup, LayerIndex));
pEditor->m_QuickActionAddFrontLayer.Call();
return CUi::POPUP_CLOSE_CURRENT;
}
}

View file

@ -37,6 +37,17 @@ void CEditor::AddTileLayer()
m_EditorHistory.RecordAction(std::make_shared<CEditorActionAddLayer>(this, m_SelectedGroup, LayerIndex));
}
void CEditor::AddFrontLayer()
{
std::shared_ptr<CLayer> pFrontLayer = std::make_shared<CLayerFront>(this, m_Map.m_pGameLayer->m_Width, m_Map.m_pGameLayer->m_Height);
m_Map.MakeFrontLayer(pFrontLayer);
m_Map.m_vpGroups[m_SelectedGroup]->AddLayer(pFrontLayer);
int LayerIndex = m_Map.m_vpGroups[m_SelectedGroup]->m_vpLayers.size() - 1;
SelectLayer(LayerIndex);
m_pBrush->Clear();
m_EditorHistory.RecordAction(std::make_shared<CEditorActionAddLayer>(this, m_SelectedGroup, LayerIndex));
}
bool CEditor::IsNonGameTileLayerSelected() const
{
std::shared_ptr<CLayer> pLayer = GetSelectedLayer(0);
@ -69,3 +80,21 @@ void CEditor::LayerSelectImage()
Ui()->DoPopupMenu(&s_LayerPopupContext, Ui()->MouseX(), Ui()->MouseY(), 120, 270, &s_LayerPopupContext, PopupLayer);
PopupSelectImageInvoke(pTiles->m_Image, Ui()->MouseX(), Ui()->MouseY());
}
void CEditor::MapDetails()
{
const CUIRect *pScreen = Ui()->Screen();
m_Map.m_MapInfoTmp.Copy(m_Map.m_MapInfo);
static SPopupMenuId s_PopupMapInfoId;
constexpr float PopupWidth = 400.0f;
constexpr float PopupHeight = 170.0f;
Ui()->DoPopupMenu(
&s_PopupMapInfoId,
pScreen->w / 2.0f - PopupWidth / 2.0f,
pScreen->h / 2.0f - PopupHeight / 2.0f,
PopupWidth,
PopupHeight,
this,
PopupMapInfo);
Ui()->SetActiveItem(nullptr);
}

View file

@ -169,6 +169,14 @@ REGISTER_QUICK_ACTION(
"Toggles proof borders. These borders represent the area that a player can see with default zoom.")
REGISTER_QUICK_ACTION(
AddTileLayer, "Add tile layer", [&]() { AddTileLayer(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "Creates a new tile layer.")
REGISTER_QUICK_ACTION(
AddFrontLayer,
"Add front layer",
[&]() { AddFrontLayer(); },
[&]() -> bool { return !GetSelectedGroup()->m_GameGroup || m_Map.m_pFrontLayer; },
ALWAYS_FALSE,
DEFAULT_BTN,
"Creates a new item layer.")
REGISTER_QUICK_ACTION(
SaveAs,
"Save As",
@ -276,6 +284,14 @@ REGISTER_QUICK_ACTION(
[&]() -> bool { return m_ColorPipetteActive; },
DEFAULT_BTN,
"[Ctrl+Shift+C] Color pipette. Pick a color from the screen by clicking on it.")
REGISTER_QUICK_ACTION(
MapDetails,
"Map details",
[&]() { MapDetails(); },
ALWAYS_FALSE,
ALWAYS_FALSE,
DEFAULT_BTN,
"Adjust the map details of the current map.")
#undef ALWAYS_FALSE
#undef DEFAULT_BTN

View file

@ -893,6 +893,12 @@ void CGameContext::ConReloadCensorlist(IConsole::IResult *pResult, void *pUserDa
pSelf->ReadCensorList();
}
void CGameContext::ConReloadAnnouncement(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
pSelf->Server()->ReadAnnouncementsFile(g_Config.m_SvAnnouncementFileName);
}
void CGameContext::ConDumpAntibot(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;

View file

@ -1253,7 +1253,7 @@ void CGameContext::OnTick()
if(Server()->Tick() % (g_Config.m_SvAnnouncementInterval * Server()->TickSpeed() * 60) == 0)
{
const char *pLine = Server()->GetAnnouncementLine(g_Config.m_SvAnnouncementFileName);
const char *pLine = Server()->GetAnnouncementLine();
if(pLine)
SendChat(-1, TEAM_ALL, pLine);
}
@ -3643,6 +3643,7 @@ void CGameContext::OnConsoleInit()
Console()->Register("set_team_all", "i[team-id]", CFGFLAG_SERVER, ConSetTeamAll, this, "Set team of all players to team");
Console()->Register("hot_reload", "", CFGFLAG_SERVER | CMDFLAG_TEST, ConHotReload, this, "Reload the map while preserving the state of tees and teams");
Console()->Register("reload_censorlist", "", CFGFLAG_SERVER, ConReloadCensorlist, this, "Reload the censorlist");
Console()->Register("reload_announcement", "", CFGFLAG_SERVER, ConReloadAnnouncement, this, "Reload the announcements");
Console()->Register("add_vote", "s[name] r[command]", CFGFLAG_SERVER, ConAddVote, this, "Add a voting option");
Console()->Register("remove_vote", "r[name]", CFGFLAG_SERVER, ConRemoveVote, this, "remove a voting option");

View file

@ -516,6 +516,7 @@ private:
static void ConUnFreezeHammer(IConsole::IResult *pResult, void *pUserData);
static void ConReloadCensorlist(IConsole::IResult *pResult, void *pUserData);
static void ConReloadAnnouncement(IConsole::IResult *pResult, void *pUserData);
CCharacter *GetPracticeCharacter(IConsole::IResult *pResult);