Jump to content

Ship Defense (Hydra Dungeon)


Recommended Posts

  • Honorable Member

This is the hidden content, please

Other Mirros
This is the hidden content, please
(GitHub
This is the hidden content, please
(Mega)

Ship Defense is a dungeon accessible only in groups (minimum 2 players, maximum 8) in which players set sail for the new continent defending the ship’s mast from increasingly stronger and more numerous monsters until they defeat all three heads of the Hydra boss. Once the mission is complete, the participants will receive some rewards (determined by chance).

TC8YhEy.png

 

Information

Spoiler

Entry Requirements
All these requirements can be disabled.

  • The player must be present in a group.

  • Only the Group Leader can request entry to the dungeon.

  • All group members must have a Passage Ticket.

  • The maximum number of participants is 8 and the minimum is 2.

  • All group members must be on the same map.

  • The use of mounts is not allowed.

Entrance

The Group Leader requests entry from the Fisherman NPC, located at Dragon Fire Chief, so all participants will be able to access the map.
Requirements: have a Passage Ticket and do not use mounts of any kind.

Objective

The objective is to defend the mast, located on the deck of your ship, from sea monsters and the giant three-headed Hydra. A fight against the destruction of the ship’s mast: monsters attack the main sail in a targeted way to make the boat sink: it will have to be defended from waves of increasingly strong attacks. At the top right, under the mini-map, the HP bar of the ship’s Mast will appear.

Battle

The challenge will begin after the leader (only he can do it) has interacted with the NPC Rudder. All group members must be present in the ship, otherwise it will not be possible to start. From now on you will have 60 seconds to prepare before the ship sails. After these, the characters will have access to the deck of the ship and the first monsters will arrive.

Stage 1 – Hold on for 120 seconds!

The aim of the first phase is to resist the attack of the monsters for 120 seconds, defending the mast NPC. After the time has elapsed, there will be a 10 second pause before moving on to the next phase.

Stage 2 – Destroy the first head!

To complete the second phase it will be necessary to destroy the head of the Hydra, which will appear from the hole in the stern just below the rudder, while continuing to defend the Mast. In this phase, other types of monsters will appear. Defeat the first head, after 10 seconds, we will move on to the next phase. Certain monsters will attack with special attacks, the Brood of Hydra will be able to use a laser beam to heavily damage the tree, this beam can be interrupted by walking over a blue circle with an arrow. This can only be done once per every 10 seconds. Killing the Hydra Brood will spawn Wood for repair, a very weak stone type that if destroyed will drop a Wood for Repair (item) that will allow you to recharge the tree’s HP a little.

Stage 3 – Destroy the second head!

The third phase is identical to the previous one: it will end once the second head of the Hydra is destroyed. The waves of monsters will be more conspicuous and more resistant monsters will appear. More monsters will attack the Tree from a distance. At the end of the phase, after 10 seconds you will move on to the next one.

Stage 4 – Destroy the last head!

The last phase is a much more complicated version of the previous two, not only for the number, type and strength of the monsters, but also for the periodic activation of the Null Magic debuff (loss of all buffs, as for effect activated by the Ability Nullify Magic ) for 25 seconds that will be inflicted on all party members by the last head of the Hydra .
Once this last phase is completed, the reward can be obtained.

Possibility of failing

The group may fail if:

  • The Master Tree is destroyed by monsters

  • All party members choose the Surrender button after dying (in this case you will be taken to Dragon Fire Chief)

In case of Crash

It is possible to reconnect to the dungeon at any time after a crash, the character will reappear directly inside the dungeon.
You must log back into the same channel the dungeon was started in, otherwise you will be taken out to Dragon Fire Chief. It is however possible to re-enter the dungeon by reconnecting in the correct channel. In the event that all members of the party unplug / crash, it is still possible to re-enter the dungeon. Attention, even if there are no group members inside the dungeon, it will continue to function normally. For example, if all party members disconnect at the beginning of the dungeon (Phase 1), and then reconnect 3 minutes later, they will end up in Phase 2 of the dungeon, resulting in the loss of life of the Master Tree .

 

Demonstration

Spoiler

🌞👍

Edited by Metin2 Dev
Core X - External 2 Internal
  • Metin2 Dev 250
  • kekw 2
  • Eyes 6
  • Dislove 1
  • Angry 2
  • Not Good 1
  • Sad 2
  • Smile Tear 1
  • Think 1
  • Scream 2
  • Lmao 1
  • Good 77
  • muscle 1
  • Love 17
  • Love 116
Link to comment
Share on other sites

  • Management

Doctor Who Dalek GIF

Edited by Metin2 Dev
Core X - External 2 Internal
  • Scream 1
  • Lmao 1
  • Love 1
  • Love 1
Link to comment
Share on other sites

someone, something?

 

ShipDefense.h:176:2: error: 'time_t' in namespace 'std' does not name a type
  std::time_t GetStartTime() const { return m_lStartTime; }
  ^
ShipDefense.h:206:2: error: 'time_t' in namespace 'std' does not name a type
  std::time_t m_lStartTime;

 

solution: 

#include <ctime>

 

 

Edited by Artagnanxd
  • Metin2 Dev 6
  • Love 1
Link to comment
Share on other sites

  • Premium

I'd like to share a message.

Your story is kind of a complex one: you went through and had to deal with countless resellers, leakers and the betrayal of close friends, yet that never stopped you from doing what you loved.

You once were a reseller yourself, but you proved everyone you didn't mean to hurt other people's work, you managed to work hard and redeem yourself.

Back when I didn't know you, I wanted to join your project to see what it was all about and in time came to realize what a great person you are.

You are now part of the Honorable members, the most esteemed people in the Metin2 community on a global level. I am truly proud of your redemption arc. You're an inspiration and in my opinion fully represent who people in this community should aim to be: A Fair, Square and Hard working person that learns from their mistakes.

I didn't know you were aiming to release your latest work for free given how much time you spent on it, but thinking about it this truly is the hardest hitting thing you could've possibly done; to release such a dungeon for free really is a powerful act and deserves praise.

Thank you again for never giving up.

Edited by Syreldar
  • Metin2 Dev 1
  • Cry 1
  • Good 1
  • Love 6

 

"Nothing's free in this life.

Ignorant people have an obligation to make up for their ignorance by paying those who help them.

Either you got the brains or cash, if you lack both you're useless."

Syreldar

Link to comment
Share on other sites

  • Forum Moderator

Astonishing work from you, as well as an excellent asset for the community as a whole. Despite all the downside imaginable to willingly share something that cost you considerable time to complete and energy to fiddle for what is conceivably a limited appraise.
Just as Distraught recently, or others before you (Mali, xP3NG3Rx and so on), I personally think you greatly deserve your place amongst the Honorable members of this community, for the quality as well as the will to make the community move forward and I believe everyone agrees with that, ASIKOO being the first.

Thank you!

  • Good 2
  • Love 6

Gurgarath
coming soon

Link to comment
Share on other sites

Compiling error:

Spoiler
compiling main.cpp
In file included from questlua_shipdefense_mgr.cpp:23:
ShipDefense.h:176:7: error: 'time_t' in namespace 'std' does not name a type
  std::time_t GetStartTime() const { return m_lStartTime; }
       ^~~~~~
ShipDefense.h:176:2: note: suggested alternative: 'time_put'
  std::time_t GetStartTime() const { return m_lStartTime; }
  ^~~
  time_put
ShipDefense.h:206:7: error: 'time_t' in namespace 'std' does not name a type
  std::time_t m_lStartTime;
       ^~~~~~
ShipDefense.h:206:2: note: suggested alternative: 'time_put'
  std::time_t m_lStartTime;
  ^~~
  time_put
gmake: *** [Makefile:161: .obj/questlua_shipdefense_mgr.o] Error 1
gmake: *** Waiting for unfinished jobs....
In file included from ShipDefense.cpp:20:
ShipDefense.h:176:7: error: 'time_t' in namespace 'std' does not name a type
  std::time_t GetStartTime() const { return m_lStartTime; }
       ^~~~~~
ShipDefense.h:176:2: note: suggested alternative: 'time_put'
  std::time_t GetStartTime() const { return m_lStartTime; }
  ^~~
  time_put
ShipDefense.h:206:7: error: 'time_t' in namespace 'std' does not name a type
  std::time_t m_lStartTime;
       ^~~~~~
ShipDefense.h:206:2: note: suggested alternative: 'time_put'
  std::time_t m_lStartTime;
  ^~~
  time_put
ShipDefense.cpp: In member function 'void SNotice::operator()(LPENTITY)':
ShipDefense.cpp:269:58: error: 'class CHARACTER' has no member named 'GetLanguag                                                                                                                                                             e'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage())
                                                          ^~~~~~~~~~~
