[РЕШЕНО] Получение необходимого текста перевода

Vit_ amin

Добрая душа
Сообщения
1,525
Реакции
688
Всем доброго времени суток. Встал в тупик при написании плагин.
Вообщем суть.
Имеются игровые BSP карты формата:

PHP:
cNmN_*

где N - цифры/числа

В maplist.txt данный список у меня всегда начинается по следующему формату:

PHP:
cNm1_*

где * - название уровня

Мне необходимо, чтобы плагин отрывал из названия карты всё, кроме cN и искал уже это через StrContains с maplist.txt

То есть (пример):

maplist.txt
C-подобный:
c1m1_map1
c6m1_map2
c2m1_map4
c3m1_map3
cXmY_mapZ

Например, я играю на карте c1m3_map3 - необходимо удалить все, кроме c1, и сравнить это с maplist.txt

Я всё написал кроме того, как удалить эту часть и оставить cN - я же не знаю какая цифра будет там и так далее.

Если объяснил не совсем правильно, могу перефразировать попробовать :D

Код (отсутствует проверка, о которой писал выше, так как не знаю, как её сделать, можете через Регулярные выражения !?):
PHP:
for (;;)
    {
        if (hMapList.ReadLine(szBuffer, sizeof(szBuffer)))
        {
            ReplaceString(szBuffer, sizeof(szBuffer), "\n", "");
         
            if (bMapFound)
            {
                strcopy(g_szMapName, sizeof(g_szMapName), szBuffer);
                bMapFound = false;
                break;
            }
         
            if (strcmp(g_szMapName, szBuffer, false) == 0)
            {
                bMapFound = true;
            }
        }
        else
        {
            hMapList.Seek(0, SEEK_SET);
            continue;
        }
    }

    if (SplitString(g_szMapName, "m1_", szBuffer, sizeof(szBuffer)) != -1)
    {
        ReplaceString(szBuffer, sizeof(szBuffer), "c", "C");
     
        char szAnnounce[192];
     
        Format(szBuffer, sizeof(szBuffer), "CampaignName_%s", szBuffer);
     
        FormatEx(szAnnounce, sizeof(szAnnounce), "%s%t \x05%t\x01.", MESSAGE_PREFIX, "ChangeMission", szBuffer);
        PrintToChatAll("%s", szAnnounce);
    }
    else
    {
        SetFailState("Error detection next campaign level ...");
    }
 
    delete hMapList;
Сообщения автоматически склеены:
 
Последнее редактирование:

Grey83

не пишу плагины с весны 2022
Сообщения
8,569
Реакции
5,071
если у вас проблема и вы решили её решить с помощью регулярных выражений, то у Вас уже 2 проблемы (с) не помню кто
Сообщения автоматически склеены:

В общемвсё делается гораздо проще: получаешь название текущей карты, сравниваешь 1-й и 3-й символ с эталоном (символы «c» и «m», если конечно есть карты с другим началом), потом запоминаешь 2-й символ и сравниваешь его потом с 2-м символом имени карты в маплисте
т.е. StrContains не нужен, как и RegEx
Сообщения автоматически склеены:

кстати, судя по префиксам карт и слову «компания» у тебя L4D или L4D2, правильно?
 
Последнее редактирование:

Vit_ amin

Добрая душа
Сообщения
1,525
Реакции
688
А как нужно делать, сравнивать в цикле каждый символ?
Сообщения автоматически склеены:

Да, игра, игра Left 4 dead 2
Сообщения автоматически склеены:

Проблема в том, что на второй позиции может быть либо цифра, либо число, то есть
c1m1; c99m1
 
Последнее редактирование:

DarklSide

Участник
Сообщения
931
Реакции
468
@Vit_ amin,
C-подобный:
#include <regex>

Regex CompanyMap;

public void OnPluginStart()
{
   // Захватываем группу (cN), чтобы начиналось с "c", затем несколько цифр "\\d+", и после "m", но не захватывая его: "(?=m)".
   CompanyMap = CompileRegex("\\b(c\\d+)(?=m)", PCRE_CASELESS | PCRE_UTF8); // UTF8 для карт может быть и не нужен (Grey83)
   if (CompanyMap == null)
   {
       LogError("Error compile");
   }
}

public void OnMapStart()
{
   // Получаем текушую карту
   char currentMap[PLATFORM_MAX_PATH];
   GetCurrentMap(currentMap, sizeof(currentMap));

   // Проверяем "Match", если ли в названии карты, то что нужно.
   // Берем "GetSubString" в [currentMap], только захваченную группу (cN) - основной индекс этой группы "1"
   if (CompanyMap.Match(currentMap) > 0 && CompanyMap.GetSubString(1, currentMap, sizeof(currentMap)))
   {
       PrintToServer("Found (cN): [%s]", currentMap);
       MapList("company map", currentMap);
   }
}

