-
Posts
656 -
Joined
-
Last visited
-
Days Won
187 -
Feedback
100%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by VegaS™
-
-
36 minutes ago, Braxy said:
- If you do this, each time the players enter the game (either is teleport or whatever) he has to chose the language for the quest.
If I am not mistaken, he said "language quest" which for him mean "The Programming Language Lua", not "
choselanguage for quest", so your post-explanation have no sense in this case.QuoteI'm working on language quest today and I got a problem never seen before.
As @Syreldar said, you can't do it with the default structure of ymir-gay, already i tried long time ago to debug it and fix it with many attempts, but no succes (at that time), i'll take a look again when i'll have time.
- 2
-
15 minutes ago, ridetpro said:
The post is from 4 years ago, i changed my mega-account, here's the re-upload.
- Password Archive: property_vegas_work
- 28
- 1
- 1
- 4
- 8
-
Try this. (not-tested!)
- ..Src/Server/common/service.h
#define ENABLE_OXEVENT_STATIC_QUIZ
- ..Src/Server/game/src/OxEvent.cpp
#ifdef ENABLE_OXEVENT_STATIC_QUIZ bool COXEventManager::Quiz(unsigned char level, int timelimit) { SendNoticeMap(LC_TEXT("문제 입니다."), OXEVENT_MAP_INDEX, true); SendNoticeMap("True or false?", OXEVENT_MAP_INDEX, true); SendNoticeMap(LC_TEXT("맞으면 O, 틀리면 X로 이동해주세요"), OXEVENT_MAP_INDEX, true); if (m_timedEvent) event_cancel(&m_timedEvent); OXEventInfoData * pkEventInfo = AllocEventInfo<OXEventInfoData>(); pkEventInfo->answer = static_cast<bool>(number(0, 1)); m_timedEvent = event_create(oxevent_timer, pkEventInfo, PASSES_PER_SEC(MINMAX(15, timelimit - 15, 60))); SetStatus(OXEVENT_QUIZ); return true; } #else bool COXEventManager::Quiz(unsigned char level, int timelimit) { if (m_vec_quiz.size() == 0) return false; if (level > m_vec_quiz.size()) level = m_vec_quiz.size() - 1; if (m_vec_quiz[level].size() <= 0) return false; if (timelimit < 0) timelimit = 30; int idx = number(0, m_vec_quiz[level].size()-1); SendNoticeMap(LC_TEXT("문제 입니다."), OXEVENT_MAP_INDEX, true); SendNoticeMap(m_vec_quiz[level][idx].Quiz, OXEVENT_MAP_INDEX, true); SendNoticeMap(LC_TEXT("맞으면 O, 틀리면 X로 이동해주세요"), OXEVENT_MAP_INDEX, true); if (m_timedEvent != NULL) { event_cancel(&m_timedEvent); } OXEventInfoData* answer = AllocEventInfo<OXEventInfoData>(); answer->answer = m_vec_quiz[level][idx].answer; timelimit -= 15; m_timedEvent = event_create(oxevent_timer, answer, PASSES_PER_SEC(timelimit)); SetStatus(OXEVENT_QUIZ); m_vec_quiz[level].erase(m_vec_quiz[level].begin()+idx); return true; } #endif
- 1
-
You should change the structure, from reading the name of item to vnum directly.
-
I don't understand why u guys, use search string name same as the return one for non-sense...
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("INFO_DESTROY_ITEM"), item->GetName()); ChatPacket(CHAT_TYPE_INFO, LC_TEXT("INFO_DESTROY_ITEM_WARNING"), item->GetName());
- ../share/locale/germany/locale_string.txt
"INFO_DESTROY_ITEM"; "[Info] Ai distrus %s."; "INFO_DESTROY_ITEM_WARNING"; "|cff8ddcab[Info]|r |cffffffffItem-ul|r |cFFFFC700%s|r |cffffffffnu se mai poate recupera.|r";
- 3
-
Add some conditions in your function like this:
if (race > 0 && race <= 2499) // vec_stPathes.push_back ("d:/ymir work/monster/"); else if (race >= 2500 && race <= 8999) // vec_stPathes.push_back ("d:/ymir work/monster2/"); else { [....] }
-
If you want to compare the guild of 2 players and see if they're in the same guild you should do a global function for LUA, which can be used everywhere.
- Src/Server/game/src/questlua_global.cpp
Spoiler// Search for: ALUA(_get_locale) { lua_pushstring(L, g_stLocale.c_str()); return 1; } // Add after: ALUA(_is_same_guild) { if (!lua_isstring(L, 1) || !lua_isstring(L, 2)) { sys_err("invalid argument"); lua_pushboolean(L, 0); return 1; } // Get name of players (arg1, arg2). const std::string c_rstrName = lua_tostring(L, 1); const std::string c_rstrTargetName = lua_tostring(L, 2); // Get character pointer by name. const LPCHARACTER pkChr = CHARACTER_MANAGER::instance().FindPC(c_rstrName.c_str()); const LPCHARACTER pkChrTarget = CHARACTER_MANAGER::instance().FindPC(c_rstrTargetName.c_str()); // Check if players are in a guild and if they're same. if ((pkChr && pkChrTarget) && (pkChr->GetGuild() && pkChrTarget->GetGuild())) { lua_pushboolean(L, pkChr->GetGuild() == pkChrTarget->GetGuild()); } else { lua_pushboolean(L, 0); } return 1; } // Search for: { "get_locale", _get_locale }, // Add after: { "is_same_guild", _is_same_guild },
- share/locale/germany/quest_function
Spoileris_same_guild
- quest_example.lua
Spoilerlocal name = pc.get_name() local target_name = "UnknownName" if (is_same_guild(name, target_name)) then -- They're in the same guild. else -- They aren't in the same guild. end
- 2
-
-
You use a dictionary since you don't save anything, in this case you should use a list.
#WARNING_WHISPER_GM = {} WARNING_WHISPER_GM = [] #constInfo.WARNING_WHISPER_GM.update({targetName : {}}) constInfo.WARNING_WHISPER_GM.append(targetName)
- 1
-
The idea isn't bad (even if we're in 2019 and can be bypassed very easy and have no effects this), but there's some things which can be written in C++11 and a better structure, since your map have empty list initialization (since C++11).
Here's some advices which can help you in future, maybe.
- Your map have as value type a another std::map, for what? Since you store in key and value the same thing (player id), you should use std::list / std::vector or anything you want, but not a another std::map for no-reason if your key is same as value and no possible changes.
- You insert all time for each login in a x map the player id, you don't check if already exist and then insert it (you could use std::find/std::map::find), you use make_pair for map and that means the key can't be duplicated, but this isn't a good practice to trying to insert 1000 times and nothing happen.
- You check if map size is smaller or equal than 0, how can be a map size < 0?
-
You declared a another map for iterating in a for-loop, you don't need to do that.
std::map<DWORD, DWORD> map_players = [....]; - You use map.at(...), if you use this you should use the std::out_of_range too, otherwise have no sense, because you already did a check before if exist mapIndex by map.count(index), so you can use directly operator std::map::operator[] instead of std::map::at.
- You declared a std::string with no-reason for GetHostName() -> return a const char *, which you can use strcmp(str1, str2) instead of string.compare(str2).
- Your key of map should be as constant, because you don't want to change it.
- You should use also #pragma once for your header file (including: less code, avoidance of name clashes, and sometimes improvement in compilation speed.)
- You should remove the pid of player after disconnect of the map, have no sense to remain.
PS: If i were in your place, i didn't do the structure like this, it's a bit messed up.
Here's some of things what i said. (didn't tested)
- map_manager.h
Spoiler#pragma once class MapManager: public singleton<MapManager> { private: std::map<const DWORD, std::list<const DWORD>> m_map_manager = { { 181, {} }, { 182, {} }, { 183, {} } }; public: const bool Initialize(); void Clear(); void Destroy(); void Enter(const LPCHARACTER ch); void Disconnect(const LPCHARACTER ch); const size_t GetIPMapCount(const DWORD dwMapIndex); const bool IsPlayerIPInMap(const LPCHARACTER ch); const bool IsUniqueIPMap(const DWORD dwMapIndex); };
- map_manager.cpp
Spoiler#include "stdafx.h" #include "buffer_manager.h" #include "char.h" #include "char_manager.h" #include "map_manager.h" #include "desc.h" void MapManager::Initialize() { Clear(); } void MapManager::Destroy() { Clear(); } // Removes all elements from the map container (which are destroyed), leaving the container with a size of 0. void MapManager::Clear() { for (auto iter = m_map_manager.begin(); iter != m_map_manager.end(); ++iter) iter->second.clear(); } // Count elements with a specific key, return 1 (if the element is found) or zero (otherwise). const bool MapManager::IsUniqueIPMap(const DWORD dwMapIndex) { return m_map_manager.count(dwMapIndex) != 0; } // Returns the number of elements in the map container. const size_t MapManager::GetIPMapCount(const DWORD dwMapIndex) { return (m_map_manager[dwMapIndex]).size(); } /* char.cpp : #include "map_manager.h" marriage::CManager::instance().Logout(this); + MapManager::instance().Disconnect(this); */ void MapManager::Disconnect(const LPCHARACTER ch) { if (!ch) return; const DWORD dwMapIndex = ch->GetMapIndex(); if (!IsUniqueIPMap(dwMapIndex)) return; // Remove the player id from map list if exist. const auto it = std::find(m_map_manager[dwMapIndex].begin(), m_map_manager[dwMapIndex].end(), ch->GetPlayerID()); if (it != m_map_manager[dwMapIndex].end()) m_map_manager[dwMapIndex].erase(it); } void MapManager::Enter(const LPCHARACTER ch) { if (!ch) return; const DWORD dwPID = ch->GetPlayerID(); const DWORD dwMapIndex = ch->GetMapIndex(); if (!IsUniqueIPMap(dwMapIndex)) return; // Return iterator to the first element satisfying the condition or last if no such element is found. const auto it = std::find(m_map_manager[dwMapIndex].begin(), m_map_manager[dwMapIndex].end(), dwPID); // If no element is found in the map, find() returns map.end(). if (it != m_map_manager[dwMapIndex].end()) return; // Add the player id into map list. m_map_manager[dwMapIndex].emplace_back(dwPID); } const bool MapManager::IsPlayerIPInMap(const LPCHARACTER ch) { if (!ch) return false; if (!IsUniqueIPMap(ch->GetMapIndex())) return false; if (GetIPMapCount() == 0) return false; LPCHARACTER pkChar = NULL; // Range-based for loop, iterating the std::list with player pids. for (const auto dwPID : m_map_manager[ch->GetMapIndex()]) { if (!(pkChar = CHARACTER_MANAGER::instance().FindByPID(dwPID))) continue; if (!strcmp(ch->GetDesc()->GetHostName(), pkChar->GetDesc()->GetHostName()) && ch->GetPlayerID() != pkChar->GetPlayerID()) return true; } return false; }
BTW: Sorry for my english skills.
- 9
- 1
- 1
- 4
- 8
-
Why u guys don't read text-informations from Git?
Spoiler-
EVENTS_CALENDAR_DICT is just a configuration for <Python-Live-Test>.
-
The struct of the dictionary need to get it like EVENTS_CALENDAR_DICT = calendar.GetEventsData() << Source Client < Server
Also i'm sure you didn't understand how's work too, check with careful, you don't need to add events for each day/week etc, all are automatic.
- 'WEEKLY' - 1 event = 48 objects (1 * 4 * 12) << Insert the event by a specific day of week for each month.
- 'DAILY' - 1 event = 336-372 objects (1 * 28-31 * 12) << Insert the event for all days in each month.
- 'MONTHLY' = 1 event = 1 object << Insert the event by a specific day of month.
- 'ANNUALLY' - 1 event = 1 object << Insert the event by a specific month, week from month and day from week.
I said in the main post, this is just the python module part, the dictionary with config is just for live-test-debug, you've to parser how you want, from source client which is sended by a packet from server bla bla, is ur business how you want to do it, not mine, there's missing some things, you can get the classes/funcs and extend with your features/design etc.
PS: This module is for people who know what they've to do and know to read the code and make it work as they want, not for beginners.
As i said, don't ask for support implementation, the module doesn't contain all resources, is just for "developers".- 1
- 2
-
-
Thanks to @Mithras01 that he reminded me about bisection years. (i'll update the repository when i'll have a bit more free time)
Leap Year
- A normal year has 365 days.
- A Leap Year has 366 days (the extra day is the 29th of February).
Leap Years are any year that can be exactly divided by 4 (such as 2012, 2016, etc) except if it can be exactly divided by 100, then it isn't (such as 2100, 2200, etc) except if it can be exactly divided by 400, then it is (such as 2000, 2400) def GetRangeDaysMonth(calendarMonth): def GetBisectionYear(year): """ Provides support for maintaining a list in sorted order without having to sort the list after each insertion. Return True for leap years, False for non-leap years. """ return year % 4 == 0 and (year % 100 <> 0 or year % 400 == 0) """ TODO-DONE: Fix the calendar range days-month if month is February and is a bisection year like 2016, 2020, 2024 ... """ return Math.OFFSETS_MONTH_RANGE_TUPLE[calendarMonth - 1] + (calendarMonth == 2 and GetBisectionYear(Math.GetCurrentYear()))
Output-test:
Spoilerprint DBG_GetRangeDaysMonth(2, 2018) # February 2018 print DBG_GetRangeDaysMonth(2, 2019) # February 2019 print DBG_GetRangeDaysMonth(2, 2020) # February 2020 print DBG_GetRangeDaysMonth(2, 2024) # February 2024 <<<< 28 <<<< 28 <<<< 29 <<<< 29
- 2
- 1
-
M2 Download Center
( Internal )
( GitHub )
There's just a smart python module which i did for fun, for a friend, no support for implementation.
Enjoy.
Github repository:
- 189
- 3
- 4
- 4
- 1
- 3
- 4
- 1
- 1
- 78
- 16
- 138
-
Spoiler
- 1
- 7
-
5 minutes ago, Syriza said:
edit: solved, empireName wasn't the problem a class was missing in ui.py
Of course, the output of syserr or in generally the lines which showing the errors are not printed 100% the line fixed with the problem, there could be a syntax error, missing things etc. Before/after your EmpireName object too, and blocked while reading the code and your dictionary have missed some objects.
We can't fix a error all time just because of one line in syserr, you need to investigate the files related and see what's the real problem and use debug method.
- 1
-
Using std::ifstream, very easy.
DWORD dwItemVnum; float fProb; std::ifstream myfile(c_pszFileName, std::ifstream::in); while (myfile >> dwItemVnum >> fProb) { [...........] }
-
If somebody needs, there's a old shit which i did for somebody who had the source with no LC_TEXT and re-convert the source and adding LC_TEXT("string_index") and write a new locale_string.txt with string_index = the string which you had before.
Ignore the code, is a shit, take just the idea.
# Output: """ "LOCALE_STRING_01"; "Hai ricevuto %d"; "LOCALE_STRING_02"; "Una luce proviene da un grande albero"; "LOCALE_STRING_03"; "Hai ricevuto %d "; "LOCALE_STRING_04"; "Target is in %d channel (my channel %d)"; "LOCALE_STRING_05"; "Cannot find map (index %d)"; "LOCALE_STRING_06"; "You warp to ( %d, %d )"; "LOCALE_STRING_07"; "There is no one by that name"; "LOCALE_STRING_08"; "You warp to ( %d, %d )"; "LOCALE_STRING_09"; "<Mercatino Offline> Rinnovato di 30 giorni. Verrai sconnesso tra 3 secondi."; """ def UpdateLocaleString_SRC(): basePath, baseExcludeExt = (SRC_GAME_BASE_PATH, EXTENSION_EXCLUDED_LIST_SRC) localeStringList = [] for root, dirs, files in os.walk(basePath, topdown = True): dirs[:] = [dir for dir in dirs if dir not in DIRECTORY_EXCLUDED_LIST] countFunc = 0 for fileName in [file for file in files if GetExtension(file) not in baseExcludeExt]: # Cpp file fileName = '{:s}/{:s}'.format(root, fileName) for line in open(fileName, 'r').readlines(): line = line.strip('\n') chatLocaleString = '"LOCALE_STRING_%02u")' if LC_TEXT in line: continue if chatPacketFunc not in line: continue chatPointer = line.split(chatPacketFunc)[0].strip() chatType = line.split(chatPacketFunc)[1].split(",")[0] chatLine = chatMacroLocale % chatPointer chatIndexFindBeginString = line.find('"') chatIndexFindEndString = line.rfind('"') + 1 chatLastArgs = line[chatIndexFindEndString : len(line)] chatLocaleStringFinal = chatLocaleString % countFunc chatPosition = line.split(chatPacketFunc)[0] if chatPointer: chatPosition = line.split(chatPointer)[0] chatResult = chatPosition + chatPointer + chatPacketFunc + chatType + ", " + chatLine + chatLocaleStringFinal + chatLastArgs bAdded = AddLocaleString(fileName, line, chatResult) if bAdded: localeStringList.append((chatLocaleStringFinal[:-1] + ';', line[chatIndexFindBeginString : chatIndexFindEndString] + ';')) countFunc += 1 f = open("{:s}/{:s}".format(basePath, LOCALE_STRING_FILE_NAME), 'a+') for first, second in localeStringList: f.write('{:s}\n{:s}\n\n'.format(first, second)) f.close()
- 1
-
- exception KeyError
Raised when a mapping (dictionary) key is not found in the set of existing keys.
For example:
mydict = { 'EmpireName': ui.TextLine, 'GuildImage': ui.ExpandedImageBox } >>> empireName = mydict['EmpireName'] # <ui.TextLine object at 0x06FC3310> >>> guildImage = mydict['SkillName'] # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # KeyError: 'SkillName'
Check your selectcharacterwindow.py and be sure you have the object called 'EmpireName'.
- 1
-
def OnKeyDown(self, key): try: self.onPressKeyDict[key]() except KeyError: pass except: raise return True
- 1
-
Spoiler
- 1
- 6
-
The title says it all.
- Programming meme
- Metin2 meme
Please, no memes with people with disabilities.
Please use also the spoiler function.I'll start:
Spoiler- 1
- 11
-
@dmitry Your problem is in localeInfo.py (korean characters + bad encoding)
Here's your localeInfo.py fixed.
For those who have the same issue, check this reply, you'll find the file rewritted with non-korean shits and a lot of checks useless:
- 1
-
8 hours ago, WeedHex said:
Why not from c++ directly?
Not everything should be written in source, but here's a method. (2 years ago - i posted it in another forum)
//@Src/Server/game/src/input_login.cpp // Add to the beginning of the file: inline bool AllowedToWarp(const DWORD dwMapIndex, const DWORD dwLevel) { struct set_struct { const unsigned short map_index; const unsigned short minimum_level; } set_fields[] = { { 91, 75 }, // Grotto of Exile 1st Floor { 82, 75 }, // Grotto of Exile 2nd Floor { 216, 75 }, // Devils Catacomb { 218, 90 }, // Cape Dragon Head { 219, 90 }, // Dawn Mist Wood { 220, 90 }, // Mount Thunder { 221, 90 } // Bay Black Sand }; for (unsigned short i = 0; i < _countof(set_fields); ++i) { if (dwMapIndex == set_fields[i].map_index && dwLevel < set_fields[i].minimum_level) return false; } return true; } //1.) Search for: ch->SendGreetMessage(); //2.) Add after: if (!AllowedToWarp(ch->GetMapIndex(), ch->GetLevel())) ch->GoHome();
- 7
-
On 12/10/2018 at 10:52 PM, Exygo said:
So basically this is just to cut the unused msm's ?
Maybe could be used like this too, but the concept which i did for him was as unknown-reason for me.
On 12/13/2018 at 11:55 AM, Helia01 said:Useless thing.
But thanks.I know, but maybe for someone is useful and can take something from here.
LocaleInfo.py - Refactored
in Programming & Scripts
Posted
There are a lot of people which had problem with localeInfo because korean-characters and bad encoding, there's a clean file with refactored code.
Diff-checker: (856 Removals + 301 Additions)