ShipDefense.cpp:269:6: error: 'LC_MOB_NAME' was not declared in this scope
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage())
      ^~~~~~~~~~~
ShipDefense.cpp:269:6: note: suggested alternative: 'CMD_NAME'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage())
      ^~~~~~~~~~~
      CMD_NAME
ShipDefense.cpp:286:58: error: 'class CHARACTER' has no member named 'GetLanguag                                                                                                                                                             e'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
                                                          ^~~~~~~~~~~
ShipDefense.cpp:286:6: error: 'LC_MOB_NAME' was not declared in this scope
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
      ^~~~~~~~~~~
ShipDefense.cpp:286:6: note: suggested alternative: 'CMD_NAME'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
      ^~~~~~~~~~~
      CMD_NAME
ShipDefense.cpp:287:55: error: 'class CHARACTER' has no member named 'GetLanguag                                                                                                                                                             e'
      LC_MOB_NAME(c_lpHydraChar->GetRaceNum(), lpChar->GetLanguage())
                                                       ^~~~~~~~~~~
ShipDefense.cpp:303:58: error: 'class CHARACTER' has no member named 'GetLanguag                                                                                                                                                             e'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
                                                          ^~~~~~~~~~~
ShipDefense.cpp:303:6: error: 'LC_MOB_NAME' was not declared in this scope
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
      ^~~~~~~~~~~
ShipDefense.cpp:303:6: note: suggested alternative: 'CMD_NAME'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
      ^~~~~~~~~~~
      CMD_NAME
ShipDefense.cpp: In function 'long int LaserEffectEvent(LPEVENT, long int)':
ShipDefense.cpp:483:8: error: 'random_device' is not a member of 'std'
   std::random_device RandomDevice;
        ^~~~~~~~~~~~~
ShipDefense.cpp:483:8: note: suggested alternative: 'ratio_divide'
   std::random_device RandomDevice;
        ^~~~~~~~~~~~~
        ratio_divide
ShipDefense.cpp:484:8: error: 'mt19937' is not a member of 'std'
   std::mt19937 Generate(RandomDevice());
        ^~~~~~~
ShipDefense.cpp:485:8: error: 'uniform_real_distribution' is not a member of 'st                                                                                                                                                             d'
   std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefens                                                                                                                                                             e::MAX_PROB);
        ^~~~~~~~~~~~~~~~~~~~~~~~~
ShipDefense.cpp:485:8: note: suggested alternative: 'uniform_int_distribution'
   std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefens                                                                                                                                                             e::MAX_PROB);
        ^~~~~~~~~~~~~~~~~~~~~~~~~
        uniform_int_distribution
ShipDefense.cpp:485:34: error: expected primary-expression before '>' token
   std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefens                                                                                                                                                             e::MAX_PROB);
                                  ^
ShipDefense.cpp:485:36: error: 'Distribute' was not declared in this scope
   std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefens                                                                                                                                                             e::MAX_PROB);
                                    ^~~~~~~~~~
ShipDefense.cpp:485:36: note: suggested alternative: 'CAttribute'
   std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefens                                                                                                                                                             e::MAX_PROB);
                                    ^~~~~~~~~~
                                    CAttribute
ShipDefense.cpp:501:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= uiSpawnProbability)
                                    ^~~~~~~~
ShipDefense.cpp:501:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= uiSpawnProbability)
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp: In function 'long int SpawnEvent(LPEVENT, long int)':
ShipDefense.cpp:601:7: error: 'random_device' is not a member of 'std'
  std::random_device RandomDevice;
       ^~~~~~~~~~~~~
ShipDefense.cpp:601:7: note: suggested alternative: 'ratio_divide'
  std::random_device RandomDevice;
       ^~~~~~~~~~~~~
       ratio_divide
