Jump to content

VegaS™

Forum Moderator
  • Posts

    656
  • Joined

  • Last visited

  • Days Won

    187
  • Feedback

    100%

Posts posted by VegaS™

  1. First one, thanks for release and good idea, here are some advices for the next time, how you should use zip method and lambda instead of __mem__func__ and others empty functions.

    • Since the loadStepList is declared with ascending numbers from 0 to 100 (by default), we don't have to use min and max method for get the values for range, just the first value and the last value from list.
    • __mem_func__ and the function 'bos' are useless in that case, we can replace it with a null lambda, will do the same job too.
    • Using an list comprehension with conditions inside, isn't so readable.

    Good idea for zip method to get all the progresses values, but we don't need to initialize like that, you can acces the first reference by using index [0] from iterator.

    Spoiler
    
    # checkin, _ = zip(*self.loadStepList)
    
    lst = [[1, None], [2, None]]
    first, second = zip(*lst)
    print (first, second)
    >>> (1, 2) (None, None)
    
    lst = [[1, None], [2, None]]
    first = tuple(zip(*lst))[0]
    print (first)
    >>> (1, 2)
    
    # I would use a bitwise and set method to get the missing values without doing a check for progress value.
    print (list(set([0, 2]) ^ set([0, 1, 2, 3, 4, 5])))
    >>> [1, 3, 4, 5]

     

    On 5/25/2019 at 12:03 AM, Mali61 said:
    
    def bos(self):
    	pass
    
    checkin, _ = zip(*self.loadStepList)
    self.loadStepList = sorted(self.loadStepList+[(i, ui.__mem_func__(self.bos)) for i in range(min(checkin), max(checkin)+1) if i not in checkin])

    Should look like

    This is the hidden content, please
    :

    This is the hidden content, please

    • Metin2 Dev 23
    • Sad 1
    • Good 4
    • Love 1
    • Love 25
  2. M2 Download Center

    This is the hidden content, please
    ( Internal )

    This is the hidden content, please
    ( GitHub )

    What's the issue?

    SYSERR: Aug 22 18:36:42.624296 :: ReadEtcDropItemFile: No such an item (name:  Èò»ö  ´ó±â+) SYSERR:  
    Aug 22 18:36:42.624379 :: Boot: cannot load ETCDropItem: locale/germany/etc_drop_item.txt

    Some people fixed it long time ago by replacing the column name from item_proto (which is korean) with vnum.

    68747470733a2f2f692e6779617a6f2e636f6d2f39616463653961663637373166343966366162353162393166353035613539372e706e67

    If you want to do it like this and don't want the source change (from below) or you don't have the source code of your game core, you can use a update query and copy the vnum to name just if the vnum from item_proto exists inside of mob_proto.drop_item by a specific mob.

    UPDATE player.item_proto SET name = vnum
    	WHERE vnum IN (SELECT drop_item FROM player.mob_proto WHERE drop_item >= 10);  
    # Affected rows: 83  
    # Time: 35.919ms

    How can i know where the items are dropped?

    So, the structure of etc_drop_item.txt is based on dropping a item with a probability from a specific mob where that mob have the item vnum attached in column mob_drop -> drop_item.

    SELECT DISTINCT locale_name, vnum, drop_item FROM player.mob_proto where drop_item >= 10;
    locale_name vnum drop_item
    Wolf 102 30028
    Alpha Wolf 103 30069
    Alpha Blue Wolf 105 30027
    Grey Wolf 106 30070

    How-To-Fix

     Default structure:

    item_proto.name prob
    늑대발톱 2.0
    늑대발톱+ 2.0
    늑대털 2.0
    멧돼지의 어금니 2.0

     With the fix you can use both of methods:

    item_proto.[name or vnum] prob
    30028 2.0
    30069 2.0
    30027 2.0
    멧돼지의 어금니 2.0

    This is the hidden content, please
    epository:

    This is the hidden content, please

    • Metin2 Dev 52
    • Smile Tear 1
    • Think 2
    • Good 23
    • Love 6
    • Love 42
    • uiScript/whisperdialog.py
    "input_limit" : PLAYER_NAME_MAX_LEN, # PLAYER_NAME_MAX_LEN declared in script dictionary of ui.py as chr.PLAYER_NAME_MAX_LEN

    Which is a constant from module chr, initialized in PythonCharacterModule.cpp and the variable is declared in a enum of StdAfx.h.

    • Srcs/Client/UserInterface/StdAfx.h
    // Search for:
    	PLAYER_NAME_MAX_LEN = 12,
    // Replace with:
    	PLAYER_NAME_MAX_LEN = CHARACTER_NAME_MAX_LEN, // 24

     

    • Love 1
  3. Wikipedia has a API included, you can play with it.

    MediaWiki docs:

    Some examples:

    You've to install the requests library first one.

    pip install requests
    # Installing collected packages: certifi, chardet, urllib3, idna, requests
    # Successfully installed certifi-2019.3.9 chardet-3.0.4 idna-2.8 requests-2.22.0 urllib3-1.25.2

    How to use:

    This is the hidden content, please

    • Metin2 Dev 29
    • Eyes 1
    • Confused 3
    • Good 18
    • Love 2
    • Love 30
  4. CLICK FOR VIDEO

    • Server\src\game\src\DragonSoul.h
    //1.1) Search for:
    	bool	DragonSoulItemInitialize(LPITEM pItem);
    //1.2) Add after:
    	bool	AreActivedAllSlotsDragonSoulByPage(const LPCHARACTER ch, const BYTE bPageIndex = DRAGON_SOUL_DECK_0) const;
    • Server\src\game\src\DragonSoul.cpp
    //1.1) Search for:
    BYTE GetStrengthIdx(DWORD dwVnum)
    {
    	return (dwVnum / 10) % 10;
    }
    //1.2) Add after:
    bool DSManager::AreActivedAllSlotsDragonSoulByPage(const LPCHARACTER ch, const uint8_t bPageIndex) const
    {
    	// Check if all the slots are actived in a specific page of dragon soul - 18.05.2019 [Vegas]
    	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 iStartSlotIndex = WEAR_MAX_NUM + (bPageIndex * DS_SLOT_MAX);
    	const uint8_t iEndSlotIndex = iStartSlotIndex + DS_SLOT_MAX;
    	
    	BYTE bSlotActive = 0;
    	for (uint8_t iSlotIndex = iStartSlotIndex; iSlotIndex < iEndSlotIndex; ++iSlotIndex) // {0: 32-38, 1: 38-44}
    	{
    		const LPITEM pkItem = ch->GetWear(iSlotIndex);
    		if (pkItem && pkItem->IsDragonSoul())
    		{
    			if (IsTimeLeftDragonSoul(pkItem) && IsActiveDragonSoul(pkItem))
    				++bSlotActive;
    		}
    	}
    
    	return (bSlotActive == DS_SLOT_MAX);
    }
    • How-To-Use-Example:
    #include "DragonSoul.h"
      
    if (DSManager::instance().AreActivedAllSlotsDragonSoulByPage(ch, DRAGON_SOUL_DECK_0))
    {
    	ch->ChatPacket(CHAT_TYPE_INFO, "DragonSoul: You've all the dragon souls active in page 1.");
    	// do something
    }
    
    if (DSManager::instance().AreActivedAllSlotsDragonSoulByPage(ch, DRAGON_SOUL_DECK_1))
    {
    	ch->ChatPacket(CHAT_TYPE_INFO, "DragonSoul: You've all the dragon souls active in page 2.");
    	// do something
    }

    The rest is up to you how you give a bonus or something, you've the function which do the check.

    • Love 5
  5. With this right the guild members can use during a guild war guild skills. It should be taken that the guild skills only encompass each the triggering player. 
    Anyone who will benefit from the guild skills in guild wars, therefore must be set to the right.
    With each level up the guild gets a skill point for the guild skills well as space for two additional members and 100 dragon ghost. 
    The currently highest achievable level is at 20.

    Guild_Skills.png

    Guild skills

    • Per guild level you can invest a point in a guild skill, but a maximum of 7 points (Master) per skill.
    • Since the maximum guild level is 20, you can only have 2 master skills. The last skill will then only 5 points.
    • To use a guild skill is needed but some of the dragon ghost. This however will not charge all by itself, it must be filled with 100 Yang per dragon ghost.

    Active

    • Active Guild skills can be used only in guild wars. But the bonus is only effective for the triggering player.
    • Popular with all Class is "Rage of Dragon God" and "Casting Aid" because it accelerates all skills.
    • Other guild skills are very class dependent in their importance.

    Passive

    • Passive Guild Skills are not yet implemented in the game.

    Blood_Of_Dragon_God.png - It increases Max HP of all guild members for a period of time .

    Benediction_Of_Dragon_God.png - It increases Max SP of all guild members for a period of time .

    Holy_Armour.png - It increases defense of all guild members for a period of time .

    Acceleration.png - It increases attack and moving speed of all guild members for a period of time .

    Rage_Of_Dragon_God.png - It increases critical hit chances of all guild members for a period of time .

    Casting_Aid.png - It decreases cool down time (casting speed) of all guild members for a period of time .

     

    Skill Bonus level 1 level 2 level 3 level 4 level 5 level 6 level 7
    Blood Of Dragon God.png Blood of Dragon God

    (Duration: 600 sec).

    HP 2% 5% 8% 12% 14% 17% 20%
    Benediction Of Dragon God.png Benediction of Dragon God

    (Duration: 600 sec).

    SP 2% 5% 8% 12% 14% 17% 20%
    Holy Armour.png Holy Armour

    (Duration: 480 sec).

    DEF 1.4% 2.9% 4.3% 5.7% 7.1% 8.5% 10%
    Acceleration.png Acceleration

    (Duration: 480 sec).

    Attack Speed

    and Motion

    4.3% 8.6% 12.9% 17.2% 21.5% 25.7% 30%
    Rage Of Dragon God.png Rage of Dragon God

    (Duration: 480 sec).

    Critical

    Chance

    7% 14% 21% 28% 35% 42% 50%
    Casting Aid.png Casting Aid

    (Duration: 480 sec).

    Casting Speed 7% 14% 21% 28% 35% 42% 50%
    • Metin2 Dev 1
    • Good 1
    • Love 2
  6. 1 hour ago, Thundernatsu said:

    help 

      Reveal hidden contents
      Reveal hidden contents

    0512 14:23:53297 :: 
    ui.py(line:3196) LoadScriptFile
    system.py(line:197) execfile
    system.py(line:168) Run
    uiscript/systemoptiondialog.py(line:316) <module>

    LoadScriptFile!!!!!!!!!!!!!! - <type 'exceptions.TypeError'>:tuple indices must be integers, not str

    0512 14:23:53297 :: ============================================================================================================
    0512 14:23:53297 :: Abort!!!!


    0512 14:23:53299 :: 
    uiSystemOption.py(line:76) __Load_LoadScript
    ui.py(line:3213) LoadScriptFile
    exception.py(line:36) Abort

    System.OptionDialog.__Load_LoadScript - <type 'exceptions.SystemExit'>:

    0512 14:23:53299 :: ============================================================================================================
    0512 14:23:53299 :: Abort!!!!

     

     

    Your children item from dictionary is a tuple, not a list.

    #1.1) Replace:
    window["children"][0]["children"] = window["children"][0]["children"] + [
    #1.2) With:
    window["children"][0]["children"] += (
      
    #2.1) Replace:
    		},]
    #2.2) With:
    		},)
    • Metin2 Dev 1
    • Love 1
  7. Good idea, but the python part is a bit too much, 200 lines for 5-6 functions.

    2 hours ago, WLsj24 said:
    Spoiler
    
    
    				self.effectLevelButtonList.append(GetObject("effect_level1"))
    				self.effectLevelButtonList.append(GetObject("effect_level2"))
    				self.effectLevelButtonList.append(GetObject("effect_level3"))
    				self.effectLevelButtonList.append(GetObject("effect_level4"))
    				self.effectLevelButtonList.append(GetObject("effect_level5"))
    
    				self.privateShopLevelButtonList.append(GetObject("privateShop_level1"))
    				self.privateShopLevelButtonList.append(GetObject("privateShop_level2"))
    				self.privateShopLevelButtonList.append(GetObject("privateShop_level3"))
    				self.privateShopLevelButtonList.append(GetObject("privateShop_level4"))
    				self.privateShopLevelButtonList.append(GetObject("privateShop_level5"))
    
    				self.dropItemLevelButtonList.append(GetObject("dropItem_level1"))
    				self.dropItemLevelButtonList.append(GetObject("dropItem_level2"))
    				self.dropItemLevelButtonList.append(GetObject("dropItem_level3"))
    				self.dropItemLevelButtonList.append(GetObject("dropItem_level4"))
    				self.dropItemLevelButtonList.append(GetObject("dropItem_level5"))

     

    Can be like:

    Spoiler
    
    for i in xrange(1, GRAPHIC_LEVEL_MAX_NUM + 1):
    	self.effectLevelButtonList.append(GetObject("effect_level%d" % i))
    	self.privateShopLevelButtonList.append(GetObject("privateShop_level%d" % i))
    	self.dropItemLevelButtonList.append(GetObject("dropItem_level%d" % i))

    _____________________________________________________________

    2 hours ago, WLsj24 said:
    Spoiler
    
    
    			self.effectLevelButtonList[0].SAFE_SetEvent(self.__OnClickEffectLevel1Button)
    			self.effectLevelButtonList[1].SAFE_SetEvent(self.__OnClickEffectLevel2Button)
    			self.effectLevelButtonList[2].SAFE_SetEvent(self.__OnClickEffectLevel3Button)
    			self.effectLevelButtonList[3].SAFE_SetEvent(self.__OnClickEffectLevel4Button)
    			self.effectLevelButtonList[4].SAFE_SetEvent(self.__OnClickEffectLevel5Button)
    
    			self.privateShopLevelButtonList[0].SAFE_SetEvent(self.__OnClickPrivateShopLevel1Button)
    			self.privateShopLevelButtonList[1].SAFE_SetEvent(self.__OnClickPrivateShopLevel2Button)
    			self.privateShopLevelButtonList[2].SAFE_SetEvent(self.__OnClickPrivateShopLevel3Button)
    			self.privateShopLevelButtonList[3].SAFE_SetEvent(self.__OnClickPrivateShopLevel4Button)
    			self.privateShopLevelButtonList[4].SAFE_SetEvent(self.__OnClickPrivateShopLevel5Button)
    
    			self.dropItemLevelButtonList[0].SAFE_SetEvent(self.__OnClickDropItemLevel1Button)
    			self.dropItemLevelButtonList[1].SAFE_SetEvent(self.__OnClickDropItemLevel2Button)
    			self.dropItemLevelButtonList[2].SAFE_SetEvent(self.__OnClickDropItemLevel3Button)
    			self.dropItemLevelButtonList[3].SAFE_SetEvent(self.__OnClickDropItemLevel4Button)
    			self.dropItemLevelButtonList[4].SAFE_SetEvent(self.__OnClickDropItemLevel5Button)
    
    			self.petStatusButtonList[0].SAFE_SetEvent(self.__OnClickPetStatusOnButton)
    			self.petStatusButtonList[1].SAFE_SetEvent(self.__OnClickPetStatusOffButton)
    
    			self.npcNameStatusButtonList[0].SAFE_SetEvent(self.__OnClickNpcNameStatusOnButton)
    			self.npcNameStatusButtonList[1].SAFE_SetEvent(self.__OnClickNpcNameStatusOffButton)
    
    		# Effect
    		def __SetEffectLevel(self, index):
    			self.__ClickRadioButton(self.effectLevelButtonList, index)
    			self.effectLevel=index
    
    		def __OnClickEffectLevel1Button(self):
    			self.__SetEffectLevel(0)
    
    		def __OnClickEffectLevel2Button(self):
    			self.__SetEffectLevel(1)
    
    		def __OnClickEffectLevel3Button(self):
    			self.__SetEffectLevel(2)
    
    		def __OnClickEffectLevel4Button(self):
    			self.__SetEffectLevel(3)
    
    		def __OnClickEffectLevel5Button(self):
    			self.__SetEffectLevel(4)
    
    		# PrivateShop
    		def __SetPrivateShopLevel(self, index):
    			self.__ClickRadioButton(self.privateShopLevelButtonList, index)
    			self.privateShopLevel=index
    
    		def __OnClickPrivateShopLevel1Button(self):
    			self.__SetPrivateShopLevel(0)
    
    		def __OnClickPrivateShopLevel2Button(self):
    			self.__SetPrivateShopLevel(1)
    
    		def __OnClickPrivateShopLevel3Button(self):
    			self.__SetPrivateShopLevel(2)
    
    		def __OnClickPrivateShopLevel4Button(self):
    			self.__SetPrivateShopLevel(3)
    
    		def __OnClickPrivateShopLevel5Button(self):
    			self.__SetPrivateShopLevel(4)
    
    		# DropItem
    		def __SetDropItemLevel(self, index):
    			self.__ClickRadioButton(self.dropItemLevelButtonList, index)
    			self.dropItemLevel=index
    
    		def __OnClickDropItemLevel1Button(self):
    			self.__SetDropItemLevel(0)
    
    		def __OnClickDropItemLevel2Button(self):
    			self.__SetDropItemLevel(1)
    
    		def __OnClickDropItemLevel3Button(self):
    			self.__SetDropItemLevel(2)
    
    		def __OnClickDropItemLevel4Button(self):
    			self.__SetDropItemLevel(3)
    
    		def __OnClickDropItemLevel5Button(self):
    			self.__SetDropItemLevel(4)
    
    		# PetStatus
    		def __OnClickPetStatusOnButton(self):
    			systemSetting.SetPetStatusFlag(True)
    			self.RefreshPetStatus()
    
    		def __OnClickPetStatusOffButton(self):
    			systemSetting.SetPetStatusFlag(False)
    			self.RefreshPetStatus()
    
    		# NpcNameStatus
    		def __OnClickNpcNameStatusOnButton(self):
    			systemSetting.SetNpcNameStatusFlag(True)
    			self.RefreshNpcNameStatus()
    
    		def __OnClickNpcNameStatusOffButton(self):
    			systemSetting.SetNpcNameStatusFlag(False)
    			self.RefreshNpcNameStatus()

     

    Can be like:

    Spoiler
    
    for i in xrange(GRAPHIC_LEVEL_MAX_NUM):
    	self.effectLevelButtonList[i].SAFE_SetEvent(self.__OnClickEffectLevelButton, i)
    	self.privateShopLevelButtonList[i].SAFE_SetEvent(self.__OnClickPrivateShopLevelButton, i)
    	self.dropItemLevelButtonList[i].SAFE_SetEvent(self.__OnClickDropItemLevelButton, i)
    	
    for i in xrange(2):
    	self.petStatusButtonList[i].SAFE_SetEvent(self.__OnClickPetStatusButton, bool(i))
    	self.npcNameStatusButtonList[i].SAFE_SetEvent(self.__OnClickNpcNameStatusButton, bool(i))
    
    # Effect
    def __OnClickEffectLevelButton(self, index):
    	self.__ClickRadioButton(self.effectLevelButtonList, index)
    	self.effectLevel=index
    
    # PrivateShop
    def __OnClickPrivateShopLevelButton(self, index):
    	self.__ClickRadioButton(self.privateShopLevelButtonList, index)
    	self.privateShopLevel=index
    
    # DropItem
    def __OnClickDropItemLevelButton(self, index):
    	self.__ClickRadioButton(self.dropItemLevelButtonList, index)
    	self.dropItemLevel=index
    
    # PetStatus
    def __OnClickPetStatusButton(self, flag):
    	systemSetting.SetPetStatusFlag(flag)
    	self.RefreshPetStatus()
    
    # NpcNameStatus
    def __OnClickNpcNameStatusButton(self, flag):
    	systemSetting.SetNpcNameStatusFlag(flag)
    	self.RefreshNpcNameStatus()

     

    Btw, for rest you can take a look how they're rended and do something like:

    Here you can hide the 'terrain', 'object', 'cloud', 'water', 'tree', and you can disable the effects and more too if you take a look inside of GameLib.

    Over 1.5 year ago i extended a bit my release but didn't had enough time to post it, i'll update the repository with the new code when i'll have time to finish it.

    That feature allow you to hide specific effects, tree, bulding by property crc or name (not finished) and write them into files like:

    graphic_mask/building.txt

    general_obj_stone14
    ob-b1-005-woodbarrel
    landmark_statuestone
    B_general_obj_40
    general_obj_jar_yellow01

    graphic_mask/effect.txt

    8182371290
    1003918098
    volcano_greatsmoke.mse
    warpgate01
    fall_7
    fire_general_obj_charcoal.mse
    • PythonGraphicMask.cpp
    Spoiler
    
    /*********************************************************************
    * title_name		: Graphic Mask
    * date_created		: 2018.04.21
    * filename			: PythonGraphicMask.cpp
    * author			: VegaS
    * version_actual	: Version 1.0
    */
    
    #include "stdafx.h"
    #ifdef ENABLE_GRAPHIC_MASK
    #include "PythonGraphicMask.h"
    #include "PythonSystem.h"
    #include "../gamelib/MapOutDoor.h"
    #include "../gamelib/MapType.h"
    
    CPythonGraphicMask::CPythonGraphicMask()
    {
    	Initialize(PROPERTY_TYPE_NONE, "graphic_mask/default.txt");
    	Initialize(PROPERTY_TYPE_TREE, "graphic_mask/tree.txt");
    	Initialize(PROPERTY_TYPE_BUILDING, "graphic_mask/building.txt");
    	Initialize(PROPERTY_TYPE_EFFECT, "graphic_mask/effect.txt");
    }
    
    CPythonGraphicMask::~CPythonGraphicMask()
    {
    	Destroy();
    }
    
    void CPythonGraphicMask::Initialize(const BYTE bPropertyType, const char * c_pszFileName)
    {
    	m_vecMaskObjectCRC[bPropertyType].clear();
    
    	FILE * fp = fopen(c_pszFileName, "r");
    	if (!fp)
    	{
    		Tracef("Can't open file %s.", c_pszFileName);
    		return;
    	}
    	
    	Tracef("-------------------- START PARSING --------------------");
    	Tracef("Read with successfully %s!", c_pszFileName);
    
    	char line[256];
    	while (fgets(line, sizeof(line) - 1, fp))
    	{
    		const auto dwCRC = strtoul(line, NULL, 0);
    		m_vecMaskObjectCRC[bPropertyType].push_back(dwCRC);
    	}
    	
    	TraceError("-------------------- END PARSING --------------------");
    }
    
    void CPythonGraphicMask::Destroy()
    {
    	for (size_t i = 0; i < PROPERTY_TYPE_MAX_NUM; ++i)
    		m_vecMaskObjectCRC[i].clear();
    }
    
    bool CPythonGraphicMask::IsEnabled(const BYTE bPropertyType) const
    {
    	if (bPropertyType >= PROPERTY_TYPE_MAX_NUM)
    		return false;
    	
    	switch (bPropertyType)
    	{
    		case prt::PROPERTY_TYPE_TREE:
    			bPropertyType = CMapOutdoor::PART_TREE;
    			break;
    		case prt::PROPERTY_TYPE_BUILDING:
    			bPropertyType = CMapOutdoor::PART_OBJECT;
    			break;
    			
    		case prt::PROPERTY_TYPE_EFFECT:
    			bPropertyType = CMapOutdoor::PART_EFFECT;
    			break;
    	}
    	
    	const CPythonSystem & rkSystem = CPythonSystem::Instance();
    	return rkSystem.GetGraphicMaskPart(bPropertyType);
    }
    
    bool CPythonGraphicMask::GetObjectByCRC(const BYTE bPropertyType, const DWORD dwCRC) const
    {
    	if (bPropertyType >= PROPERTY_TYPE_MAX_NUM)
    		return false;
    
    	return std::find(m_vecMaskObjectCRC[bPropertyType].begin(), m_vecMaskObjectCRC[bPropertyType].end(), dwCRC) != m_vecMaskObjectCRC[bPropertyType].end());;
    }
    #endif

     

    • PythonGraphicMask.h
    Spoiler
    
    #pragma once
    class CPythonGraphicMask : public CSingleton<CPythonGraphicMask>
    {
    	public:
    		CPythonGraphicMask();
    		virtual ~CPythonGraphicMask();
    	
    		void	Initialize(const BYTE bPropertyType, const char * c_pszFileName);
    		void	Destroy();
    		
    		bool	IsEnabled(const BYTE bPropertyType) const;
    		bool	GetObjectByCRC(const BYTE bPropertyType, const DWORD dwCRC) const;
    		
    		enum 
    		{
    			PROPERTY_TYPE_NONE,
    			PROPERTY_TYPE_TREE,
    			PROPERTY_TYPE_BUILDING,
    			PROPERTY_TYPE_EFFECT,
    			PROPERTY_TYPE_MAX_NUM,
    		};
    
    	protected:
    		std::vector<DWORD> m_vecMaskObjectCRC[PROPERTY_TYPE_MAX_NUM];
    };

     

     

     

     

    • Metin2 Dev 9
    • Angry 1
    • Sad 1
    • Good 1
    • Love 13
  8. Btw, instead of removing the calculation, i would set a MIN-MAX value for duration of stun flag.

    So, let's take a look how the duration is calculated for POINT_PARTY_BUFFER_BONUS.

    iDur += m_pkChr->GetPoint(POINT_PARTY_BUFFER_BONUS);
    Spoiler
    
    int	CHARACTER::GetSkillPowerByLevel(int level, bool bMob) const
    {
    	return CTableBySkill::instance().GetSkillPowerByLevelFromType(GetJob(), GetSkillGroup(), MINMAX(0, level, SKILL_MAX_LEVEL), bMob);
    }
    
    int CTableBySkill::GetSkillPowerByLevelFromType(int job, int skillgroup, int skilllevel, bool bMob) const
    {
    	if (bMob)
    		return m_aiSkillPowerByLevelFromType[0][skilllevel];
    
    	if (job >= JOB_MAX_NUM || skillgroup == 0)
    		return 0;
    
    	int idx = (job * 2) + (skillgroup - 1);
    	return m_aiSkillPowerByLevelFromType[idx][skilllevel];
    }

     

    m_iLeadership = Leader skill ship skill level which is increased by (book vnum: 50301, 50302, 50303)

    Let's take a example, a warrior, skill group 1.

    CHARACTER::GetSkillPowerByLevel << CTableBySkill::GetSkillPowerByLevelFromType

    • idx = 0 * 2 + 1 - 1 = 0
    • skilllevel = m_iLeadership
    • m_iLeadership = 40 (Skill Perfect Master)
    // 0 5 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 50 52 54 56 58 60 63 66 69 72 82 85 88 91 94 98 102 106 110 115 125 125 125 125 125
    m_aiSkillPowerByLevelFromType[0][40] = 125
    • int iBonus = (int) (5 + 45 * k);
    • float k = (float) ch->GetSkillPowerByLevel( MIN(SKILL_MAX_LEVEL, m_iLeadership ) ) / 100.0f;
    • k = 125 / 100 = 1.25
    • iBonus = 5 + 45 1.25 = 56.5 (converted to integer will be 61) 
    leadership Set as attacker Set as berserker Set as melee Set as blocker Set as defender Set as wizzard
    Image Set as attacker.jpg Set as berserker.jpg Set as melee.jpg Set as blocker.jpg Set as defender.jpg Set as wizzard.jpg
    G1 +59 AP +5 AS MaxHP +1.239 Length of spell: +41 From P on From G6 on
    G2 +61 AP +5 AS MaxHP +1.282 Length of spell: +43 From P on From G6 on
    G3 +62 AP +5 AS MaxHP +1.326 Length of spell: +44 From P on From G6 on
    G4 +64 AP +5 AS MaxHP +1.369 Length of spell: +45 From P on From G6 on
    G5 +66 AP +5 AS MaxHP +1.413 Length of spell: +47 From P on From G6 on
    G6 +68 AP +5 AS MaxHP +1.471 Length of spell: +49 From P on MaxMP +613
    G7 +71 AP +6 AS MaxHP +1.529 Length of spell: +50 From P on MaxSP +637
    G8 +73 AP +6 AS MaxHP +1.587 Length of spell: +52 From P on MaxSP +661
    G9 +76 AP +6 AS MaxHP +1.645 Length of spell: +54 From P on MaxSP +685
    G10 +79 AW +6 AG MaxHP +1.717 Length of spell: +56 From P on MaxSP +715
    P +85 AW +7 AG MaxHP +1.862 Length of spell: +61 Defence: +42 MaxSP +775
    Quote

    (STUN can to last kinda 70 seconds)

    That means 61 seconds of duration are getted from the party role bonus, so you can set a limit.

    				// Set a min-max value for party role bonus just when flag is stun.
    				const uint16_t iMaxStunDuration = 30;
    				if (IS_SET(m_pkSk->dwFlag, SKILL_FLAG_STUN))
    				{
    					iDur += MINMAX(static_cast<int>(m_pkSk->kDurationPoly2.Eval()), m_pkChr->GetPoint(POINT_PARTY_BUFFER_BONUS), iMaxStunDuration);
    				}
    				else
    				{
    					// SLOW, FIRE_CONT, POISON, BLEEDING will still be working with the default calculation.
    					iDur += m_pkChr->GetPoint(POINT_PARTY_BUFFER_BONUS);
    				}

     

    • Metin2 Dev 3
    • Love 3
  9. I didn't tested that "bug", but you can disable the calculation from char_skill.cpp. (not tested)

    				iDur += m_pkChr->GetPoint(POINT_PARTY_BUFFER_BONUS);

    By change it with:

    				// Ignore the party role bonus just for stun flag.
    				// SLOW, FIRE_CONT, POISON, BLEEDING will still be working.
    				if (!IS_SET(m_pkSk->dwFlag, SKILL_FLAG_STUN))
    					iDur += m_pkChr->GetPoint(POINT_PARTY_BUFFER_BONUS);

     

    • Love 2
  10. 4 hours ago, Kori said:
    
    BWords = text.replace(v, '****')
    
    #text = text.replace(word, word[0] + "*" * (len(word) - 2) + word[-1])
    text = text.replace(word, '{first}{filter_char}{last}'.format(
    					first = word[0], filter_char = "*" * (len(word) - 2), last = word[-1]))
    >>> Don't call me a l******y. 

    With that type of replace you'll get asterisks by the length of your specific word, and will show just the first and the last character.

    @avertuss Btw you already have CInsultChecker::FilterInsult  (which is used just for server-2-client TPacketGCChat), you can modify/duplicate the functions which are related about it and return the specific string which is detected from sentence and replace it with that method in python.

  11. On 11/17/2018 at 10:03 PM, Chookez said:

    Successsfully resolved!

    Please delete the topic.

    (2.5) Questions & Answers specific rules

    • Don't modify your thread (or reply to it) to mark it solved, and not explain the solution to the issue.

    Srcs/Server/game/src/input_main.cpp

    //Search in void CInputMain::SafeboxCheckin(LPCHARACTER ch, const char * c_pData) for:
    	if( IS_SET(pkItem->GetAntiFlag(), ITEM_ANTIFLAG_SAFEBOX) )
    	{
    		ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<창고> 이 아이템은 넣을 수 없습니다."));
    		return;
    	}
    //Add after:
    	if (ch->IsDead() && pkItem->IsEquipped())
    	{
    		ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("SAFEBOX_CANNOT_ADD_EQUIPPED_ITEM_WHILE_IS_DEAD"));
    		return;
    	}
    	
    	if (pkItem->IsDragonSoul())
    	{
    		ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("SAFEBOX_CANNOT_ADD_ITEM_DRAGON_SOUL"));
    		return;
    	}

     

  12. On 1/7/2019 at 12:56 AM, Hust said:

    Still nothing

    That's the correct way.

    int affect_stun(lua_State * L)
    {
    	const uint32_t lDuration = 30; // seconds
      	const LPCHARACTER ch = CQuestManager::instance().GetCurrentCharacterPtr();
    	if (ch)
    		ch->AddAffect(AFFECT_STUN, POINT_NONE, 0, AFF_STUN, lDuration, 0, true);
      	return 0;
    }

     

    • Love 2
  13. On 4/29/2019 at 12:16 AM, Syriza said:

    How can i use the keys f1, f2, f3, f4 for choosing the saved account data? Would be amazing if someone help 

    Something I wrote in a hurry.

    • introLogin.py (add it to the end of the lines)

    This is the hidden content, please

    • Metin2 Dev 30
    • Eyes 1
    • Think 1
    • Confused 1
    • Scream 1
    • Good 8
    • Love 34
  14. 1 hour ago, Aioria said:

    could be because i'm using python 2.2? I can't get it work with 2.2?

    I can't read your file because atm i'm at phone,  you're not using the same minor version of python interpreter, the pyc (compiled bytecode) module was compiled for example 2.7 vs. 2.2, but this can't be the real problem since you don't get Bad magic number.

    1 hour ago, Aioria said:

    vUH4pSV.png

    So i assume your problem is with the sequence (sequence of the elements to be joined) from join method.
    Basically there's a list comprehensions, list comprehensions provide a concise way to create lists.

    new_list = []
    for item in old_list:
        new_list.append(item)

    You can obtain the same thing using list comprehension:

    new_list = [item for item in old_list]

    The list comprehension always returns a result list.

    # Now
    return ''.join(random.choice(letters) for i in range(length))
    # After
    return ''.join([random.choice(letters) for i in range(length)])

    That's because python22 isn't so smart. (18 years ago)

    • Love 1
  15. Ok, there're many guys which want that and wroted me in PM, i'll leave the code here.

    • root/uiInventory.py
    Spoiler
    
    #1.1) Search for:
    	def RefreshItemSlot(self):
    		self.RefreshBagSlotWindow()
    		self.RefreshEquipSlotWindow()
    #1.1) Replace with:
    	def RefreshItemSlot(self):
    		self.RefreshBagSlotWindow()
    		self.RefreshEquipSlotWindow()
    		self.RefreshCostumeSlot()
    		
    #1.2) Search for:
    	def SetItemToolTip(self, tooltipItem):
    		self.tooltipItem = tooltipItem
    		
    #1.2) Add after:
    	def RefreshCostumeSlot(self):
    		for i in xrange(item.COSTUME_SLOT_COUNT):
    			slotNumber = item.COSTUME_SLOT_START + i
    			self.wndEquip.SetItemSlot(slotNumber, player.GetItemIndex(slotNumber), 0)
    		
    #1.3) Search in def RefreshEquipSlotWindow(self) for:
    		self.wndEquip.RefreshSlot()
    		
    #1.3) Add before:
    		self.RefreshCostumeSlot()

     

    • locale/en/ui/InventoryWindow.py
    Spoiler
    
    #1.1) Search for:
    import item
    #1.1) Add after:
    COSTUME_START_INDEX = item.COSTUME_SLOT_START
    
    #1.2) Search in "slot" : ( for:
    	{"index":item.EQUIPMENT_BELT, "x":39, "y":106, "width":32, "height":32},
    #1.2) Add after:
    	#{"index":COSTUME_START_INDEX+0, "x":80, "y":3, "width":32, "height":32}, # Costume - Body
    	#{"index":COSTUME_START_INDEX+1, "x":80, "y":3, "width":32, "height":32}, # Costume - Hair
    	{"index":COSTUME_START_INDEX+2, "x":80, "y":3, "width":32, "height":32}, # Costume - Acce

     

    • Metin2 Dev 1
    • Love 5
×
×
  • 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.