// addons/sourcemod/configs/maplists.cfg
/*
    // Company maps
    "company map"
    {
        "file"            "addons/sourcemod/configs/company_maplist.ini"
    }
*/

// addons/sourcemod/configs/company_maplist.ini
/*
    c1m1_hotel
    c6m1_riverbank
    c2m1_highway
    c3m1_plankcountry
    cXmY_mapZ
*/
void MapList(char[] configName, char[] partMap) // (cN)
{
   Handle mapArray;

   // Читаем карты из конфига [configName] в массив
   if ((mapArray = ReadMapList(_, _, configName, MAPLIST_FLAG_NO_DEFAULT)) != null)
   {
       // Если нужно найти только карту, добавляем после (cN) следующий символ карты "m"
       // иначе найдет все вхождения
       // Format(partMap, sizeof(partMap), "%sm", partMap);

       // Получаем размер массива
       int mapCount = GetArraySize(mapArray);
       char mapName[PLATFORM_MAX_PATH];
       for (int i = 0; i < mapCount; i++)
       {
           // Получаем строку по индексу
           GetArrayString(mapArray, i, mapName, sizeof(mapName));
           // Находим все вхождения (cN) [partMap], из конфига
           if (StrContains(mapName, partMap, false) != -1)
           {
               PrintToServer("Found map: [%s]", mapName);
               // break;
           }
       }
   }

   delete mapArray;
}
 
Последнее редактирование:

Grey83

не пишу плагины с весны 2022
Сообщения
8,569
Реакции
5,071
Проблема в том, что на второй позиции может быть либо цифра, либо число, то есть
c1m1; c99m1
Не сильно это и проблема: если 3-й символ - цифра, то запоминаем и третий символ
В общем: сохраняем цифры, пока не встретим символ 'm'

Как приду с работы сегодня, попробую код набросать, если не забуду

DarklSide, тут RegEx избыточен, да и UTF-8 для него не нужен: сомневаюсь, что можно использовать что-то отличное от латиницы в имени карты
 

Vit_ amin

Добрая душа
Сообщения
1,525
Реакции
688
@Vit_ amin,
C-подобный:
#include <regex>

Regex CompanyMap;

public void OnPluginStart()
{
   CompanyMap = CompileRegex("(c\\d+)(?=m)", PCRE_CASELESS | PCRE_UTF8);
   if (CompanyMap == null)
   {
       LogError("Error compile");
   }
}

public void OnMapStart()
{
   char currentMap[PLATFORM_MAX_PATH];
   GetCurrentMap(currentMap, sizeof(currentMap));
   if (CompanyMap.Match(currentMap) > 0 && CompanyMap.GetSubString(1, currentMap, sizeof(currentMap)))
   {
       PrintToServer("Found cN: [%s]", currentMap);
       MapList("company map", currentMap);
   }
}

// addons/sourcemod/configs/maplists.cfg
/*
    // Company maps
    "company map"
    {
        "file"            "addons/sourcemod/configs/company_maplist.ini"
    }
*/

// addons/sourcemod/configs/company_maplist.ini
/*
    c1m1_hotel
    c6m1_riverbank
    c2m1_highway
    c3m1_plankcountry
    cXmY_mapZ
*/
void MapList(char[] configName, char[] partMap) // cN
{   
   Handle mapArray;
  
   if ((mapArray = ReadMapList(_, _, configName, MAPLIST_FLAG_NO_DEFAULT | MAPLIST_FLAG_CLEARARRAY)) != null)
   {
       char mapName[PLATFORM_MAX_PATH];
       int mapCount = GetArraySize(mapArray);
      
       // char cNm_onlyOneMap[PLATFORM_MAX_PATH];
       // Format(cNm_onlyOneMap, sizeof(cNm_onlyOneMap), "%sm", partMap);
      
       for (int i = 0; i < mapCount; i++)
       {
           GetArrayString(mapArray, i, mapName, sizeof(mapName));
           // if (StrContains(mapName, cNm_onlyOneMap, false) != -1)
           if (StrContains(mapName, partMap, false) != -1)
           {
               PrintToServer("Found map: [%s]", mapName);
               // break;
           }
       }
   }
  
   delete mapArray;
}
C-подобный:
Found map: [c1m1_hotel]
Found map: [c13m1_alpinecreek]
Found map: [c10m1_caves]
Found map: [c11m1_greenhouse]
Found map: [c12m1_hilltop]
Но по идеи должно высветиться только c1m1_hotel ? Я просто в регулярных выражениях не очень силён
 