ShipDefense.cpp:602:7: error: 'mt19937' is not a member of 'std'
  std::mt19937 Generate(RandomDevice());
       ^~~~~~~
ShipDefense.cpp:603:7: error: 'uniform_real_distribution' is not a member of 'st                                                                                                                                                             d'
  std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense                                                                                                                                                             ::MAX_PROB);
       ^~~~~~~~~~~~~~~~~~~~~~~~~
ShipDefense.cpp:603:7: note: suggested alternative: 'uniform_int_distribution'
  std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense                                                                                                                                                             ::MAX_PROB);
       ^~~~~~~~~~~~~~~~~~~~~~~~~
       uniform_int_distribution
ShipDefense.cpp:603:33: error: expected primary-expression before '>' token
  std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense                                                                                                                                                             ::MAX_PROB);
                                 ^
ShipDefense.cpp:603:35: error: 'Distribute' was not declared in this scope
  std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense                                                                                                                                                             ::MAX_PROB);
                                   ^~~~~~~~~~
ShipDefense.cpp:603:35: note: suggested alternative: 'CAttribute'
  std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense                                                                                                                                                             ::MAX_PROB);
                                   ^~~~~~~~~~
                                   CAttribute
ShipDefense.cpp:635:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
ShipDefense.cpp:635:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp:638:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 30) // 3%
                                    ^~~~~~~~
ShipDefense.cpp:638:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 30) // 3%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp:664:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
ShipDefense.cpp:664:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp:667:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 40) // 4%
                                    ^~~~~~~~
ShipDefense.cpp:667:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 40) // 4%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp:693:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
ShipDefense.cpp:693:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp:696:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 50) // 5%
                                    ^~~~~~~~
ShipDefense.cpp:696:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 50) // 5%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp: In constructor 'CShipDefense::CShipDefense(long int, DWORD)':
ShipDefense.cpp:738:2: error: 'm_lStartTime' was not declared in this scope
  m_lStartTime = 0;
  ^~~~~~~~~~~~
ShipDefense.cpp:738:2: note: suggested alternative: 'm_byState'
  m_lStartTime = 0;
  ^~~~~~~~~~~~
  m_byState
ShipDefense.cpp: In member function 'virtual void CShipDefense::Destroy()':
ShipDefense.cpp:764:2: error: 'm_lStartTime' was not declared in this scope
  m_lStartTime = 0;
  ^~~~~~~~~~~~
ShipDefense.cpp:764:2: note: suggested alternative: 'm_byState'
  m_lStartTime = 0;
  ^~~~~~~~~~~~
  m_byState
ShipDefense.cpp: In member function 'void CShipDefense::Notice(LPCHARACTER, bool                                                                                                                                                             , const char*, ...)':
ShipDefense.cpp:862:63: error: 'class CHARACTER' has no member named 'GetLanguag                                                                                                                                                             e'
   const char* c_pszLocaleText = LC_STRING(c_pszBuf, c_lpChar->GetLanguage());
                                                               ^~~~~~~~~~~
ShipDefense.cpp:862:33: error: 'LC_STRING' was not declared in this scope
   const char* c_pszLocaleText = LC_STRING(c_pszBuf, c_lpChar->GetLanguage());
                                 ^~~~~~~~~
ShipDefense.cpp:862:33: note: suggested alternative: 'LC_TIME'
   const char* c_pszLocaleText = LC_STRING(c_pszBuf, c_lpChar->GetLanguage());
                                 ^~~~~~~~~
                                 LC_TIME
ShipDefense.cpp: In member function 'void CShipDefense::Start()':
ShipDefense.cpp:1057:2: error: 'm_lStartTime' was not declared in this scope
  m_lStartTime = std::time(nullptr);
  ^~~~~~~~~~~~
ShipDefense.cpp:1057:2: note: suggested alternative: 'm_byState'
  m_lStartTime = std::time(nullptr);
  ^~~~~~~~~~~~
  m_byState
ShipDefense.cpp: In member function 'bool CShipDefense::PrepareDeck()':
ShipDefense.cpp:1094:3: error: 'm_lStartTime' was not declared in this scope
   m_lStartTime = std::time(nullptr);
   ^~~~~~~~~~~~
ShipDefense.cpp:1094:3: note: suggested alternative: 'm_byState'
   m_lStartTime = std::time(nullptr);
   ^~~~~~~~~~~~
   m_byState
gmake: *** [Makefile:161: .obj/ShipDefense.o] Error 1

 

 

Edited by Calypso2
Link to comment
Share on other sites

  • Management
3 minutes ago, Calypso2 said:

Compiling error:

  Reveal hidden contents

 

 

Try this : 

Link to comment
Share on other sites

  • Honorable Member

I haven't tested the system, but there's something that you should always avoid if possible:

using UniqueCharacterMap = std::map<UNIQUE_CHAR_POSITION, LPCHARACTER>;
UniqueCharacterMap m_mapUniqueCharacter;

You are directly storing the character ptr into the map, and, later on, calling GetUniqueCharacter to get the ptr back. There's a very good possibility of getting a dangling pointer.

Purged monsters expire immediately, dead monsters in few seconds. One of the common issues of writing dungeons in c++ is actually this one.

To be sure you're not getting a dangling pointer, you should store the VID of the monster instead of the ptr. This little change slightly affects performance though.

This function should be enough to check the validity of a vid:

LPCHARACTER FindValidCharacter(const VID & vid)
{
	if (!vid.GetID())
		return nullptr;
	const auto ch = CHARACTER_MANAGER::instance().Find(vid.GetID());
	return (ch && !ch->IsDead()) ? ch : nullptr;
}

 

Thanks for sharing.

  • Metin2 Dev 1
  • Eyes 1
  • Good 2
  • Love 1
  • Love 2
Link to comment
Share on other sites

  • Honorable Member

@Calypso2, check the repository, it's been updated since yesterday and you can include <ctime> in your stdafx.h.

Spoiler
46 minutes ago, Calypso2 said:

Compiling error:

  Hide contents
compiling main.cpp
In file included from questlua_shipdefense_mgr.cpp:23:
ShipDefense.h:176:7: error: 'time_t' in namespace 'std' does not name a type
  std::time_t GetStartTime() const { return m_lStartTime; }
       ^~~~~~
