-
Posts
402 -
Joined
-
Last visited
-
Days Won
20 -
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by Ikarus_
-
-
Did u notice this piece of code?
def BINARY_NEW_AddAffect(self, type, pointIdx, value, duration): print "BINARY_NEW_AddAffect", type, pointIdx, value, duration if type < 500: #<<-- return #<<--
Check if the type of the affect you are not seeing is over 500..
-
It looks like it is getting "false" as an int somehow. I ve no idea why it is happening only to you.A dirty solution may be define a spaceship operator with bool and int at the beginning of AsyncSQL.h (before the includes).Since i can't reproduce the error i m not able to check if my propose is valid (and i neither tried to compile the code tbh).inline constexpr auto operator<=>(const bool x, const int y) { return x <=> bool(y); }
to be honest i don't like it, i hate it, and i ve many doubts that it will work.
Another ugly way would be to use bool(false) instead of false where is getting the error.... but i don't really like to modify std files..A test that i think i may try to suggest you use to move the standard files included in AsyncSQL.h to the beginning of the file (move them above the other includes, i ve seen your files in stackoverflow question you made)
EDIT:
I ve found the cause of the error, it is a macro in libthrecore/stdafx.h and following my suggestion of move up the standard headers and move down the user defined headers you will solve your error.
here the macro is destroying the standard code:
#ifndef false #define false 0 #define true (!false) #endif
- 1
-
Sorry for the squat, but what do you want others to know about what you have in that source?
-
did u think to look at the expand button you already got? xd
i guess it would be a good idea
-
post the makefile libsql
- 1
-
On 3/13/2021 at 11:28 AM, astroNOT said:
Hello,
How can i create a new button that will show somewhere on the player's screen, which files stand for button object creation, and which module is the actual UI design ? To respect the patterns already implemented?
I assume I would create a button based on the classes in ui.py module. The question is where do I create the actual UI definition to display the button
in game? And on click, the lets say icon.tga button would display a message, "Hello world"?
Thanks
It depend where you need to add it...
e.g.
add button in inventory -> uiinventory.py
add button in taskbar -> uitaskbar.pyadd button in minimap -> uiminimap.py
etc etc
-
Dangling pointer, it may be due to the special storage/inventory if you got it
-
ScriptWindow (as the name suggests) are window created using scriptfiles (you can find a lot of them in uiscript and in locale/xx/ui).
These script files are (in short) a dictionary of items with settings of certain keys used by PythonScriptLoader class to assign to the elements the properties linked with the keys.
Let's show here an example:
SpoilerFile uiscript/inputdialog.py
import uiScriptLocale window = { "name" : "InputDialog", "x" : 0, "y" : 0, "style" : ("movable", "float",), "width" : 170, "height" : 90, "children" : ( { "name" : "Board", "type" : "board_with_titlebar", "x" : 0, "y" : 0, "width" : 170, "height" : 90, "title" : "", "children" : ( ## Input Slot { "name" : "InputSlot", "type" : "slotbar", "x" : 0, "y" : 34, "width" : 90, "height" : 18, "horizontal_align" : "center", #"type" : "image", #"image" : "d:/ymir work/ui/public/Parameter_Slot_03.sub", "children" : ( { "name" : "InputValue", "type" : "editline", "x" : 3, "y" : 3, "width" : 90, "height" : 18, "input_limit" : 12, }, ), }, ## Button { "name" : "AcceptButton", "type" : "button", "x" : - 61 - 5 + 30, "y" : 58, "horizontal_align" : "center", "text" : uiScriptLocale.OK, "default_image" : "d:/ymir work/ui/public/middle_button_01.sub", "over_image" : "d:/ymir work/ui/public/middle_button_02.sub", "down_image" : "d:/ymir work/ui/public/middle_button_03.sub", }, { "name" : "CancelButton", "type" : "button", "x" : 5 + 30, "y" : 58, "horizontal_align" : "center", "text" : uiScriptLocale.CANCEL, "default_image" : "d:/ymir work/ui/public/middle_button_01.sub", "over_image" : "d:/ymir work/ui/public/middle_button_02.sub", "down_image" : "d:/ymir work/ui/public/middle_button_03.sub", }, ), }, ), }
All the scripts have local variable named window (the dictionary that contains all the settings).
The first dictionary's (window) keys describe the scriptwindow properties, the window name, the height/width, the x/y where the window spawn, the style of the window (in this case moveable mean the window can be moved with the mouse and float mean the window has an order how the children are show and they can be moved over other children using SetTop).
the window usually has a "children" key that describe a tuple of dictionaries.
The tuple start with "(" and end with ")," and it contains other dictionaries that describe the children properties.
and example is the "Board" child that is a "board_with_titlebar" element (so a board with a titlebar and a close button on the top side).
the "type" key is really important, it describe what kind of element is going to be create. You can read all types available and all keys you can use to assign properties to the elements in the class PythonScriptLoader (especially in def LoadChildren) in ui.py.
The self.GetChild you mentioned is used to obtain the element using its "name" property.
The script window are a really clever way to make a window, but it has some limit.
The window made by using the script window can contain in the script only the "static" elements, the elements that are always created with the board.
To create dynamically the elements you have to code them and to assign the properties using the class methods defined in ui.py
An example on how you can create a button would be:
import ui ... ... ... class MyBoardExample(ui.Window): ... ... ... ... def LoadDynamicElements(self): race = player.GetRace() race_image_default = "d:/ymir work/ui/game/race_%d_default.sub"%race race_image_down = "d:/ymir work/ui/game/race_%d_down.sub"%race race_image_over = "d:/ymir work/ui/game/race_%d_over.sub"%race self.MainCharRaceButton = ui.Button() self.MainCharRaceButton.SetParent(self) #giving the parent to link the button the main board self.MainCharRaceButton.SetPosition(105, 456) #giving position using local coordinates self.MainCharRaceButton.SetUpVisual(race_image_default) #setting up visual (the image shown when button is in default state) self.MainCharRaceButton.SetDownVisual(race_image_down) #setting down visual (the image show when button is pressed) self.MainCharRaceButton.SetOverVisual(race_image_over) #setting over visual (the image shown when mouse come over the button) self.MainCharRaceButton.SAFE_SetEvent(self.__OnClickMainCharRaceButton) #setting an event to the button defined above self.MainCharRaceButton.Show() #the show is necessary to see the button
In the e.g. i created a button that change its visual based on the player character race.
WARNING: the code above wont work since the images and the event are invented and they don't exist
- 1
- 4
-
Doest it happen only with players?
I think you should show here some code.. if it happen only with players you should show all the ActorInstance class files and the InstanceBase files.
-
Fix updated with one more check in input_main.cpp
- 1
-
9 hours ago, Speachless said:
Hello,
int CInputMain::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
if (ch && ch->IsPC()) { if (get_global_time() < ch->analyze_protect) { ch->analyze_protect_count = ch->analyze_protect_count + 1; ch->ChatPacket(CHAT_TYPE_INFO, "<test server> analyze_protect_count. Count %d", ch->analyze_protect_count); if (ch->analyze_protect_count >= 300) { ch->analyze_protect_count = 0; d->SetPhase(PHASE_CLOSE); return (0); } } else ch->analyze_protect_count = 0; ch->analyze_protect = get_global_time() + 1; }
In char.h
int analyze_protect; int analyze_protect_count;
It is missing the initializing of these two values added in char.h.
They got a random value if you don't set it when CHARACTER object is instancied
i suggest to add something like :
//SEARCH void CHARACTER::Initialize() { //ADD UNDER analyze_protect = 0; analize_protect_count = 0;
-
4 minutes ago, ALF said:
and he still saying that to me if i have more money to pay he will tell me more fixes
I m available on discord for who want help
IkarusDeveloper#3677- 1
-
Hi guys,
There's a guy that is blackmailing all servers that are using my offlineshop.
Not just my clients, but also those who downloaded it from some idiot's leak.
I'm sharing the fix here as 60/70% of the servers currently open use my shop.
Fix:
Spoiler//FILE : new_offlineshop_manager.cpp //SEARCH FOR bool CShopManager::RecvShopCreateOfferClientPacket(LPCHARACTER ch, TOfferInfo& offer) { if(!ch) return false; //offlineshop-updated 03/08/19 if(ch->GetPlayerID() == offer.dwOwnerID) return false; //ADD UNDER // fix flooding offers if (!CheckOfferCooldown(ch->GetPlayerID())) return false; //SEARCH FOR: void CShopManager::ClearSearchTimeMap() { m_searchTimeMap.clear(); //ADD UNDER // fix flooding offers m_offerCooldownMap.clear(); //SEARCH FOR void CShopManager::ClearSearchTimeMap() { m_searchTimeMap.clear(); } //ADD UNDER // fix flooding offers bool CShopManager::CheckOfferCooldown(DWORD dwPID) { DWORD now = get_dword_time(); const DWORD cooldown_seconds = 15; itertype(m_offerCooldownMap) it = m_offerCooldownMap.find(dwPID); if (it == m_offerCooldownMap.end()) { m_offerCooldownMap[dwPID] = now + cooldown_seconds *1000; return true; } if (it->second > now) return false; it->second = now + cooldown_seconds * 1000; return true; } //FILE : new_offlineshop_manager.h //SEARCH FOR: //search time map (checking to avoid search abouse) void ClearSearchTimeMap(); bool CheckSearchTime(DWORD dwPID); //ADD UNDER: // fix flooding offers bool CheckOfferCooldown(DWORD dwPID); //SEARCH FOR: AUCTIONMAP m_mapAuctions; //ADD UNDER: // fix flooding offers SEARCHTIMEMAP m_offerCooldownMap; //SEARCH FOR int OfflineshopPacketCreateNewShop(LPCHARACTER ch, const char* data, int iBufferLeft) { offlineshop::TSubPacketCGShopCreate* pack = nullptr; if(!CanDecode(pack, iBufferLeft)) return -1; int iExtra=0; data = Decode(pack, data, &iExtra, &iBufferLeft); offlineshop::TShopInfo& rShopInfo = pack->shop; //ADD UNDER //fix flooding if (rShopInfo.dwCount > 500 || rShopInfo.dwCount == 0) { sys_err("tried to open a shop with 500+ items."); return -1; } //FILE : ClientManagerOfflineshop.cpp //SEARCH FOR: bool CClientManager::RecvOfflineShopOfferAccepted(const char* data) { offlineshop::TSubPacketGDOfferAccept* subpack; data = Decode(subpack, data); offlineshop::COfferCache::TOfferCacheInfo* pOffer=nullptr; m_offlineshopOfferCache.Get(subpack->dwOfferID,&pOffer); //ADD UNDER: if(!pOffer) return true;
Random User :
Why are u sharing it using metin2dev?
Answer:
I m bored to see this guy make money by blackmailing.Random User part2:
Is it right to share this fix even with those who are not your customer?Answer:
I honestly think that anyone who uses the shop without permission, taking it from sources different from me, is not worthy of help from me, however I can't even allow so many people to be fooled by this idiot boy.Random User part3:
Do you know who is blackmailing the p.server founders?Answer:
Yes, i know his discord account : Mădălin#2332I recommend to don't pay him at all. I would like to know other accounts of this guy, if anyone know some please report to me.
I also have the proofs about what i m talking.
BIG DISCLAIMER:
Test the code on a test-sever before to move it on a live-server.Thanks to @VegaS™ for the tip about cooldown
- 15
-
The first numbers are used when your level is 15 (or more) levels higher than monster level (the number 1 means that the basic chance is reduced by a factor 1/100 ).
The last numbers are used when your level is 15 (or more) levels lower than monster level (the number 1 means that the basic chance is increased by a factor 180/100)
the numbers in the center (100) is the neutral value (doesn't affect the basic chance to drop the item)- 1
-
-
You could download cryptopp library code from the official website.
You will find the .sln file (Solution) which is to be open with visual studio.
Once You open it You can compile it.
Take care to check the Code mode generation to be set on MT for Release and MTd for Debug.
You can find it by clicking right click on cryptlib project > properties > C++ > Code generation > runtime library
After compiled the library move it in your extern/lib and move all .h files (aka headers) on your extern/include/cryptopp (headers and libs are always to be used from the identical version of the library source code)
Hope i ve explained enoght clearly but for a short recap:
- Download the library source code from the official website.
- Open the file .sln with visual studio.
- Check the code generation mode as explained above.
- Compile the library and move it on extern/lib.
- Move the headers from the library's source code on your extern/include/cryptopp.
- Compiler your game again and enjoy.
-
VERY BIG DISCLAIMER: I m going to show you where the level delta is applied and how they made the constants, but they are used for all monsters, and not only for Stones.
long answer:
Spoilerin game/src/constants.h
#define PERCENT_LVDELTA(me, victim) aiPercentByDeltaLev[MINMAX(0, (victim + 15) - me, MAX_EXP_DELTA_OF_LEV - 1)] #define PERCENT_LVDELTA_BOSS(me, victim) aiPercentByDeltaLevForBoss[MINMAX(0, (victim + 15) - me, MAX_EXP_DELTA_OF_LEV - 1)]
as you can see here is calculating a PERCENTAGE to apply to the drop chance which depend on level delta (monster level - player level)
These are macros which are using aiPercentByDeltaLev and aiPercentByDeltaLevForBoss and they are defined in constant.h/constant.cpp.
here is where is calling the macros (item_manager.cpp ITEM_MANAGER::GetDropPct ):
if (!pkChr->IsStone() && pkChr->GetMobRank() >= MOB_RANK_BOSS) iDeltaPercent = PERCENT_LVDELTA_BOSS(pkKiller->GetLevel(), pkChr->GetLevel()); else iDeltaPercent = PERCENT_LVDELTA(pkKiller->GetLevel(), pkChr->GetLevel());
here is where the aiPercentByDeltaLev and aiPercentByDeltaLevForBoss are defined (i really don't like how they are defined) from constants.cpp:
const int * aiPercentByDeltaLev = NULL; const int * aiPercentByDeltaLevForBoss = NULL;
They are instanced as NULL and they get the real value on runtime by parsing the locale (from locale_service.cpp):
void LocaleService_TransferDefaultSetting() { if (!check_name) check_name = check_name_euckr; if (!is_twobyte) is_twobyte = is_twobyte_euckr; if (!exp_table) exp_table = exp_table_common; if (!CTableBySkill::instance().Check()) exit(1); if (!aiPercentByDeltaLevForBoss) aiPercentByDeltaLevForBoss = aiPercentByDeltaLevForBoss_euckr; if (!aiPercentByDeltaLev) aiPercentByDeltaLev = aiPercentByDeltaLev_euckr; if (!aiChainLightningCountBySkillLevel) aiChainLightningCountBySkillLevel = aiChainLightningCountBySkillLevel_euckr; }
Finally we can see here that the real array const defined is aiPercentByDelta_euckr and aiPercentByDeltaLevForBoss_euckr, which are defined in constants.cpp:
// MIN(MAX_EXP_DELTA_OF_LEV - 1, (Àû·¾ + 15) - ³»·¾)) const int aiPercentByDeltaLevForBoss_euckr[MAX_EXP_DELTA_OF_LEV] = { 1, // -15 0 3, // -14 1 5, // -13 2 7, // -12 3 15, // -11 4 30, // -10 5 60, // -9 6 90, // -8 7 91, // -7 8 92, // -6 9 93, // -5 10 94, // -4 11 95, // -3 12 97, // -2 13 99, // -1 14 100, // 0 15 105, // 1 16 110, // 2 17 115, // 3 18 120, // 4 19 125, // 5 20 130, // 6 21 135, // 7 22 140, // 8 23 145, // 9 24 150, // 10 25 155, // 11 26 160, // 12 27 165, // 13 28 170, // 14 29 180 // 15 30 }; const int aiPercentByDeltaLev_euckr[MAX_EXP_DELTA_OF_LEV] = { 1, // -15 0 5, // -14 1 10, // -13 2 20, // -12 3 30, // -11 4 50, // -10 5 70, // -9 6 80, // -8 7 85, // -7 8 90, // -6 9 92, // -5 10 94, // -4 11 96, // -3 12 98, // -2 13 100, // -1 14 100, // 0 15 105, // 1 16 110, // 2 17 115, // 3 18 120, // 4 19 125, // 5 20 130, // 6 21 135, // 7 22 140, // 8 23 145, // 9 24 150, // 10 25 155, // 11 26 160, // 12 27 165, // 13 28 170, // 14 29 180, // 15 30 };
short answer:
Spoilerfrom constants.cpp:
// MIN(MAX_EXP_DELTA_OF_LEV - 1, (Àû·¾ + 15) - ³»·¾)) const int aiPercentByDeltaLevForBoss_euckr[MAX_EXP_DELTA_OF_LEV] = { 1, // -15 0 3, // -14 1 5, // -13 2 7, // -12 3 15, // -11 4 30, // -10 5 60, // -9 6 90, // -8 7 91, // -7 8 92, // -6 9 93, // -5 10 94, // -4 11 95, // -3 12 97, // -2 13 99, // -1 14 100, // 0 15 105, // 1 16 110, // 2 17 115, // 3 18 120, // 4 19 125, // 5 20 130, // 6 21 135, // 7 22 140, // 8 23 145, // 9 24 150, // 10 25 155, // 11 26 160, // 12 27 165, // 13 28 170, // 14 29 180 // 15 30 }; const int aiPercentByDeltaLev_euckr[MAX_EXP_DELTA_OF_LEV] = { 1, // -15 0 5, // -14 1 10, // -13 2 20, // -12 3 30, // -11 4 50, // -10 5 70, // -9 6 80, // -8 7 85, // -7 8 90, // -6 9 92, // -5 10 94, // -4 11 96, // -3 12 98, // -2 13 100, // -1 14 100, // 0 15 105, // 1 16 110, // 2 17 115, // 3 18 120, // 4 19 125, // 5 20 130, // 6 21 135, // 7 22 140, // 8 23 145, // 9 24 150, // 10 25 155, // 11 26 160, // 12 27 165, // 13 28 170, // 14 29 180, // 15 30 };
Conclusions:
The influence of difference of level on dropping is exactly how you described.If my level is lower than the level of the monster/stone i get a drop bonus.
if my level is equal to the level of the monster/stone i don't get a bonus and neither a malus.
if my level is higher than level of the monster i get a malus
- 3
-
Post here the .msa files used for the buggy skill.
You can find them in playersettingmodule.py, around def __LoadGameWarriorEx
.msa files can cause this, the reason is here:
At least one Motion Event must be Type 4 for skills.
-
8 minutes ago, ZumbaCafew said:
Thanks for sharing, where should I put this folder? Thank you
I usually prefer to put the 3th part libraries on extern folder, but you can move it whenever you want.
The important thing is to change the -I and -L directives with your directories.
An example would be:
#Mysql Dynamic LIBDIR += -L../../../extern/lib/mysql INCDIR += -I../../../extern/include/mysql LIBS += -lmysqlclient #Mysql Static INCDIR += -I../../../extern/include/mysql LIBS += ../../../extern/lib/mysql/libmysqlclient.a
the first three lines are for a dynamic linking (it might prefer to link using libmysqlclient.so rather than libmysqlclient.a where both are available)
the second two lines are for a static linking (where we are forcing it to use libmysqlclient.a)
You can choice the way you prefer.
- 1
-
-
i ll send you my include and lib folders for mysql80, they are for freebsd 11.3 only (32 bit obv) give me a moment to make the zip
4 hours ago, ZumbaCafew said:I solved the problem thanks to the lib in the mysql 7.x-5.1.35 folder, so I manage to compile, but how can I get the lib for mysql8?
You can't use a lib and an include which are from differents version of mysql... you will get runtime errors (segmentation fault)
-
10 minutes ago, ZumbaCafew said:
I don't have the lib-lmysqlclient
You should put it in your extern/lib.
I don't think you will find it in your machine x64, you need the 32bit one.
What version of freebsd are u using? pkg.freebsd.org may help you to find it easly
-
On 10/25/2020 at 1:57 AM, ZumbaCafew said:
linking ../db_r40414_64....
ld: error: unable to find library -lmysqlclient
clang-9: error: linker command failed with exit code 1 (use -v to see invocation)
gmake: *** [Makefile:56: ../db_r40414_64] Error 1Are you compiling on a i386 machine? or an amd64?
Amd64 machines will install you the lib built in 64bit which are incompatible with your game and db executables (which you are building in 32bit).On 11/3/2020 at 10:54 PM, ZumbaCafew said:ifeq ($(BSD_VERSION), 7) INCDIR += -I../../libmysql/7.x-5.1.35 LIBDIR += -L../../libmysql/7.x-5.1.35 else INCDIR += -I../../libmysql/mysql_8_0_20 LIBDIR += -L../../libmysql/mysql_8_0_20 endif
Here you changed the -I and -L paths you are adding to LIBDIR and INCDIR, but can u find the lib in the directory you moved to?
-
On 10/28/2020 at 4:55 PM, TokiSan said:
char.cpp:8086: error: request for member 'reset' in 'pkMsg', which is of non-class type 'SQLMsg*' char.cpp:8086: error: 'nullptr' was not declared in this scope
Uhm, yep, nullptr is not declared means you are not using c++11(+) and pkMsg is of non-class type SQLMsg* means you are using .reset on a raw pointer (and .reset is not needed even for smart ptr).
You solved differently but maybe someone is interested in knowing why errors are received when they are received, as well as knowing how to fix it.
On 11/7/2020 at 2:21 PM, developerares said:Is there a problem with this code? I have smart ptr.
No it is correct. std::unique_ptr<SQLMsg> will delete the memory from heap when its destructor is called.
smart pointers have the overload of the operator -> and this help to use them as classic (raw) pointers. (e.g. where you used Msg->Get())
How to create button expand?
in Community Support - Questions & Answers
Posted
Yeah so if you want an help i think you should post the code... otherwise i can't check nothing xd