-
Posts
21 -
Joined
-
Last visited
-
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by Reached
-
-
6 hours ago, martysama0134 said:
Another annoying issue is the repeated commands. This solves that issue:
def __PushLastSentenceStack(self, text): global ENABLE_LAST_SENTENCE_STACK if not ENABLE_LAST_SENTENCE_STACK: return if len(text) <= 0: return if text in chatStack: #remove duplicated elements and push the new one on top chatStack.remove(text) if len(chatStack) > LAST_SENTENCE_STACK_SIZE: chatStack.pop(0) chatStack.append(text)
Thank you for your contribution.
-
# Search ENABLE_CHAT_COMMAND = True # Add below chatStack = [] LAST_SENTENCE_STACK_SIZE = 32 # Search def __PrevLastSentenceStack(self): # Change whole function def __PrevLastSentenceStack(self): if self.lastSentencePos < len(chatStack): self.lastSentencePos += 1 lastSentence = chatStack[-self.lastSentencePos] self.SetText(lastSentence) self.SetEndPosition() # Search def __NextLastSentenceStack(self): # Change whole function def __NextLastSentenceStack(self): if self.lastSentencePos > 1: self.lastSentencePos -= 1 lastSentence = chatStack[-self.lastSentencePos] self.SetText(lastSentence) self.SetEndPosition() # Search def __PushLastSentenceStack(self, text): # Change whole function. def __PushLastSentenceStack(self, text): global ENABLE_LAST_SENTENCE_STACK if not ENABLE_LAST_SENTENCE_STACK: return if len(text) <= 0: return if len(chatStack) > LAST_SENTENCE_STACK_SIZE: chatStack.pop(0) chatStack.append(text)
It ensures that the saved message in the chat is not lost after teleporting.
- 5
- 2
- 1
- 2
-
Thank you for sharing this tutorial, for the Set function error
NetPacketHeaderMap.h
//Add under the SPacketType struct TPacketType& createPacketType(int iSize = 0, bool bFlag = false) { return *(new TPacketType(iSize, bFlag)); }
and replace all the
//replace CNetworkPacketHeaderMap::TPacketType( //to this createPacketType(
i solve it like this without any errors.
-
Preview -> https://metin2.download/video/H3qHG80L4b7O2ZOrKZGsYswGL8izIeov/.mp4
* When extracting a map from a files, it outputs all objects belonging to that map.
* Rarely, some dds files are not put in the same folder with their gr2, so some objects may have problems with their textures. You can take the textures with the problem by hand by opening the gr2.
* There is a video on how to do it in the Github README
- 40
- 1
- 8
- 3
- 13
-
12 minutes ago, Syreldar said:
A couple heads-up:
- You don't need to clear a server_timer inside its own trigger unless it's a server_loop_timer. Normal timers get cleared upon triggering.
- You could've just used another dungeon flag to get the state, instead of using c++ shenanigans. The immunity part is also easily achievable without any source-sided input.
define FLOOR2_METINSTONE_VNUM 42069 define FLOOR2_METINSTONE_SPAWN_LOCAL_X 333 define FLOOR2_METINSTONE_SPAWN_LOCAL_Y 666 define FLOOR2_METINSTONE_HP_THRESHOLD 50 define FLOOR2_REGEN_PATH "example_dungeon/x.txt" define TIME_TO_WARP_NEXT 10 function new_zodiac_notice(str) d.zodiac_notice_clear(); d.zodiac_notice(str); end -- function when dungeon_warp_to_2floor.server_timer begin if (d.select(get_server_timer_arg())) then d.setf("level", 2); d.setf("2floor_metinstone_vid", d.spawn_mob(FLOOR2_METINSTONE_VNUM, FLOOR2_METINSTONE_SPAWN_LOCAL_X, FLOOR2_METINSTONE_SPAWN_LOCAL_Y)); d.set_unique("2floor_metinstone", d.getf("2floor_metinstone_vid")); server_loop_timer("dungeon_2floor_control_metinstone_hp", 2, get_server_timer_arg()) dungeon_name.new_zodiac_notice(string.format("<Floor 2 | Stage 1> Bring the Metinstone down to %d%% HPs", FLOOR2_METINSTONE_HP_THRESHOLD)) end -- if end -- when when dungeon_2floor_control_metinstone_hp.server_timer begin if (d.select(get_server_timer_arg())) then if (d.unique_get_hp_perc("2floor_metinstone") <= FLOOR2_METINSTONE_HP_THRESHOLD) then clear_server_timer("dungeon_2floor_control_metinstone_hp", get_server_timer_arg()); npc.set_vid_damage_mul(d.getf("2floor_metinstone_vid"), 0.0001); d.regen_file(FLOOR2_REGEN_PATH); server_loop_timer("dungeon_2floor_control_monster_count", 2, d.get_map_index()); dungeon_name.new_zodiac_notice("<Floor 2 | Stage 2> Kill all the monsters") end -- if end -- if end -- when when dungeon_2floor_control_monster_count.server_timer begin if (d.select(get_server_timer_arg())) then if (d.count_monster() == 0) then clear_server_timer("dungeon_2floor_control_monster_count", get_server_timer_arg()); npc.set_vid_damage_mul(d.getf("2floor_metinstone_vid"), 1.0); dungeon_name.new_zodiac_notice("<Floor 2 | Stage 3> Destroy the Metinstone") end -- if end -- if end -- if when kill with npc.get_race() == FLOOR2_METINSTONE_VNUM and d.getf("level") == 2 begin d.clear_regen(); d.kill_all(); d.kill_all(); -- If there are resurrecting units. dungeon_name.new_zodiac_notice(string.format("<Floor 2 Completed> Warping to next floor in %d seconds..", TIME_TO_WARP_NEXT)) server_timer("dungeon_warp_to_3floor", TIME_TO_WARP_NEXT, d.get_map_index()); end -- when when dungeon_warp_to_3floor.server_timer begin if (d.select(get_server_timer_arg())) then d.setf("level", 3); -- end -- if end -- when
This snippet behaves exactly the same and does not require any C++ input.
Thank you for your suggestions and corrections.
-
I like Aeldra's Nilay Dungeon so I made it.
Allows you to hit a metinstone up to 50% health and start a stage within the stage.
The logic is simple, do this to bosses etc. You can also adapt it.
I added an example dungeon quest usage, you can easily understand the logic.
Spoiler- 74
- 14
- 2
- 35
-
-
It compares 2 diffrent locale_game (One is the language you want to convert and the other is the original)
You can also use as locale_interface
- 96
- 1
- 1
- 1
- 2
- 1
- 32
- 1
- 5
- 41
-
-
2 minutes ago, xTryhard said:
ofc you set the weapon. in your code you use this
item2->SetForceAttribute(idx, 72, value);
as third parameter you use value.
anyway this is the correct if statement :
if (item2->GetAttributeValue(idx) >= 50 && item2->GetAttributeValue(idx) <= 200) { item2->SetForceAttribute(idx, 72, value); }
yes, i shared
-
9 hours ago, Xovarto said:
It somehow is not adding the avg value.
Even tho i have 55avg on weapon it says i need 50-150avg.
Do i need to add further code beside the on u posted?
Can you try like this
else if (item->GetVnum() == 75891) { if ((item2->GetType() == ITEM_WEAPON) && item2->HasAttr(72)) { int16_t idx = item2->FindAttribute(72); int32_t value = item2->GetAttributeValue(idx)+1; if ((150 > item2->GetAttributeValue(idx)) && (item2->GetAttributeValue(idx) >= 50)) { item2->SetForceAttribute(idx, 72, value); } else { ChatPacket(CHAT_TYPE_INFO, "You can only use this item which is between 80-200 avg."); return false; } } else { ChatPacket(CHAT_TYPE_INFO, "You can only use this item on weapons with average damage."); return false; } }
4 hours ago, xTryhard said:if you want just to increase a value from a bonus you dont have to change anything in item_proto
the bonus value is signed 16 bit that means you can have max. 32767 without change anything
item2->SetForceAttribute(idx, 72, 32767);
this function will do it
also if you want to increase a value by 1 use the ++ increment operator instead of using +1
int32_t value = item2->GetAttributeValue(idx); ++value;
Uhm no, I don't want to get the value 32767. I just want to increase an attribute type 150 by increasing value and this code does that. if you gonna do ++value, you'll increase by 1, and equals value to value+1. But you don't set it trough the weapon. You just declare a value by variable and you'll just increase value by 1.
-
Today I will share with you something simple.
char_item.cpp
// Add in the USE_CHANGE_ATTRIBUTE case else if (item->GetVnum() == 75891) { if ((item2->GetType() == ITEM_WEAPON) && item2->HasAttr(72)) { int16_t idx = item2->FindAttribute(72); int32_t value = item2->GetAttributeValue(idx)+1; if ((150 > item2->GetAttributeValue(idx)) && (item2->GetAttributeValue(idx) >= 50)) { item2->SetForceAttribute(idx, 72, value); } else { ChatPacket(CHAT_TYPE_INFO, "You can only use this item which is between 80-200 avg."); return false; } } else { ChatPacket(CHAT_TYPE_INFO, "You can only use this item on weapons with average damage."); return false; } }
item_names.txt
75891 Efsun Arttırma
item_proto.txt
75891 a_c ITEM_USE USE_CHANGE_ATTRIBUTE 1 ANTI_DROP | ANTI_SELL ITEM_STACKABLE | LOG NONE NONE 1000 0 0 0 0 LIMIT_NONE 0 LIMIT_NONE 0 APPLY_NONE 0 APPLY_NONE 0 APPLY_NONE 0 0 0 0 0 0 0 0 0 0
https://metin2.download/picture/sZNM9Bsys7hT70MZWwro3N9Y7t95aQfR/.gif
- 1
-
Thnx for release, btw they still steal xd.
- 1
-
Thank you.
-
On 2/15/2020 at 4:04 AM, blabla112 said:
didnt work, did everything, i think i messed something up in the mysql... i dont know how to put them there
It's work, after than adding codes open your mob_proto and for example
1093 (Lucifer) Add the RaceFlag ATT_NEWATTRTYPE
-
On 2/9/2020 at 1:18 PM, Raylee said:
I've revised your Syntax in the main post.
Please check if everything is correct.Best regards
RayleeThank you so much, everything is correct succesfully
-
Hello, i haven't seen a topic like this in the forum. I want to share it.
Firs of all we create own attr type with RaceFlag (Maybe in the following days i'll show you how to without RaceFlag)
Client Source:
GameLib:
ItemData.h
Spoiler// Search: enum EApplyTypes { // Add to Enum: APPLY_ATTBONUS_NEWATTRTYPE,
UserInterface:
PythonPlayerModule.cpp
Spoiler// Search: PyModule_AddIntConstant(poModule, "APPLY_ANTI_PENETRATE_PCT", CItemData::APPLY_ANTI_PENETRATE_PCT ); // Add: PyModule_AddIntConstant(poModule, "APPLY_ATTBONUS_NEWATTRTYPE", CItemData::APPLY_ATTBONUS_NEWATTRTYPE);
Packet.h
Spoiler// Search: enum EPointTypes { .... } // Add to Enum: POINT_ATTBONUS_NEWATTRTYPE,
Game Source:
common:
length.h
Spoiler// Search: enum ERaceFlags { // Add: RACE_FLAG_ATT_NEWATTRTYPE = (1 << /*Last number +1*/) // Search: enum EApplyTypes { // Add to Enum: APPLY_ATTBONUS_NEWATTRTYPE,
game:
char.h
Spoiler// Search: enum EPointTypes { // Add to Enum: POINT_ATTBONUS_NEWATTRTYPE,
char.cpp
Spoiler// Search: case POINT_RESIST_SHAMAN: // Add: case POINT_ATTBONUS_NEWATTRTYPE: // Search: case APPLY_NORMAL_HIT_DAMAGE_BONUS: // Add: case APPLY_ATTBONUS_NEWATTRTYPE:
cmd_general.cpp
Spoiler// Search: static const char* [...] switch (apply_number) { // ICINDE BUL case POINT_RESIST_SHAMAN: return LC_TEXT("¹«´ç°ø°Ý¿¡ %d%% ÀúÇ×"); // Add: case POINT_ATTBONUS_NEWATTRTYPE: return LC_TEXT("POINT_ATTBONUS_NEWATTRTYPE: %d%%");
cmd_gm.cpp
Spoiler// Search: tch->GetPoint(POINT_ATTBONUS_SHAMAN)); // Add in do_state command: ch->ChatPacket(CHAT_TYPE_INFO, " NEWATTRTYPE:%3d%%", tch->GetPoint(POINT_ATTBONUS_NEWATTRTYPE));
constants.cpp
Spoiler// Search: const TApplyInfo aApplyInfo[MAX_APPLY_NUM] = // Add in function: { POINT_ATTBONUS_NEWATTRTYPE, }, // APPLY_ATTBONUS_NEWATTRTYPE, // Search: TValueName c_aApplyTypeNames[] = // Search in this: { NULL, 0 } // Add above: { "ATT_NEWATTRTYPE", APPLY_ATTBONUS_NEWATTRTYPE },
battle.cpp
SpoilerpkVictim (It meanings of defendor) pkAttacker is attacker if we are adding Defence attr type from mobs we will add this func. if (pkAttacker->IsNPC() && pkVictim->IsPC()) or we are adding attack attr type to mobs we will add this func. if (pkAttacker->IsPC() && pkVictim->IsNPC()) Logic is this: //Search if (pkVictim->IsRaceFlag(RACE_FLAG_ANIMAL)) iAtk+= (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_ANIMAL)) / 100; // Add: else if (pkVictim->IsRaceFlag(RACE_FLAG_ATT_NEWATTRTYPE)) iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_NEWATTRTYPE)) / 100;
db:
protoreader.cpp
Spoiler// Search: string arApplyType[] // Add to the end: "APPLY_ATTBONUS_NEWATTRTYPE", // Search: string arRaceFlag[] // Add to the end: "ATT_NEWATTRTYPE"
Tools:
DumpProtoSource
ItemCSVReader.cpp
Spoiler// Search: string arApplyType[] // Add to the end: "APPLY_ATTBONUS_NEWATTRTYPE", // Search: string arRaceFlag[] // Add to the end: "ATT_NEWATTRTYPE"
Client
root
uitooltip.py
Spoiler// Search: item.APPLY_ATTBONUS_DEVIL : localeInfo.TOOLTIP_APPLY_ATTBONUS_DEVIL, // Add: item.APPLY_ATTBONUS_NEWATTRTYPE : localeInfo.TOOLTIP_APPLY_ATTBONUS_NEWATTRTYPE,
locale
locale_game.txt
Spoiler// Add: TOOLTIP_APPLY_ATTBONUS_NEWATTRTYPE Strong against to attr type you want xd +%d%% SA
- 1
- 1
- 2
Find mount mobs wihout folder
in Programming & Scripts
Posted
Hello, this is a script that will help you fill in the empty spaces of the folder section of the mount caused by missing additions in mob_proto.
Tutorial
In main.py
Configure the values in these sections according to your needs.
For example item_proto:
0->Vnum
1->locale_name
2->type
If the mount gets its mob number from value, check which column it is in and replace it with ITEM_MOUNT_VALUE.
Install the chardet package.
Set the contents of the file like this:
After setting the file like this;
Run the script with Python.
There are files for the vnums you need to complete in the mount_with_folder.txt file.
You can complete the missing