ShipDefense.h:176:2: note: suggested alternative: 'time_put'
  std::time_t GetStartTime() const { return m_lStartTime; }
  ^~~
  time_put
ShipDefense.h:206:7: error: 'time_t' in namespace 'std' does not name a type
  std::time_t m_lStartTime;
       ^~~~~~
ShipDefense.h:206:2: note: suggested alternative: 'time_put'
  std::time_t m_lStartTime;
  ^~~
  time_put
gmake: *** [Makefile:161: .obj/questlua_shipdefense_mgr.o] Error 1
gmake: *** Waiting for unfinished jobs....
In file included from ShipDefense.cpp:20:
ShipDefense.h:176:7: error: 'time_t' in namespace 'std' does not name a type
  std::time_t GetStartTime() const { return m_lStartTime; }
       ^~~~~~
ShipDefense.h:176:2: note: suggested alternative: 'time_put'
  std::time_t GetStartTime() const { return m_lStartTime; }
  ^~~
  time_put
ShipDefense.h:206:7: error: 'time_t' in namespace 'std' does not name a type
  std::time_t m_lStartTime;
       ^~~~~~
ShipDefense.h:206:2: note: suggested alternative: 'time_put'
  std::time_t m_lStartTime;
  ^~~
  time_put
ShipDefense.cpp: In member function 'void SNotice::operator()(LPENTITY)':
ShipDefense.cpp:269:58: error: 'class CHARACTER' has no member named 'GetLanguag                                                                                                                                                             e'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage())
                                                          ^~~~~~~~~~~
ShipDefense.cpp:269:6: error: 'LC_MOB_NAME' was not declared in this scope
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage())
      ^~~~~~~~~~~
ShipDefense.cpp:269:6: note: suggested alternative: 'CMD_NAME'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage())
      ^~~~~~~~~~~
      CMD_NAME
ShipDefense.cpp:286:58: error: 'class CHARACTER' has no member named 'GetLanguag                                                                                                                                                             e'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
                                                          ^~~~~~~~~~~
ShipDefense.cpp:286:6: error: 'LC_MOB_NAME' was not declared in this scope
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
      ^~~~~~~~~~~
ShipDefense.cpp:286:6: note: suggested alternative: 'CMD_NAME'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
      ^~~~~~~~~~~
      CMD_NAME
ShipDefense.cpp:287:55: error: 'class CHARACTER' has no member named 'GetLanguag                                                                                                                                                             e'
      LC_MOB_NAME(c_lpHydraChar->GetRaceNum(), lpChar->GetLanguage())
                                                       ^~~~~~~~~~~
ShipDefense.cpp:303:58: error: 'class CHARACTER' has no member named 'GetLanguag                                                                                                                                                             e'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
                                                          ^~~~~~~~~~~
ShipDefense.cpp:303:6: error: 'LC_MOB_NAME' was not declared in this scope
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
      ^~~~~~~~~~~
ShipDefense.cpp:303:6: note: suggested alternative: 'CMD_NAME'
      LC_MOB_NAME(c_lpAllianceChar->GetRaceNum(), lpChar->GetLanguage()),
      ^~~~~~~~~~~
      CMD_NAME
ShipDefense.cpp: In function 'long int LaserEffectEvent(LPEVENT, long int)':
ShipDefense.cpp:483:8: error: 'random_device' is not a member of 'std'
   std::random_device RandomDevice;
        ^~~~~~~~~~~~~
ShipDefense.cpp:483:8: note: suggested alternative: 'ratio_divide'
   std::random_device RandomDevice;
        ^~~~~~~~~~~~~
        ratio_divide
ShipDefense.cpp:484:8: error: 'mt19937' is not a member of 'std'
   std::mt19937 Generate(RandomDevice());
        ^~~~~~~
ShipDefense.cpp:485:8: error: 'uniform_real_distribution' is not a member of 'st                                                                                                                                                             d'
   std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefens                                                                                                                                                             e::MAX_PROB);
        ^~~~~~~~~~~~~~~~~~~~~~~~~
ShipDefense.cpp:485:8: note: suggested alternative: 'uniform_int_distribution'
   std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefens                                                                                                                                                             e::MAX_PROB);
        ^~~~~~~~~~~~~~~~~~~~~~~~~
        uniform_int_distribution
ShipDefense.cpp:485:34: error: expected primary-expression before '>' token
   std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefens                                                                                                                                                             e::MAX_PROB);
                                  ^
ShipDefense.cpp:485:36: error: 'Distribute' was not declared in this scope
   std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefens                                                                                                                                                             e::MAX_PROB);
                                    ^~~~~~~~~~
ShipDefense.cpp:485:36: note: suggested alternative: 'CAttribute'
   std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefens                                                                                                                                                             e::MAX_PROB);
                                    ^~~~~~~~~~
                                    CAttribute
ShipDefense.cpp:501:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= uiSpawnProbability)
                                    ^~~~~~~~
ShipDefense.cpp:501:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= uiSpawnProbability)
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp: In function 'long int SpawnEvent(LPEVENT, long int)':
ShipDefense.cpp:601:7: error: 'random_device' is not a member of 'std'
  std::random_device RandomDevice;
       ^~~~~~~~~~~~~
ShipDefense.cpp:601:7: note: suggested alternative: 'ratio_divide'
  std::random_device RandomDevice;
       ^~~~~~~~~~~~~
       ratio_divide
ShipDefense.cpp:602:7: error: 'mt19937' is not a member of 'std'
  std::mt19937 Generate(RandomDevice());
       ^~~~~~~
ShipDefense.cpp:603:7: error: 'uniform_real_distribution' is not a member of 'st                                                                                                                                                             d'
  std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense                                                                                                                                                             ::MAX_PROB);
       ^~~~~~~~~~~~~~~~~~~~~~~~~
ShipDefense.cpp:603:7: note: suggested alternative: 'uniform_int_distribution'
  std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense                                                                                                                                                             ::MAX_PROB);
       ^~~~~~~~~~~~~~~~~~~~~~~~~
       uniform_int_distribution
ShipDefense.cpp:603:33: error: expected primary-expression before '>' token
  std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense                                                                                                                                                             ::MAX_PROB);
                                 ^