Grey83

не пишу плагины с весны 2022
Сообщения
8,569
Реакции
5,071
Vit_ amin, d+ означает, что будет отлавливаться от 1 до N цифр в строке
 

DarklSide

Участник
Сообщения
931
Реакции
468

DarklSide

Участник
Сообщения
931
Реакции
468
\b
CompileRegex("\b(c\\d+)(?=m)"
->
\\b
CompileRegex("\\b(c\\d+)(?=m)"
 

Vit_ amin

Добрая душа
Сообщения
1,525
Реакции
688
И да, я немножко не правильное сделал уточнение.
Получается: например я играю на карте c1m4_*
Есть событие, при котором мне необходимо залезть в maplist.txt и оттуда взять следующую карту (название и её префикс cN):
То есть:
C-подобный:
c1m1_hotel
c6m1_revierbank
Я играю на c1m4_*
Есть событие HookEvent("finale_win", ...);

И там мне необходимо относительно прифекса cN - в моём случае это - c1
Взять следующую карту на уровень ниже - то есть c6m1_riverbank - и еще необходимо для файла перевода взять префикс c6, так как у меня в переводе все буквы c - прописные, то я это делал простой заменой с малой на заглавную ReplaceString - или как то еще лучше можно сделать ? Через IsCharLower ?
Сообщения автоматически склеены:

C-подобный:
Found cN: [c1]
Found map: [c1m1_hotel]
Found map: [c13m1_alpinecreek]
Found map: [c10m1_caves]
Found map: [c11m1_greenhouse]
Found map: [c12m1_hilltop]
 

DarklSide

Участник
Сообщения
931
Реакции
468
C-подобный:
Found cN: [c1]
Found map: [c1m1_hotel]
Found map: [c13m1_alpinecreek]
Found map: [c10m1_caves]
Found map: [c11m1_greenhouse]
Found map: [c12m1_hilltop]

раскомментировать :
// Если нужно найти только карту, добавляем после (cN) следующий символ карты "m"
// иначе найдет все вхождения
Format(partMap, sizeof(partMap), "%sm", partMap);
Сообщения автоматически склеены:

Я играю на c1m4_*
Есть событие HookEvent("finale_win", ...);

И там мне необходимо относительно прифекса cN - в моём случае это - c1
Взять следующую карту на уровень ниже - то есть c6m1_riverbank - и еще необходимо для файла перевода взять префикс c6, так как у меня в переводе все буквы c - прописные, то я это делал простой заменой с малой на заглавную ReplaceString - или как то еще лучше можно сделать ? Через IsCharLower ?

По быстрому:

C-подобный:
#include <regex>

Regex CompanyMap;
#define MESSAGE_PREFIX "[NextCompany] "

public void OnPluginStart()
{
   //LoadTranslations("");
 
   // Захватываем группу (cN), чтобы начиналось с "c", затем несколько цифр "\\d+", и после "m", но не захватывая его: "(?=m)".
   CompanyMap = CompileRegex("\\b(c\\d+)(?=m)", PCRE_CASELESS | PCRE_UTF8); // UTF8 для карт может быть и не нужен (Grey83)
   if (CompanyMap == null)
   {
       SetFailState("Error compile Regex");
   }
 
   HookEvent("finale_win", finale_win, EventHookMode_Post);
   RegConsoleCmd("sm_getnextcompany", sm_getnextcompany, "[currentMap]");
}

public Action sm_getnextcompany(int client, int args)
{
   char sArg_CurrentMap[64];
 
   int iArg_CurrentMap = 1;
   if (!GetCmdArg(iArg_CurrentMap, sArg_CurrentMap, sizeof(sArg_CurrentMap)))
   {
       GetCurrentMap(sArg_CurrentMap, sizeof(sArg_CurrentMap));
   }
 
   NextCompany(sArg_CurrentMap, sizeof(sArg_CurrentMap));
 
   return Plugin_Handled;
}

public void finale_win(Event event, const char[] name, bool dontBroadcast)
{
   // Получаем текушую карту
   char currentMap[PLATFORM_MAX_PATH];
   GetCurrentMap(currentMap, sizeof(currentMap));
 
   NextCompany(currentMap, sizeof(currentMap));
}

public void NextCompany(char[] currentMap, int maxlen_currentMap)
{
   // Проверяем "Match", если ли в названии карты, то что нужно.
   // Берем "GetSubString" в [currentMap], только захваченную группу (cN) - основной индекс этой группы "1"
   if (CompanyMap.Match(currentMap) > 0 && CompanyMap.GetSubString(1, currentMap, maxlen_currentMap))
   {
       PrintToServer("Found (cN): [%s]", currentMap);
     
       char nextMap[PLATFORM_MAX_PATH];
       NextMap("company map", currentMap, maxlen_currentMap, nextMap, sizeof(nextMap));
       if (nextMap[0] != 0)
       {
           PrintToServer("Found nextmap: [%s]", nextMap);
         
           char szBuffer[PLATFORM_MAX_PATH]
           if (SplitString(nextMap, "m1_", szBuffer, sizeof(szBuffer)) != -1)
           {
               szBuffer[0] = CharToUpper(szBuffer[0]); //ReplaceString(szBuffer, sizeof(szBuffer), "c", "C");
               Format(szBuffer, sizeof(szBuffer), "CampaignName_%s", szBuffer);
             
               PrintToChatAll("%s%t \x05%t\x01.", MESSAGE_PREFIX, "ChangeMission", szBuffer);
             
               PrintToServer("%s%t %t.", MESSAGE_PREFIX, "ChangeMission", szBuffer);
           }
           else
           {
               SetFailState("Error detection next campaign level ...");
           }
       }
       else
       {
           SetFailState("Error detection find next campaign level ...");
       }
   }
}

// addons/sourcemod/configs/maplists.cfg
/*
    // Company maps
    "company map"
    {
        "file"            "addons/sourcemod/configs/company_maplist.ini"
    }
*/

// addons/sourcemod/configs/company_maplist.ini
/*
    c1m1_hotel
    c6m1_riverbank
    c2m1_highway
    c3m1_plankcountry
    cXmY_mapZ
*/
void NextMap(char[] configName, char[] partMap, int maxlen_partMap, char[] nextMap, int maxlen_nextMap) // (cN)
{
   Handle mapArray;
 
   // Читаем карты из конфига [configName] в массив
   if ((mapArray = ReadMapList(_, _, configName, MAPLIST_FLAG_NO_DEFAULT | MAPLIST_FLAG_CLEARARRAY)) != null)
   {
       // Если нужно найти только карту, добавляем после (cN) следующий символ карты "m"
       // иначе найдет все вхождения
       Format(partMap, maxlen_partMap, "%sm", partMap);
     
       // Получаем размер массива
       int mapCount = GetArraySize(mapArray);
       char mapName[PLATFORM_MAX_PATH];
       for (int i = 0; i < mapCount; i++)
       {
           // Получаем строку по индексу
           GetArrayString(mapArray, i, mapName, sizeof(mapName));
           // Находим все вхождения (cN) [partMap], из конфига
           if (StrContains(mapName, partMap, false) != -1)
           {
               PrintToServer("Found map: [%s]", mapName);
               if (i == mapCount - 1)
               {
                   i = 0;
               }
               else
               {
                   i++;
               }
               GetArrayString(mapArray, i, mapName, sizeof(mapName));
               strcopy(nextMap, maxlen_nextMap, mapName);
               break;
           }
       }
   }
 
   delete mapArray;
}

Проверить можно командой:
для текущей карты:
sm_getnextcompany
или неужной:
sm_getnextcompany c3m1_plankcountry

P.S.: не забыть загрузить нужные переводы: LoadTranslations
 
Последнее редактирование:

Vit_ amin

Добрая душа
Сообщения
1,525
Реакции
688
C-подобный:
Found cN: [c1]
Found map: [c1m1_hotel]
Found map: [c13m1_alpinecreek]
Found map: [c10m1_caves]
Found map: [c11m1_greenhouse]
Found map: [c12m1_hilltop]

раскомментировать :
// Если нужно найти только карту, добавляем после (cN) следующий символ карты "m"
// иначе найдет все вхождения
Format(partMap, sizeof(partMap), "%sm", partMap);
Сообщения автоматически склеены:



По быстрому:

C-подобный:
#include <regex>

Regex CompanyMap;
#define MESSAGE_PREFIX "[NextCompany] "

public void OnPluginStart()
{
   //LoadTranslations("");

   // Захватываем группу (cN), чтобы начиналось с "c", затем несколько цифр "\\d+", и после "m", но не захватывая его: "(?=m)".
   CompanyMap = CompileRegex("\\b(c\\d+)(?=m)", PCRE_CASELESS | PCRE_UTF8); // UTF8 для карт может быть и не нужен (Grey83)
   if (CompanyMap == null)
   {
       SetFailState("Error compile Regex");
   }

   HookEvent("finale_win", finale_win, EventHookMode_Post);
   RegConsoleCmd("sm_getnextcompany", sm_getnextcompany, "[currentMap]");
}

public Action sm_getnextcompany(int client, int args)
{
   char sArg_CurrentMap[64];

   int iArg_CurrentMap = 1;
   if (!GetCmdArg(iArg_CurrentMap, sArg_CurrentMap, sizeof(sArg_CurrentMap)))
   {
       GetCurrentMap(sArg_CurrentMap, sizeof(sArg_CurrentMap));
   }

   NextCompany(sArg_CurrentMap, sizeof(sArg_CurrentMap));

   return Plugin_Handled;
}

public void finale_win(Event event, const char[] name, bool dontBroadcast)
{
   // Получаем текушую карту
   char currentMap[PLATFORM_MAX_PATH];
   GetCurrentMap(currentMap, sizeof(currentMap));

   NextCompany(currentMap, sizeof(currentMap));
}

public void NextCompany(char[] currentMap, int maxlen_currentMap)
{
   // Проверяем "Match", если ли в названии карты, то что нужно.
   // Берем "GetSubString" в [currentMap], только захваченную группу (cN) - основной индекс этой группы "1"
   if (CompanyMap.Match(currentMap) > 0 && CompanyMap.GetSubString(1, currentMap, maxlen_currentMap))
   {
       PrintToServer("Found (cN): [%s]", currentMap);
    
       char nextMap[PLATFORM_MAX_PATH];
       NextMap("company map", currentMap, maxlen_currentMap, nextMap, sizeof(nextMap));
       if (nextMap[0] != 0)
       {
           PrintToServer("Found nextmap: [%s]", nextMap);
        
           char szBuffer[PLATFORM_MAX_PATH]
           if (SplitString(nextMap, "m1_", szBuffer, sizeof(szBuffer)) != -1)
           {
               szBuffer[0] = CharToUpper(szBuffer[0]); //ReplaceString(szBuffer, sizeof(szBuffer), "c", "C");
               Format(szBuffer, sizeof(szBuffer), "CampaignName_%s", szBuffer);
            
               PrintToChatAll("%s%t \x05%t\x01.", MESSAGE_PREFIX, "ChangeMission", szBuffer);
            
               PrintToServer("%s%t %t.", MESSAGE_PREFIX, "ChangeMission", szBuffer);
           }
           else
           {
               SetFailState("Error detection next campaign level ...");
           }
       }
       else
       {
           SetFailState("Error detection find next campaign level ...");
       }
   }
}

// addons/sourcemod/configs/maplists.cfg
/*
    // Company maps
    "company map"
    {
        "file"            "addons/sourcemod/configs/company_maplist.ini"
    }
*/

// addons/sourcemod/configs/company_maplist.ini
/*
    c1m1_hotel
    c6m1_riverbank
    c2m1_highway
    c3m1_plankcountry
    cXmY_mapZ
*/
void NextMap(char[] configName, char[] partMap, int maxlen_partMap, char[] nextMap, int maxlen_nextMap) // (cN)
{
   Handle mapArray;

   // Читаем карты из конфига [configName] в массив
   if ((mapArray = ReadMapList(_, _, configName, MAPLIST_FLAG_NO_DEFAULT | MAPLIST_FLAG_CLEARARRAY)) != null)
   {
       // Если нужно найти только карту, добавляем после (cN) следующий символ карты "m"
       // иначе найдет все вхождения
       Format(partMap, maxlen_partMap, "%sm", partMap);
    
       // Получаем размер массива
       int mapCount = GetArraySize(mapArray);
       char mapName[PLATFORM_MAX_PATH];
       for (int i = 0; i < mapCount; i++)
       {
           // Получаем строку по индексу
           GetArrayString(mapArray, i, mapName, sizeof(mapName));
           // Находим все вхождения (cN) [partMap], из конфига
           if (StrContains(mapName, partMap, false) != -1)
           {
               PrintToServer("Found map: [%s]", mapName);
               if (i == mapCount - 1)
               {
                   i = 0;
               }
               else
               {
                   i++;
               }
               GetArrayString(mapArray, i, mapName, sizeof(mapName));
               strcopy(nextMap, maxlen_nextMap, mapName);
               break;
           }
       }
   }

   delete mapArray;
}

Проверить можно командой:
для текущей карты:
sm_getnextcompany
или неужной:
sm_getnextcompany c3m1_plankcountry

P.S.: не забыть загрузить нужные переводы: LoadTranslations
Работает, спасибо большое, что всё подробно прокомментировал в коде
 
Сверху Снизу