Jump to content

Syreldar

Premium
  • Posts

    1295
  • Joined

  • Last visited

  • Days Won

    38
  • Feedback

    100%

Everything posted by Syreldar

  1. That makes no sense. You're using the same global flag to save the player's id, meaning it will get overwritten every time a player opens the letter. Also using a global flag, something which is used for events or global settings, to save a var for a player is something you totally should not do.
  2. void CActorInstance::__ProcessDataAttackSuccess(const NRaceData::TAttackData& c_rAttackData, CActorInstance& rVictim, const D3DXVECTOR3& c_rv3Position, UINT uiSkill, BOOL isSendPacket) else if (rVictim.IsStone() || rVictim.IsDoor()) { __HitStone(rVictim); } void CActorInstance::__HitStone(CActorInstance& rVictim) { if (rVictim.IsStun()) { rVictim.Die(); } else { rVictim.__Shake(100); // This is what triggers the shake, make sure it's there. } }
  3. Quality always has a price. Alternatively you can get your files from kebabmmo for free, good luck.
  4. Well, the rejoin seems to work fine.. so just fix the local coordinates?
  5. Well, I told you to change the coordinates of a map, so both root/atlasinfo.txt (client) and mapname/Settings.txt (server) need to be edited.
  6. This is not a quest issue. There's a conflict of coordinates between DevilTower and Valley of Seungryong. This bug also exists in official servers, but it's irrelevant cause they don't have a Rejoin system within the DevilTower dungeon, thus never accessing that set of coordinates globally. The conflict for the DevilTower becomes relevant at 7th, 8th and 9th floor cause they're placed in the utmost right section of the map, which, as you can see from the screenshot below, is partly inside the Valley's map sector. The server simply doesn't know where to place you., because that global set of coordinates belongs to two different maps. To fix the issue, you gotta move either the DevilTower or the Valley in different coordinates in the plane, be careful to choose a free and valid set of coordinates.
  7. Good. That fixes the first part of the issue: The party member pids not being taken into account for characters in different cores/channels. However, that still won't do, it requires more work: Your solution assumes that the party stays valid through channels, but as I previously stated, when a group member logins in a different one they will be without a party in that channel, parties are channel-exclusive. Screenshots for reference: This means that they can just change channel, do whatever they want while eluding the party checks, then log back in the old one. With my solution they can't, because a flag stays valid between different channels. Also, I have already stated that my solution was suboptimal, I simply shared my own approach while being informative about it. That said, I believe your take towards questflags is a bit of a stretch: the game is built to handle hundreds of thousands of them active and get info on them at the same time with negligible impact on the server.
  8. Starting now, I'll permanently offer a 10% Discount on my services to @ Owsap's OSF members.
  9. The quest by default has a check for GMs. If you want to trigger it as GM (keep in mind that in TEST_SERVER everyone is considered a GM), remove the first condition, otherwise, everything works as it should.
  10. Definitely one of the most competent and prepared developers around. I can only recommend.
  11. Hello, For context, this is what it's about: [Hidden Content], for each one of them. [Hidden Content]
  12. SELECT `locale_name`, `max_hp` FROM `player`.`mob_proto` WHERE `max_hp` = 0 AND (`type` = 0 OR `type` = 2); This makes you see all the monsters and metins that have a bugged max_hp value in your proto, so you can fix them manually. but, If you want to temporarily fix them all automatically, you can run this: UPDATE `player`.`mob_proto` SET `max_hp` = 100 WHERE `max_hp` = 0 AND (`type` = 0 OR `type` = 2);
  13. Yes, USE_INVISIBILITY. But I am pretty sure he also wanted that taken into account, after all taking damage and bouncing left and right while seeing no one hitting you looks pretty bad.
  14. AFF_INVISIBILITY Is the affect given by /inv, Ninjas have EUNHYUNG. So it's not necessary.
  15. 1. Clientside: Srcs/Client/InstanceBase.cpp bool CInstanceBase::IsAttackableInstance(CInstanceBase& rkInstVictim) { // else if (IsPC()) { if (rkInstVictim.IsStone()) return true; if (rkInstVictim.IsPC()) { // ADD This here: if (IsAffect(AFFECT_INVISIBILITY)) return false; // // 2. Serverside: Srcs/game/src/pvp.cpp: bool CPVPManager::CanAttack(LPCHARACTER pkChr, LPCHARACTER pkVictim) { // if (pkChr == pkVictim) // ³»°¡ ³¯ Ä¥¶ó°í ÇÏ³× -_- return false; if (pkVictim->IsNPC() && pkChr->IsNPC() && !pkChr->IsGuardNPC()) return false; // Add this here: if (pkChr->IsAffectFlag(AFF_INVISIBILITY) && pkVictim->IsPC()) return false; // //
  16. Why would you care how is in official, if that's what he wants regardless? char_skill.cpp, search: // 2. Shoot! if (f.GetVictim()) { ch->CreateFly(FLY_SKILL_MUYEONG, f.GetVictim()); ch->ComputeSkill(SKILL_MUYEONG, f.GetVictim()); } Turn into: // 2. Shoot! LPCHARACTER victim = f.GetVictim(); if (victim && !victim->IsAffectFlag(AFF_EUNHYUNG) && !victim->IsAffectFlag(AFF_INVISIBILITY) && !victim->IsAffectFlag(AFF_REVIVE_INVISIBLE))) { ch->CreateFly(FLY_SKILL_MUYEONG, victim); ch->ComputeSkill(SKILL_MUYEONG, victim); }
  17. Because your first screen shows what it looks like on metin2 by default. The screenshot with the Greatsword shows a modified version of the Hwang where only the main details are not set to opaque in the alpha channel. This is the modified Hwang texture that you want: [Hidden Content]
  18. g 385 387 1 1 0 0 15400s 100 1 2019 `g` means I'm spawning the vnum of a group, not a monster. So in this case I'm calling the vnum of the group associated with the Spider Queen. `385` `387` are the local spawn coordinates of the group. `1` `1` are the random values for the local spawn coordinates. `0` is the Z section, you don't care about that. the other `0` is the direction, since this is not an NPC, you don't care about this either. `15400` is the number of seconds in between respawns since server start time. Change it as you like. `100` is the spawn chance per tick. `1` is the number of groups to spawn per tick. and finally, `2019` is the vnum of the monster, or in this case the group, to spawn.
  19. Yes, that's perfect. What you wrote also happens to be the method I use for my dungeons. I applied two corrections to it, maybe it'll help you out. Regarding your question, I wrote it with the incremental flag because while this way of writing it is more efficient, with the incremental flag it becomes easier to understand, I chose to do it because this is an example and as such it is meant to instruct people.
  20. Why would you add a new source function for such a thing?
  21. This is a development forum, not a baby school, I have wrote an example, you obviously adapt the code to your needs. use the >= operator if you need it. If by "BEING BADASS" you mean "copy literally what illiterates did for Zodiac", then sure. But I don't see how that's relevant for the topic.
  22. Hello. 100% of the people I've seen coding dungeons or making time-based events of any sort handled `Time remaining` notices like this: This is not entirely their fault, sadly Webzen isn't exactly capable of setting a good example of how to do things right in Python, C++ and -of course- Lua. This way of doing things is very limited, initializing a new timer for every notice they wanna make is not a very efficient way of dealing with the matter. Naturally, you could implement the Official Zodiac's way of handling Time remaining, by overriding the Minimaps' interface with a new interface that has a built-in timer which works via python-quest communication, but shouldn't that be available for you, then you can do this: First things first, we'll need a single server timer, which will be of the loop type, and it will handle both the `Time remaining` notices and the actions for when the time expires. For simplicity purposes, I'll make an example for the dungeons. Now, we can either set up two full-scope variables, or defines: define TIME_OUT 3600 -- 1 hour define TIME_OUT_STEP 60 -- 1 minute Or, we can make an array that stores the information within a function, like this: function GetDungeonData() return { ["time_out"] = 3600, ["time_out_step"] = 60 }; end -- function Note that functions initialized inside quests are not global: they are only valid within their scope - the state they get initialized in. For this example, I'll make use of the first of the 2 methods I just showed you. Now, we got 2 elements: time_out, which is our time limit. time_out_step, which will be the interval in seconds in-between triggers of our server loop timer. We'll use them like this: if (TIME_OUT and TIME_OUT_STEP) then -- No reason to initialize anything if you don't want a time limit. server_loop_timer("dungeon_time_out_check", TIME_OUT_STEP, d.get_map_index()); notice(string.format("<Dungeon> Initialized. Time limit: %s!", get_time_format(TIME_OUT))) -- get_time_format - [Hidden Content] end -- if We have bound a timer to our dungeon instance and set it to trigger once every `time_out_step` seconds; This allows us to control the interval between `Time remaining` notices by changing the `time_out_step` element as we like. Now all that remains is to set our timer's trigger and make use of `time_out` and `time_out_step`, the full example code would look like this: define TIME_OUT 3600 -- 1 hour define TIME_OUT_STEP 60 -- 1 minute define DUNGEON_MAP_INDEX XXX quest dungeon begin state start begin when --[[]] with InDungeon(DUNGEON_MAP_INDEX) begin -- InDungeon - [Hidden Content] -- if (TIME_OUT and TIME_OUT_STEP) then -- No reason to initialize anything if you don't want a time limit. server_loop_timer("dungeon_time_out_check", TIME_OUT_STEP, d.get_map_index()); d.notice(string.format("<Dungeon> Initialized! Time limit: %s!", get_time_format(TIME_OUT))) -- get_time_format - [Hidden Content] end -- if end -- when when dungeon_time_out_check.server_timer begin -- Only refer to our personal dungeon instance's server timer. if (d.select(get_server_timer_arg())) then -- increase by TIME_OUT_STEP each trigger d.setf("seconds_passed", d.getf("seconds_passed") + TIME_OUT_STEP); -- If the flag equals or surpasses TIME_OUT after being increased, it means the time has expired. if (d.getf("seconds_passed") >= TIME_OUT) then -- Clear the timer as there's no more need for it to loop. clear_server_timer("dungeon_time_out_check", get_server_timer_arg()); d.notice("<Dungeon> Time expired.") d.exit_all(); else -- As long as the time hasn't expired, we just notify the dungeon about the Time remaining. d.notice(string.format("<Dungeon> Time remaining: %s.", get_time_format(TIME_OUT - d.getf("seconds_passed")))) -- get_time_format - [Hidden Content] end -- if/else end -- if end -- when end -- state end -- quest Alternatively, instead of using the `seconds_passed` flag like I'm doing (the way I showed you is more understandable and thus more proper since this is an example), you can initialize a single flag to register the starting time and make use of get_time() in between triggers. And there you have it, full control in a single timer for your time remaining notices.
  23. I'm not sure why you made this post, given you know exactly what the problem is and why it occurs. The monster doesn't spawn because your boss.txt file for that map is empty.. so fill it?
×
×
  • 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.