ShipDefense.cpp:603:35: error: 'Distribute' was not declared in this scope
  std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense                                                                                                                                                             ::MAX_PROB);
                                   ^~~~~~~~~~
ShipDefense.cpp:603:35: note: suggested alternative: 'CAttribute'
  std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense                                                                                                                                                             ::MAX_PROB);
                                   ^~~~~~~~~~
                                   CAttribute
ShipDefense.cpp:635:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
ShipDefense.cpp:635:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp:638:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 30) // 3%
                                    ^~~~~~~~
ShipDefense.cpp:638:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 30) // 3%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp:664:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
ShipDefense.cpp:664:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp:667:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 40) // 4%
                                    ^~~~~~~~
ShipDefense.cpp:667:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 40) // 4%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp:693:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
ShipDefense.cpp:693:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 10) // 1%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp:696:36: error: 'Generate' was not declared in this scope
   if (static_cast<UINT>(Distribute(Generate)) <= 50) // 5%
                                    ^~~~~~~~
ShipDefense.cpp:696:36: note: suggested alternative: 'rename'
   if (static_cast<UINT>(Distribute(Generate)) <= 50) // 5%
                                    ^~~~~~~~
                                    rename
ShipDefense.cpp: In constructor 'CShipDefense::CShipDefense(long int, DWORD)':
ShipDefense.cpp:738:2: error: 'm_lStartTime' was not declared in this scope
  m_lStartTime = 0;
  ^~~~~~~~~~~~
ShipDefense.cpp:738:2: note: suggested alternative: 'm_byState'
  m_lStartTime = 0;
  ^~~~~~~~~~~~
  m_byState
ShipDefense.cpp: In member function 'virtual void CShipDefense::Destroy()':
ShipDefense.cpp:764:2: error: 'm_lStartTime' was not declared in this scope
  m_lStartTime = 0;
  ^~~~~~~~~~~~
ShipDefense.cpp:764:2: note: suggested alternative: 'm_byState'
  m_lStartTime = 0;
  ^~~~~~~~~~~~
  m_byState
ShipDefense.cpp: In member function 'void CShipDefense::Notice(LPCHARACTER, bool                                                                                                                                                             , const char*, ...)':
ShipDefense.cpp:862:63: error: 'class CHARACTER' has no member named 'GetLanguag                                                                                                                                                             e'
   const char* c_pszLocaleText = LC_STRING(c_pszBuf, c_lpChar->GetLanguage());
                                                               ^~~~~~~~~~~
ShipDefense.cpp:862:33: error: 'LC_STRING' was not declared in this scope
   const char* c_pszLocaleText = LC_STRING(c_pszBuf, c_lpChar->GetLanguage());
                                 ^~~~~~~~~
ShipDefense.cpp:862:33: note: suggested alternative: 'LC_TIME'
   const char* c_pszLocaleText = LC_STRING(c_pszBuf, c_lpChar->GetLanguage());
                                 ^~~~~~~~~
                                 LC_TIME
ShipDefense.cpp: In member function 'void CShipDefense::Start()':
ShipDefense.cpp:1057:2: error: 'm_lStartTime' was not declared in this scope
  m_lStartTime = std::time(nullptr);
  ^~~~~~~~~~~~
ShipDefense.cpp:1057:2: note: suggested alternative: 'm_byState'
  m_lStartTime = std::time(nullptr);
  ^~~~~~~~~~~~
  m_byState
ShipDefense.cpp: In member function 'bool CShipDefense::PrepareDeck()':
ShipDefense.cpp:1094:3: error: 'm_lStartTime' was not declared in this scope
   m_lStartTime = std::time(nullptr);
   ^~~~~~~~~~~~
ShipDefense.cpp:1094:3: note: suggested alternative: 'm_byState'
   m_lStartTime = std::time(nullptr);
   ^~~~~~~~~~~~
   m_byState
gmake: *** [Makefile:161: .obj/ShipDefense.o] Error 1

 

 

 

@ martysama0134, this is something that I tested over and over again, when any character is purged, deleted or killed the pointer is removed immediately from the map and cleared preventing the pointer to get dangled and additional checks where made to avoid this issue but I might consider changing the storage type if eventually there are future problems with it. Thanks for the reply.

Spoiler
9 minutes ago, martysama0134 said:

I haven't tested the system, but there's something that you should always avoid if possible:

using UniqueCharacterMap = std::map<UNIQUE_CHAR_POSITION, LPCHARACTER>;
UniqueCharacterMap m_mapUniqueCharacter;

You are directly storing the character ptr into the map, and, later on, calling GetUniqueCharacter to get the ptr back. There's a very good possibility of getting a dangling pointer.

Purged monsters expire immediately, dead monsters in few seconds. One of the common issues of writing dungeons in c++ is actually this one.

To be sure you're not getting a dangling pointer, you should store the VID of the monster instead of the ptr. This little change slightly affects performance though.

This function should be enough to check the validity of a vid:

LPCHARACTER FindValidCharacter(const VID & vid)
{
	if (!vid.GetID())
		return nullptr;
	const auto ch = CHARACTER_MANAGER::instance().Find(vid.GetID());
	return (ch && !ch->IsDead()) ? ch : nullptr;
}

 

Thanks for sharing.

 

 

Link to comment
Share on other sites

  • Developer

I leave here a few tips that could improve code readability, performance and safety. I also report you a serious issue that generates memory leaks.
Clearly, even though there are things that I consider outdated (which I am sure you have seen in the ymir code written in the early 2000s), I still appreciate that you have released all this work for free.

The Functor (struct with operator()) is a trick used in the past to work with temporary functions that can store data, in short, a very outdated "lambda".
Since C++11, we can use lambdas to definitely replace Functors, which are clearer and more readable and probably much optimizable by the compiler.

The serious issue I noticed is how you insert and remove data inside m_mapShipDefense. (ps. emplace is always preferable than insert)
The raw use of new and delete is to be considered outdated, and really unsafe. Proof of this is the leak I am about to show.
Looking on CShipDefenseManager::Remove method:

void CShipDefenseManager::Remove(const DWORD c_dwLeaderPID)
{
	ShipDefenseMap::iterator it = m_mapShipDefense.find(c_dwLeaderPID);
	if (it != m_mapShipDefense.end())
		m_mapShipDefense.erase(it); //erased but not deleted?
}

