Jump to content

VegaS™

Forum Moderator
  • Posts

    656
  • Joined

  • Last visited

  • Days Won

    187
  • Feedback

    100%

Posts posted by VegaS™

  1. Just now arrived from work, sorry for late answer.

    On 11/11/2019 at 10:52 PM, ManiacRobert said:

    Depend of your costume type, if is REAL_TIME and REAL_TIME_FIRST_USE you need to use get_global_time() for time verification, will be something like this

    
    (7 * 24 * 60 * 60) - get_global_time();

    If he do what you said, 604800 - current_timestamp =  > -1kkk.

    The correct way and single way to do it properly, is the the next one:

    This is the hidden content, please

    • Metin2 Dev 9
    • Scream 1
    • Love 7
  2. On 11/3/2019 at 11:13 PM, Syriza said:

    i hope I get some help  @Syriza

    slotIndex = Your index position from inventory.

    Python

    import player
    
    attrCount = 0
    for i in xrange(player.ATTRIBUTE_SLOT_MAX_NUM):
    	if player.GetItemAttribute(player.INVENTORY, slotIndex, i):
    		attrCount += 1
    
    print(attrCount)

    C++

    This is the hidden content, please

     

    • Metin2 Dev 17
    • Good 3
    • Love 8
  3. M2 Download Center

    This is the hidden content, please
    ( Internal )

    This is the hidden content, please
    ( GitHub )

    Hello cowboys, since i was at job and i was bored while coding in other languages, i thought would be funny if i code something in Python, so an idea came in mind, doing a general text file loader for parsing different data, with different structs, normal variables, groups and lists, like ymir idea for parsing the files (.mse, .msa, .msm, .txt like mob_drop_item.txt, group.txt, etc)

    This tool can be used everywhere, for metin2 or else, i wrote this from scratch using ymir idea, also you can run it in any version of Python.
    If you use this for metin2, change USING_METIN2_CLIENT to True.

    Spoiler
    
    
    
    ANDROID_LINK	http://www.antutu.com/en/ranking/rank1.htm
    IOS_LINK		http://www.antutu.com/en/ranking/ios1.htm
    DOWNLOAD_LINK	http://www.antutu.com/en/download.htm
    
    Group Antutu_Benchmark_Android
    {
    	LAST_UPDATED	"September 2019"
    
    	Group Device00
    	{
    		NAME				"ROG Phone 2"
    		RAM_AND_STORAGE		"8GB+128GB"
    		CPU					127580
    		UX					81187
    		3D					173673
    		TOTAL_SCORE			396200
    	}
    	
    	Group Device01
    	{
    		NAME				"Asus ZenFone 6 2019"
    		RAM_AND_STORAGE		"6GB+128GB"
    		CPU					115926
    		UX					72764
    		3D					175221
    		TOTAL_SCORE			377199
    	}
    	
    	Group Device02
    	{
    		NAME				"OnePlus 7 Pro"
    		RAM_AND_STORAGE		"8GB+256GB"
    		CPU					122874
    		UX					77862
    		3D					157802
    		TOTAL_SCORE			373097
    	}
    }

     

    This is the hidden content, please

     

    Full source repository:

     

    • Metin2 Dev 48
    • Eyes 1
    • Think 1
    • Good 8
    • Love 3
    • Love 34
  4. On 10/15/2019 at 1:30 PM, Mali61 said:

    PythonPlayer.cpp:

    
    bool CPythonPlayer::_IsDSPageFull(BYTE page)
    {
    	if (page < 0 || page >= DS_DECK_MAX_NUM)
    		return false;
    	DWORD count = 0;
    	DWORD startsize = c_DragonSoul_Equip_Start + c_DragonSoul_Equip_Slot_Max * page;
    	const DWORD endsize = c_DragonSoul_Equip_Start + c_DragonSoul_Equip_Slot_Max * (page + 1);
    	for (; startsize < endsize; ++startsize)
    		if (GetItemIndex(TItemPos(INVENTORY, startsize)))
    			count++;
    	return count == c_DragonSoul_Equip_Slot_Max;
    }

    @Mali61 Good idea, but what i did doesn't work like this.

    You've to check each dragon soul from all pages if they aren't expired and the specific page is activated too.

    This is the hidden content, please

    • Metin2 Dev 21
    • Good 5
    • Love 13
  5. I don't like so much Lua, but i did something fast, i hope that's what you wanted.
    Replace npc.get_level() with npc.get_level0() if you use marty source.

    quest common_drop_quest begin
    	state start begin
    
    		function CanDrop(pc_level, npc_level, isPC)
    			local DIFF_LEVEL_CONST = 10
    			return not isPC and math.abs(pc_level - npc_level) <= DIFF_LEVEL_CONST
    		end
    
    		function GetSettings()
    			local PLAYER_MAX_LEVEL_CONST = 105
    			return
    			{
    				{ 20, 40, {27001, 27001, 27001, 27001, 27001, 27001} }, -- from 20 to 39
    				{ 40, 60, {27002, 27002, 27002, 27002, 27002, 27002} }, -- from 40 to 59
    				{ 60, 80, {27003, 27003, 27003, 27003, 27003, 27003} }, -- from 60 to 79
    				{ 80, 100, {27004, 27004, 27004, 27004, 27004, 27004} }, -- from 80 to 99
    				{ 100, PLAYER_MAX_LEVEL_CONST + 1, {27005, 27005, 27005, 27005, 27005, 27005} }, -- from 100 to PLAYER_MAX_LEVEL_CONST
    			}
    		end
    
    		when kill with common_drop_quest.CanDrop(pc.get_level(), npc.get_level(), npc.is_pc()) begin
    			local common_drop_table = common_drop_quest.GetSettings()
    
    			for i = 1, table.getn(common_drop_table) do
    				local dropLevelMin, dropLevelMax, dropItemTable = unpack(common_drop_table[i])
    				local dropItemVnum = dropItemTable[number(1, table.getn(dropItemTable))]
    
    				if pc.get_level() >= dropLevelMin and pc.get_level() < dropLevelMax then
    					if number(1, 10000) <= 100 then
    						game.drop_item_with_ownership(dropItemVnum)
    						break
    					end
    				end
    			end
    		end
    	end
    end

     

    • Love 5
  6. 42 minutes ago, ManiacRobert said:

    I think it's needed to send via packet or cmdchat get_global_time() from server-side

    Already app.GetGlobalTimeStamp() (#1 #2) doing that, returns the server timestamp (sent by TPacketGCTime to client) on each enter in game, you just need to convert the timestamp with a proper method.

    cur_time_stamp = app.GetGlobalTimeStamp()
    seconds = cur_time_stamp % 60
    minutes = (cur_time_stamp / 60) % 60
    hours = (cur_time_stamp / 60) / 60 % 24
    
    self.textLine.SetText("%02i:%02i:%02i" % (hours, minutes, seconds))
    • Metin2 Dev 1
    • Good 1
    • Love 7
  7. CLICK FOR VIDEO

     

     

    • Server\src\game\src\DragonSoul.h
    Spoiler
    
    //1.1) Search for:
    	bool	DragonSoulItemInitialize(LPITEM pItem);
    //1.2) Add after:
    	bool	HasActivedAllSlotsByPage(const LPCHARACTER ch, const BYTE bPageIndex = DRAGON_SOUL_DECK_0) const;

     

    • Server\src\game\src\DragonSoul.cpp
    Spoiler
    
    //1.1) Search for:
    BYTE GetStrengthIdx(DWORD dwVnum)
    {
    	return (dwVnum / 10) % 10;
    }
    //1.2) Add after:
    bool DSManager::HasActivedAllSlotsByPage(const LPCHARACTER ch, const uint8_t bPageIndex) const
    {
    	if (!ch || bPageIndex >= DRAGON_SOUL_DECK_MAX_NUM)
    		return false;
    
    	const uint16_t iDragonSoulDeckAffectType = AFFECT_DRAGON_SOUL_DECK_0 + bPageIndex; // 540 + [0 or 1]
    	if (!ch->FindAffect(iDragonSoulDeckAffectType))
    		return false;
    
    	// start : 32 + ([0 or 1] * 6) = [32 or 38]
    	// end : start + 6
    	const uint8_t iStartIndex = WEAR_MAX_NUM + (bPageIndex * DS_SLOT_MAX);
    	const uint8_t iEndIndex = iStartIndex + DS_SLOT_MAX;
    	
    	uint8_t bSlotActive = 0;
    	for (uint8_t bCell = iStartIndex; bCell < iEndIndex; ++bCell) // {0: 32-38, 1: 38-44}
    	{
    		const LPITEM pkItem = ch->GetWear(bCell);
    		if (pkItem && pkItem->IsDragonSoul())
    		{
    			if (IsTimeLeftDragonSoul(pkItem) && IsActiveDragonSoul(pkItem))
    				++bSlotActive;
    		}
    	}
    
    	return (bSlotActive == DS_SLOT_MAX);
    }

     

    • How-To-How-To-How-To-Use-Ex:

    This is the hidden content, please

    • Metin2 Dev 30
    • Good 7
    • Love 27
  8. That's what he requested in private, if someone need it, those are not my calculations/code.

    void CItemAddonManager::ApplyAddonTo(int iAddonType, LPITEM pItem)
    {
    	if (!pItem)
    	{
    		sys_err("ITEM pointer null");
    		return;
    	}
    
    	bool bCustomizedAddon = false;
    	switch (pItem->GetVnum())
    	{
    		case 1129:	
    		case 2129:	
    		case 3129:	
    		case 5129:	
    			bCustomizedAddon = true;
    			break;
    	}
    	
    	int iSkillBonus = MINMAX(-30, static_cast<int>(gauss_random(0, 5) + 0.5f), 30);
    	int iNormalHitBonus = 0;
    	if (bCustomizedAddon)
    	{
    		if (abs(iSkillBonus) <= 0)
    			iNormalHitBonus = (-1 * iSkillBonus) / 2 + abs(number(-2, 2) + number(-2, 2)) + number(1, 2);
    		else
    			iNormalHitBonus = (-1 * iSkillBonus) / 2 + abs(number(-3, 6));
    	
    		if (abs(iSkillBonus) <= 0)
    			iSkillBonus = (1 * iSkillBonus) / 2 + abs(number(-1, 1) + number(-1, 1)) + number(1, 2);
    		else
    			iSkillBonus = (1 * iSkillBonus) / 2 + abs(number(-3, 1));
    	}
    	else
    	{
    		if (abs(iSkillBonus) <= 20)
    			iNormalHitBonus = -2 * iSkillBonus + abs(number(-8, 8) + number(-8, 8)) + number(1, 4);
    		else
    			iNormalHitBonus = -2 * iSkillBonus + number(1, 5);
    	}
    
    	pItem->RemoveAttributeType(APPLY_SKILL_DAMAGE_BONUS);
    	pItem->RemoveAttributeType(APPLY_NORMAL_HIT_DAMAGE_BONUS);
    	pItem->AddAttribute(APPLY_NORMAL_HIT_DAMAGE_BONUS, iNormalHitBonus);
    	pItem->AddAttribute(APPLY_SKILL_DAMAGE_BONUS, iSkillBonus);
    }
    • Love 4
  9. V1

    • You can use unlimited arguments on functions, now is using the apply method which returns the result of a function or class object called with supplied arguments,  with the old structure you could use just one argument.
    • You can lock/unlock an event for being processed, it's like a prevent in some actions, if the event is created and you want to do something, you should lock the event, do some actions then you can unlock it again and the process function will run where remained.
    • Delete an event instantly and force it to stop the process.
    • Adding return t.EXIT inside of the running function, will delete the event too.
    • Functions to check if an event exists or is locked or not.
    • Check if the function is a method type.
    • Delete the events with a properly method.
    • Using app.GetGlobalTimeStamp() now will give you the chance to run the event after teleport where timer remained instantly.

    V2

    • Fixed non-returning time for processing, if the specific event function has no value from returning, it runs continuously.
    • Fixed the check if an event exist, now will be replaced with the new one.
    • Removed
      This is the hidden content, please
      library (i heard that some people don't have it) and using builtin functions, instead of types.MethodType now we're using callable(object), which check if the event function can be called, now you can insert classes and others callable methods, not just simple functions.
    • Added a reset time event function.

    Next update: (when i'll have some free time again)

    • Insert a new type of event, which you can run an event by specific counter like:
    t.AppendEvent(eventName='RUN', eventStartTime=5, eventRunCount=10, eventFunc=self.Run, eventFuncArgs=player.GetLevel())

    The following things will happen:

    • The function Run(args), will start to run in 5 seconds for 10 times.

    PS: Check my first reply for code.

    • Metin2 Dev 3
    • Good 3
    • Love 7
  10. On 10/9/2019 at 11:44 PM, WeedHex said:

    Was better with timer solution, mount begin load after other things so checking the login is useless cuz there isn't still mount at login :)

    No, we don't need a timer for this, you're right that you can't do this inside of login because the POINT_MOUNT is seted after, so, this method is for all types of mounts/horses: 

    This is the hidden content, please

    Not tested.

    • Metin2 Dev 6
    • Think 1
    • Good 1
    • Love 1
    • Love 7
  11. 1 hour ago, Cripplez said:

    I tried like this but when i'm riding a mount it still doesn't make me unmount it :( with the horse it is perfect

    Then your problem is that you've costume mount slot, not the default mount, replace the code what i gave you with:

    #ifdef ENABLE_BLOCK_RIDING_IN_DUNGEON
    	if (ch && ch->GetDungeon())
    	{
    		const LPITEM pMount = ch->GetWear(WEAR_COSTUME_MOUNT);
    		if (pMount && pMount->IsEquipped())
    			ch->UnequipItem(pMount);
    	
    		if (ch->IsHorseRiding())
    		{
    			ch->StopRiding();
    			ch->HorseSummon(false);
    		}
    	}
    #endif

    Be careful to have on all of your vnums type: ITEM_COSTUME < 28, sub type: COSTUME_MOUNT < 2

    • Love 1
  12. 2 hours ago, Cripplez said:

    I'm not sure if i did this part as you write in your message, maybe the problem is here?

      Hide contents
    
    
    	if (ch->GetHorseLevel() > 0)
    	{
    		DWORD pid = ch->GetPlayerID();
    
    		if (pid != 0 && CHorseNameManager::instance().GetHorseName(pid) == NULL)
    			db_clientdesc->DBPacket(HEADER_GD_REQ_HORSE_NAME, 0, &pid, sizeof(DWORD));
    		//@fix horse_level update at login
    		ch->SetHorseLevel(ch->GetHorseLevel());
    		ch->SkillLevelPacket();
    #ifdef ENABLE_BLOCK_RIDING_IN_DUNGEON
    		if (ch && ch->GetDungeon())
    		{
    			if (ch->IsHorseRiding())
    			{
    				ch->StopRiding();
    				ch->HorseSummon(false);
    			}
    
    			if (ch->FindAffect(AFFECT_MOUNT))
    			{
    				ch->RemoveAffect(AFFECT_MOUNT);
    				ch->RemoveAffect(AFFECT_MOUNT_BONUS);
    			}
    		}
    #endif
    	}

     

    You added it wrong, not inside of GetHorseLevel > 0, outside of condition. 

    Spoiler
    
    	if (ch->GetHorseLevel() > 0)
    	{
    		DWORD pid = ch->GetPlayerID();
    
    		if (pid != 0 && CHorseNameManager::instance().GetHorseName(pid) == NULL)
    			db_clientdesc->DBPacket(HEADER_GD_REQ_HORSE_NAME, 0, &pid, sizeof(DWORD));
    		//@fix horse_level update at login
    		ch->SetHorseLevel(ch->GetHorseLevel());
    		ch->SkillLevelPacket();
    	}
    #ifdef ENABLE_BLOCK_RIDING_IN_DUNGEON
    	if (ch && ch->GetDungeon())
    	{
    		if (ch->IsHorseRiding())
    		{
    			ch->StopRiding();
    			ch->HorseSummon(false);
    		}
    
    		if (ch->FindAffect(AFFECT_MOUNT))
    		{
    			ch->RemoveAffect(AFFECT_MOUNT);
    			ch->RemoveAffect(AFFECT_MOUNT_BONUS);
    		}
    	}
    #endif

     

     

  13. Not tested, but you can try to do something like:

    • Srcs/Server/game/src/questlua_horse.cpp
    Spoiler
    
    // Search in horse_summon function:
    		bool bFromFar = lua_isboolean(L, 1) ? lua_toboolean(L, 1) : false;
    // Add before:
    #ifdef ENABLE_BLOCK_RIDING_IN_DUNGEON
    		if (ch && ch->GetDungeon())
    			return 0;
    #endif
    • Srcs/Server/game/src/questlua_pc.cpp
    Spoiler
    
    // Search in pc_mount_bonus and pc_mount function:
    		LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
    // Add after:
    #ifdef ENABLE_BLOCK_RIDING_IN_DUNGEON
    		if (ch && ch->GetDungeon())
    			return 0;
    #endif
    • Srcs/Server/game/src/input_login.cpp
    Spoiler
    
    // Search in CInputLogin::Entergame(LPDESC d, const char * data) for:
    	if (ch->GetHorseLevel() > 0)
    	{
    		DWORD pid = ch->GetPlayerID();
    
    		if (pid != 0 && CHorseNameManager::instance().GetHorseName(pid) == NULL)
    			db_clientdesc->DBPacket(HEADER_GD_REQ_HORSE_NAME, 0, &pid, sizeof(DWORD));
    	}
    // Add after:
    #ifdef ENABLE_BLOCK_RIDING_IN_DUNGEON
    		if (ch && ch->GetDungeon())
    		{
    			if (ch->IsHorseRiding())
    			{
    				ch->StopRiding();
    				ch->HorseSummon(false);
    			}
    
    			if (ch->FindAffect(AFFECT_MOUNT))
    			{
    				ch->RemoveAffect(AFFECT_MOUNT);
    				ch->RemoveAffect(AFFECT_MOUNT_BONUS);
    			}
    		}
    #endif
    • Srcs/Server/game/service.h
    Spoiler
    
    #define ENABLE_BLOCK_RIDING_IN_DUNGEON
  14. On 10/5/2019 at 2:19 AM, Syriza said:

    Can you maybe tell how to do the Video with escape key, like official ?
    I mean being able to cancel the Video with escape key.

    As the title says, here's the simple method how you can skip the video without waiting until is finished, like official did long time ago.
    Here're the constants value for virtual-key codes (hexadecimal values), right now these are by default:

    • VK_LBUTTON 0x01 - Left mouse button
    • VK_ESCAPE 0x1B - ESC key
    • VK_SPACE 0x20 SPACEBAR

    Srcs/Client/UserInterface/Locale_inc.h

    Spoiler
    
    #define ENABLE_SKIP_MOVIE

    Srcs/Client/UserInterface/MovieMan.cpp

    Spoiler
    
    // 1.0) Search the function:
    	PlayMovie(pcszName);
    // 1.1) Replace with:
    #ifdef ENABLE_SKIP_MOVIE
    	PlayMovie(pcszName, true);
    #else
    	PlayMovie(pcszName);
    #endif

     

    Quote

    How to do it when i press any key/mouse etc to skip it? Not only by specific keys, people don't know those keys maybe.

    This is the hidden content, please

    • Metin2 Dev 24
    • Angry 1
    • Think 1
    • Good 5
    • Love 2
    • Love 40
  15. 9 minutes ago, glosteng4141 said:

    collected codes from the garbage  :) please learn how to code.

    Instead of repeating yourself in every reply that the code is bullshit, how about showing us your coding skills and let us criticize it too?  
    I'm sure that i'll have a lot of fun, and not only me. ?

    Btw, is funny how you're talking about shit code and say to people 'learn how to code', when you do this:

    Spoiler

    24d97a9c65f8e345cb9ac641c9566b75.png

     

    • Love 13
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.