and again looking on CShipDefenseManager::Destroy() method:
 

void CShipDefenseManager::Destroy()
{
	ShipDefenseMap::iterator it = m_mapShipDefense.begin();
	for (; it != m_mapShipDefense.end(); ++it)
	{
		CShipDefense* pShipDefense = it->second;
		if (pShipDefense)
		{
			pShipDefense->Destroy(); //is this use safe if you check its value immediately below?
			if (pShipDefense)
				delete pShipDefense;
		}
	}
	m_mapShipDefense.clear();
}


A good way to solve your issue would be the use of smart pointers which are much safer and do the dirty work for you.


PS:
Since C++98 you can use struct without encapsulating it in a typedef declaration.
 

typedef struct SBroadcastAllianceHP
{
} TBroadcastAllianceHP;

// can be changed to

struct TBroadcastAllianceHP
{
};

 

I've only checked ShipDefense.cpp so far. If I get time, I'll check the rest



---- EDIT
I think you have misunderstood the meaning of the return value of the c lua functions.
You should return the number of pushed elements in the stack.
Many of the functions I have seen in the code you shared have a wrong return.

	int ship_defense_mgr_land(lua_State* L)
	{
		const LPCHARACTER c_lpChar = CQuestManager::instance().GetCurrentCharacterPtr();
		if (c_lpChar == nullptr)
			return 0;

		CShipDefenseManager& rkShipDefenseMgr = CShipDefenseManager::Instance();
		rkShipDefenseMgr.Land(c_lpChar);
		return 1; // WRONG - NO PUSHED ELEMENTS SO WHY 1?
	}

	int ship_defense_mgr_is_created(lua_State* L)
	{
		const LPCHARACTER c_lpChar = CQuestManager::instance().GetCurrentCharacterPtr();
		if (c_lpChar == nullptr)
			return 0;

		CShipDefenseManager& rkShipDefenseMgr = CShipDefenseManager::Instance();
		lua_pushboolean(L, rkShipDefenseMgr.IsCreated(c_lpChar));
		return 1; // CORRECT, YOU PUSHED 1 ELEMENT
	}

 

----- EDIT2
I would recommend to add some small check here to make the function skip all monsters dead outside the dungeon.
This method CShipDefenseManager::OnKill get called 2 times (first inside CHARACTER::Dead, second inside CHARACTER_MANAGER::DestroyCharacter) anytime a monster die, anytime a monster die in the whole core.Not a good idea keep it loops throught `std::map` (which is really slow to get iterated) and perform the whole CShipDefense::DeadCharacter on each dungeon instance (which it again has a while loop iterating a `std::map`) method anytime a player kill a monster anywhere.
All of this is preventable with a small check making the function skips 99.9% of the monsters killed/purged.
 


bool CShipDefenseManager::OnKill(LPCHARACTER lpDeadChar, LPCHARACTER lpKillerChar)
{
	if (lpDeadChar == nullptr)
		return false;

	if (m_mapShipDefense.empty())
		return false;
  
  	//TODO : Add here a check to skip 99.99% of the monsters which are not relevant in this method







 

Edited by Ikarus_
  • Metin2 Dev 1
  • Scream 1
  • Good 4
  • Love 1
  • Love 4

My youtube channel  on which you can see my works here

Link to comment
Share on other sites

  • Honorable Member

@ Ikarus_, thanks for the feedback and heads-up, I have updated the repository.
About the struct usage, sometimes I add the typedef and sometimes I don't, It's personal preference but for good practice I removed it and about the lua returns, I honestly completely ignored and forgot them because I copied the first function from another questlua file and I continued to paste the same returns for the other functions. As for the destruction of the instance I have reviewed and fixed it. Finally, I add a check to the CShipDefenseManager::OnKill functuion that should be enough to prevent it beeing called from every destruction of characters.

Quote
5 hours ago, Ikarus_ said:

I leave here a few tips that could improve code readability, performance and safety. I also report you a serious issue that generates memory leaks.
Clearly, even though there are things that I consider outdated (which I am sure you have seen in the ymir code written in the early 2000s), I still appreciate that you have released all this work for free.

The Functor (struct with operator()) is a trick used in the past to work with temporary functions that can store data, in short, a very outdated "lambda".
Since C++11, we can use lambdas to definitely replace Functors, which are clearer and more readable and probably much optimizable by the compiler.

The serious issue I noticed is how you insert and remove data inside m_mapShipDefense. (ps. emplace is always preferable than insert)
The raw use of new and delete is to be considered outdated, and really unsafe. Proof of this is the leak I am about to show.
Looking on CShipDefenseManager::Remove method:

void CShipDefenseManager::Remove(const DWORD c_dwLeaderPID)
{
	ShipDefenseMap::iterator it = m_mapShipDefense.find(c_dwLeaderPID);
	if (it != m_mapShipDefense.end())
		m_mapShipDefense.erase(it); //erased but not deleted?
}

and again looking on CShipDefenseManager::Destroy() method:
 

void CShipDefenseManager::Destroy()
{
	ShipDefenseMap::iterator it = m_mapShipDefense.begin();
	for (; it != m_mapShipDefense.end(); ++it)
	{
		CShipDefense* pShipDefense = it->second;
		if (pShipDefense)
		{
			pShipDefense->Destroy(); //is this use safe if you check its value immediately below?
			if (pShipDefense)
				delete pShipDefense;
		}
	}
	m_mapShipDefense.clear();
}


A good way to solve your issue would be the use of smart pointers which are much safer and do the dirty work for you.


PS:
Since C++98 you can use struct without encapsulating it in a typedef declaration.
 

typedef struct SBroadcastAllianceHP
{
} TBroadcastAllianceHP;

// can be changed to

struct TBroadcastAllianceHP
{
};

 

I've only checked ShipDefense.cpp so far. If I get time, I'll check the rest



---- EDIT
I think you have misunderstood the meaning of the return value of the c lua functions.
You should return the number of pushed elements in the stack.
Many of the functions I have seen in the code you shared have a wrong return.

	int ship_defense_mgr_land(lua_State* L)
	{
		const LPCHARACTER c_lpChar = CQuestManager::instance().GetCurrentCharacterPtr();
		if (c_lpChar == nullptr)
			return 0;

		CShipDefenseManager& rkShipDefenseMgr = CShipDefenseManager::Instance();
		rkShipDefenseMgr.Land(c_lpChar);
		return 1; // WRONG - NO PUSHED ELEMENTS SO WHY 1?
	}

	int ship_defense_mgr_is_created(lua_State* L)
	{
		const LPCHARACTER c_lpChar = CQuestManager::instance().GetCurrentCharacterPtr();
		if (c_lpChar == nullptr)
			return 0;

		CShipDefenseManager& rkShipDefenseMgr = CShipDefenseManager::Instance();
		lua_pushboolean(L, rkShipDefenseMgr.IsCreated(c_lpChar));
		return 1; // CORRECT, YOU PUSHED 1 ELEMENT
	}

 

----- EDIT2
I would recommend to add some small check here to make the function skip all monsters dead outside the dungeon.
This method CShipDefenseManager::OnKill get called 2 times (first inside CHARACTER::Dead, second inside CHARACTER_MANAGER::DestroyCharacter) anytime a monster die, anytime a monster die in the whole core.Not a good idea keep it loops throught `std::map` (which is really slow to get iterated) and perform the whole CShipDefense::DeadCharacter on each dungeon instance (which it again has a while loop iterating a `std::map`) method anytime a player kill a monster anywhere.
All of this is preventable with a small check make the function skips 99.9% of the monsters killed/purged.
 


bool CShipDefenseManager::OnKill(LPCHARACTER lpDeadChar, LPCHARACTER lpKillerChar)
{
	if (lpDeadChar == nullptr)
		return false;

	if (m_mapShipDefense.empty())
		return false;
  
  	//TODO : Add here a check to skip 99.99% of the monsters which are not relevant in this method







 

 

 

  • Metin2 Dev 3
  • Good 3
Link to comment
Share on other sites

  • Developer

I ve also found a really slow piece of code which execute a syscall on every call that can be avoided just by declaring the variables as statics.

Here is the piece of code i m talking about:

	// Generate random probability for spawning something.
	std::random_device RandomDevice;
	std::mt19937 Generate(RandomDevice());
	std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense::MAX_PROB);

And here the fix i would recommend:

	// Generate random probability for spawning something.
	static std::random_device RandomDevice;
	static std::mt19937 Generate(RandomDevice());
	static std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense::MAX_PROB);

Here is a small benchmark i made to better clarify what we are talking about.
As you can see, we are talking about an improvement that reduces execution time by about 100,000 times, not a small amount I would say. 
https://godbolt.org/z/bGrqfvMna

 

EDIT -----

I ve noticed right now that you got a failed check which should prevent numerical overflow but that actually it doesn't.
 

	//THIS EXPRESION RESULT TO BE ALWAYS FALSE DUE TO NUMERICAL OVERFLOW
	// Prevent second counter from overflowing.
	if (pSpawnEventInfo->uiCountSec > UINT_MAX)
		return 0;
	
	//CORRECT WAY OF PREVENTING NUMERICAL OVERFLOW
	// Prevent second counter from overflowing.
	if (static_cast<uint64_t>(pSpawnEventInfo->uiCountSec) + 1 > UINT_MAX)
		return 0;

 

Edited by Ikarus_
  • Metin2 Dev 1
  • Good 4
  • Love 2

My youtube channel  on which you can see my works here

Link to comment
Share on other sites

  • Premium
1 hour ago, Ikarus_ said:

I ve also found a really slow piece of code which execute a syscall on every call that can be avoided just by declaring the variables as statics.

Here is the piece of code i m talking about:

	// Generate random probability for spawning something.
	std::random_device RandomDevice;
	std::mt19937 Generate(RandomDevice());
	std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense::MAX_PROB);

And here the fix i would recommend:

	// Generate random probability for spawning something.
	static std::random_device RandomDevice;
	static std::mt19937 Generate(RandomDevice());
	static std::uniform_real_distribution<> Distribute(ShipDefense::MIN_PROB, ShipDefense::MAX_PROB);

Here is a small benchmark i made to better clarify what we are talking about.
As you can see, we are talking about an improvement that reduces execution time by about 100,000 times, not a small amount I would say. 
https://godbolt.org/z/bGrqfvMna

 

EDIT -----

I ve noticed right now that you got a failed check which should prevent numerical overflow but that actually it doesn't.
 

	//THIS EXEPRESION RESULT TO BE ALWAYS FALSE DUE TO NUMERICAL OVERFLOW
	// Prevent second counter from overflowing.
	if (pSpawnEventInfo->uiCountSec > UINT_MAX)
		return 0;
	
	//CORRECT WAY OF PREVENTING NUMERICAL OVERFLOW
	// Prevent second counter from overflowing.
	if (static_cast<uint64_t>(pSpawnEventInfo->uiCountSec) + 1 > UINT_MAX)
		return 0;

 

That random thing is very interesting, I didn't know about such speed improvement (I replaced the number() function with STL implementations. Obviously in a test server environment it doesn't feel slow, but this is a big jump on speed nonetheless. Love it.)

Link to comment
Share on other sites

  • Developer
7 minutes ago, xXIntelXx said:

That random thing is very interesting, I didn't know about such speed improvement (I replaced the number() function with STL implementations. Obviously in a test server environment it doesn't feel slow, but this is a big jump on speed nonetheless. Love it.)

Don't forget that static variables aren't thread safe (m2 server is a single-threaded application so it is still safe).
The `std::uniform_real_distribution<>` can be static only if min and max used to declare it are constant (as it is in the code i posted).
Anyway moving to static storage only the two others  (std::random_device, std::mt19937) still give most of the advantage in terms of execution time.

Edited by Ikarus_
  • Metin2 Dev 2
  • Good 1

My youtube channel  on which you can see my works here

Link to comment
Share on other sites

  • Honorable Member

Repository updated.

Replaced "functors" (function objects) with lambda expressions.
Optimized execution time of random generation by making them static and corrected numerical overflow check on second count. (Thanks @ Ikarus_)

Edited by Owsap
  • Metin2 Dev 21
  • Lmao 1
  • Love 3
  • Love 3
Link to comment
Share on other sites

  • Premium

Thanks for the amazing work you do and for publishing such system that cost you time and work

There is a core crash problem tho, maybe you can check what's wrong

https://metin2.download/picture/3RdcFkFv0mb07LtE3mIHW46Lk6YiYFfT/.png

Thank you again

Edited by Metin2 Dev
Core X - External 2 Internal
Link to comment
Share on other sites

  • Developer
8 minutes ago, Mano said:

Thanks for the amazing work you do and for publishing such system that cost you time and work

There is a core crash problem tho, maybe you can check what's wrong

https://metin2.download/picture/eKgq96f6A5lsfmpSwxNKw7PL2Y4sgG37/.png

Thank you again

It would be helpful to post char_battle.cpp or at least what it contains at line 2530 and around.

Edited by Metin2 Dev
Core X - External 2 Internal

My youtube channel  on which you can see my works here

Link to comment
Share on other sites

  • Premium
12 minutes ago, Ikarus_ said:

It would be helpful to post the char_battle.cpp file or at least what it contains at line 2530 and around.

I'm running test server and i got that core downer because of this block

Spoiler

        if (test_server)
        {
            int iTmpPercent = 0; // @fixme136
            if (GetMaxHP() >= 0)
                iTmpPercent = (GetHP() * 100) / GetMaxHP();

            if(pAttacker)
            {
                pAttacker->ChatPacket(CHAT_TYPE_INFO, "-> %s, DAM %d HP %d(%d%%) %s%s",
                        GetName(),
                        dam,
                        GetHP(),
                        iTmpPercent,
                        IsCritical ? "crit " : "",
                        IsPenetrate ? "pene " : "",
                        IsDeathBlow ? "deathblow " : "");
            }

            ChatPacket(CHAT_TYPE_PARTY, "<- %s, DAM %d HP %d(%d%%) %s%s",
                    pAttacker ? pAttacker->GetName() : 0,
                    dam,
                    GetHP(),
                    iTmpPercent,
                    IsCritical ? "crit " : "",
                    IsPenetrate ? "pene " : "",
                    IsDeathBlow ? "deathblow " : "");
        }

This line exactly

Spoiler

iTmpPercent = (GetHP() * 100) / GetMaxHP();

Edit: if i deactivated test server it works and there is no core crash but the mast is destroyed right after counter timer ends

https://metin2.download/picture/1e97P10iU39HjN9be33bqBsycEm2stuD/.png

Edited by Metin2 Dev
Core X - External 2 Internal
Link to comment
Share on other sites

  • Developer
1 hour ago, Mano said:

I'm running test server and i got that core downer because of this block

  Hide contents

        if (test_server)
        {
            int iTmpPercent = 0; // @fixme136
            if (GetMaxHP() >= 0)
                iTmpPercent = (GetHP() * 100) / GetMaxHP();

            if(pAttacker)
            {
                pAttacker->ChatPacket(CHAT_TYPE_INFO, "-> %s, DAM %d HP %d(%d%%) %s%s",
                        GetName(),
                        dam,
                        GetHP(),
                        iTmpPercent,
                        IsCritical ? "crit " : "",
                        IsPenetrate ? "pene " : "",
                        IsDeathBlow ? "deathblow " : "");
            }

            ChatPacket(CHAT_TYPE_PARTY, "<- %s, DAM %d HP %d(%d%%) %s%s",
                    pAttacker ? pAttacker->GetName() : 0,
                    dam,
                    GetHP(),
                    iTmpPercent,
                    IsCritical ? "crit " : "",
                    IsPenetrate ? "pene " : "",
                    IsDeathBlow ? "deathblow " : "");
        }

This line exactly

  Hide contents

iTmpPercent = (GetHP() * 100) / GetMaxHP();

Edit: if i deactivated test server it works and there is no core crash but the mast is destroyed right after counter timer ends

https://metin2.download/picture/1XiUAKWZEeCBM5XwxGy0Dri1Asb7v94h/.png

I guess that GetMaxHP returned 0 for some reason, and that is why it crashed. You can solve it by simply checking that GetMaxHP is different from 0 in that if.
Test this fix and report if it helped you:
 

// replace this
	if (GetMaxHP() >= 0)
		iTmpPercent = (GetHP() * 100) / GetMaxHP();

//with this
	if (GetMaxHP() > 0)
		iTmpPercent = (GetHP() * 100) / GetMaxHP();

 

Edited by Metin2 Dev
Core X - External 2 Internal
  • Love 1

My youtube channel  on which you can see my works here

Link to comment
Share on other sites

  • Premium
31 minutes ago, Ikarus_ said:

I guess that GetMaxHP returned 0 for some reason, and that is why it crashed. You can solve it by simply checking that GetMaxHP is different from 0 in that if.
Test this fix and report if it helped you:
 

// replace this
	if (GetMaxHP() >= 0)
		iTmpPercent = (GetHP() * 100) / GetMaxHP();

//with this
	if (GetMaxHP() > 0)
		iTmpPercent = (GetHP() * 100) / GetMaxHP();

 

Yeah that solved the problem, so somehow BroadcastAllianceHP is setting mast hp to 0 or idk why the mast is destroyed right after the timer ends

Edit: Turns out mob_proto.txt data is the reason and max_hp field is missed up

Edited by Mano
Link to comment
Share on other sites

  • Honorable Member
12 minutes ago, sibermaster said:

Failed to create private map. why?

You need to have the correct map indexes in the same CONFIG file.
Make sure the metin2_map_capedragonhead (301), metin2_map_defensewave (358) and metin2_map_defensewave_port (359) are in the same CONFIG.

301	metin2_map_capedragonhead
358	metin2_map_defensewave
359	metin2_map_defensewave_port

CONFIG

MAP_INDEX: 301 358 359
Edited by Owsap
Link to comment
Share on other sites

24 minutes ago, Owsap said:

You need to have the correct map indexes in the same CONFIG file.
Make sure the metin2_map_capedragonhead (301), metin2_map_defensewave (358) and metin2_map_defensewave_port (359) are in the same CONFIG.

301	metin2_map_capedragonhead
358	metin2_map_defensewave
359	metin2_map_defensewave_port

CONFIG

MAP_INDEX: 301 358 359

Thanks for reply i will try.

Link to comment
Share on other sites

Announcements



×
×
  • 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.