Jump to content

Syreldar

Premium
  • Posts

    1295
  • Joined

  • Last visited

  • Days Won

    38
  • Feedback

    100%

Everything posted by Syreldar

  1. It means your qc does not support defines. Keep in mind that I wrote that in 5 minutes spare, didn't even doublecheck. The statement's structure is fine, the error was that I wrote "to_kill" (the flag we use to store the AMOUNT of monsters to kill), instead of "mob_vnum" (the flag we use to store the vnum of the monster to kill). so the correct statement is: when kill with not npc.is_pc() and npc.get_race() == pc.getqf("mob_vnum") begin which translates to: "When you kill an entity which is not a character and its vnum is equal to the vnum of the monster we need to kill, trigger the code inside of the statement" I have edited the original message. Your "fix" Makes no sense, it works because effectively the second part of the condition just returns "true" since it's a value > 0, so it's like it's not even there; but you're not checking for the vnum at all, meaning that code will trigger on any entity which is not a character, so every monster or metinstone.
  2. Some suggestions and heads-up for both of you. 1. Handle your states better, and also the when conditions. Players always need to be able to see the reason(s) why they can't do a quest at that moment. 2. Simplify your time checks. 3. Defining variables inside of a state is not possible, the only accepted things inside of a state are "when" triggers and "function"s. Currently, we have 3 types of variables at our disposal: local variables. quest-bound, also known as "defines", their scope is the whole quest. globals, non-local variables valid throughout the whole env. 4. "when" statements need their triggers to be specific, meaning even if you could assign a random npc to a variable named "A", writing "when A.kill" won't work. At most you can assign a specific vnum to a variable (use the questnpc.txt file for reference on how that works); or, you can use a "define" to achieve the same result, but again only on a static vnum, not a random or dynamic one. The only exception to this is the "when kill with" method, which creates a "notarget" folder and allows the trigger to work with dynamic code, but you still need to save your randomly generated vnum somehow in order to call it later and work with it. Following all my suggestions and decent knowledge of the language should end you up with something like this: [Hidden Content]
  3. 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. Never forget something like the in_dungeon check I made in the kill trigger, it's very important that every code gets only triggered in our dungeon and not in other dungeons that share a similiar flag name for the level. define DUNGEON_INDEX 999 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 function in_dungeon(map_index) local pc_index = pc.get_map_index(); return pc_index >= map_index*10000 and pc_index < (map_index+1)*10000; end -- function when dungeon_warp_to_2floor.server_timer begin local instance_arg = get_server_timer_arg(); if (d.select(instance_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", 1, instance_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 local instance_arg = get_server_timer_arg(); if (d.select(instance_arg)) then if (d.unique_get_hp_perc("2floor_metinstone") <= FLOOR2_METINSTONE_HP_THRESHOLD) then clear_server_timer("dungeon_2floor_control_metinstone_hp", instance_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", 3, instance_arg); 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 local instance_arg = get_server_timer_arg(); if (d.select(instance_arg)) then if (d.count_monster() == 0) then clear_server_timer("dungeon_2floor_control_monster_count", instance_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 -- when when kill with npc.get_race() == FLOOR2_METINSTONE_VNUM and dungeon_name.in_dungeon(DUNGEON_INDEX) 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 local instance_arg = get_server_timer_arg(); if (d.select(instance_arg)) then d.setf("level", 3); -- end -- if end -- when This snippet behaves exactly the same and does not require any C++ input.
  4. Look... no. There are things you shouldn't use a quest for, this is one of them.
  5. when 24930.kill with pc.in_dungeon() and pc.get_map_index() >= 40000 and pc.get_map_index() < 40000+10 begin -- ????? This check means that if there are more than 10 active instances of that specific dungeon, it'll stop working. I'd start by fixing that. Regarding your question, you can write this: d.kill_all() d.clear_regen() if (party.is_party()) then for _, pid in ipairs({party.get_member_pids()}) do q.begin_other_pc_block(pid); -- pc.give_item2(71084, 50) pc.give_item2(71085, 50) pc.give_item2(70024, 5) pc.give_item2(50300, 2) pc.give_exp2(200000) -- q.end_other_pc_block(); end -- for else pc.give_item2(71084, 50) pc.give_item2(71085, 50) pc.give_item2(70024, 5) pc.give_item2(50300, 2) pc.give_exp2(200000) end -- if/else Although I'd write a function.
  6. 25/10/2022: Fixed IntToRomanStr typo
  7. You just made one of the oldest classic metin2 italian memes reality. Thank you.
  8. My guess is that the index you're using for that specific hair is probably greater than 32767 for some reason. If that's the case, you got two solutions: Either lower the hair index, both in the protos and in the root msm. (Recommended solution) Or, apply this query ALTER TABLE `player`.`player` MODIFY COLUMN `part_hair` int NOT NULL DEFAULT '' AFTER `part_base`;
  9. A few advices: 1. If you're trying to make the player select their skill-group, there's no reason to select the race. 2. This is not a function, "return false" means and does nothing here; "return" also means nothing since you're using if and else, nesting can be improved but that's about it. 3. Loops are your friends, use them. Useful data you can add to your questlib or a Global var file: NO_SKILL_GROUP = 0; BASE_SKILL_LEVEL = 1; MASTER_SKILL_LEVEL = 20; GRAND_MASTER_SKILL_LEVEL = 30; PERFECT_MASTER_SKILL_LEVEL = 40; -- Essentially, pc.get_job()'s output. WARRIOR = 0; NINJA = 1; ASSASSIN = NINJA; SURA = 2; SHAMAN = 3; LYCAN = 4; WOLFMAN = LYCAN; -- Essentially, pc.get_skill_group()'s output. DOCTRINE_1 = 1; DOCTRINE_2 = 2; WARRIOR_BODY_FORCE = DOCTRINE_1; WARRIOR_MENTAL_FIGHT = DOCTRINE_2; NINJA_BLADE_FIGHT = DOCTRINE_1; NINJA_ARCHERY = DOCTRINE_2; SURA_WEAPONRY = DOCTRINE_1; SURA_BLACK_MAGIC = DOCTRINE_2; SHAMAN_DRAGON_FORCE = DOCTRINE_1; SHAMAN_HEALING_FORCE = DOCTRINE_2; LYCAN_INSTINCT = DOCTRINE_1; -- A list of class names. DOCTRINE_NAME_LIST = { [WARRIOR] = { [WARRIOR_BODY_FORCE] = "Body-Force", [WARRIOR_MENTAL_FIGHT] = "Mental-Fight" }, [NINJA] = { [NINJA_BLADE_FIGHT] = "Blade-Fight", [NINJA_ARCHERY] = "Archery" }, [SURA] = { [SURA_WEAPONRY] = "Weaponry", [SURA_BLACK_MAGIC] = "Black Magic" }, [SHAMAN] = { [SHAMAN_DRAGON_FORCE] = "Dragon Force", [SHAMAN_HEALING_FORCE] = "Healing Force" }, [LYCAN] = { [LYCAN_INSTINCT] = "Instinct", } }; Quest file:
  10. You can use Fliege files to open a server, I have no idea what "They're outdated" means in this context cause no matter how "outdated" something is, you could open a server with 2007 rain files if you wanted to, so.. I guess the last sentence was an attempt to write "Does anyone know to correctly start a server?", yes, you can still do it with the files you are using this very moment. You just need, well, to buy a server.
  11. That is not how it works. "*.use" triggers only work if the item's type is 18 (ITEM_QUEST), while a Potion/Elixir's type is 3.
  12. Yeah, everything is possible. But he didn't ask if it was possible to code a different type to satisfy his request, he asked if there was a type among the already existing ones which could satisfy his request. <_<
  13. So what you're saying is that humanity as a whole is a big scam since literally every human being prefers the least effort way of doing things. Not so far from the truth, but still delusional.
  14. I've already explained to you that these people could just look for the solution on the internet, since it's free. You don't create scammers, it's human nature to try and get advantages with the least effort. What you're saying makes no sense.
  15. I don't really understand your point. Everyone can make fresh lemonade. This doesn't stop people from making stands where they sell theirs. Are lemonade stands scammers, by that logic? Of course not, cause while everyone can make lemonade at home you might not have access to it while walking 40 degrees under the scorching sun to go to your shitty job, so you'll gladly pay for it on the go. This is how it always worked, ever since the beginning of society, in fact. If you got money but no time = you pay. This applies both to services and everything else in life, and it's also the reason why item-shop exists in games. In this case, nobody can stop you from asking to get paid to fix someone else's issue, cause they're essentially paying for your knowledge, no matter how you got it and no matter if it's available for free on the internet. If you don't have money to pay people to solve the issue, then why not solve it yourself? Why are you here complaining about people getting paid for it instead? You said it yourself that this information is available to everyone for free, so why? In the end the people who are gonna pay are people that got money and can't be arsed looking through the solution to their issue and how to apply it. This tells me you're simply projecting your own personal issues and complexes onto this bigger picture, which is not something you should do. Logically speaking your pov makes no sense at all.
  16. No. But, you can write an exponential formula easily via quest.
  17. 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.
  18. > Even little Anya is confused by such a question. Assuming you implemented it correctly and you didn't change coordinates, then you should /warp 602 4186, not 2600 2600
  19. The table_shuffle function from my functions file does what you want. --[[ Returns: The shuffled version of a table. Example: local table_ex = { [1] = "cow", [2] = "bird", [3] = "dog", [4] = "cat", [5] = "monkey" }; table_shuffle(table_ex) -> returns { [1] = "monkey", [2] = "cow", [3] = "bird", [4] = "cat", [5] = "dog" }; (Since it's random, some values may be the same as before.) ]] table_shuffle = function(table_ex) local table_ex_copy = table_ex; local rand = 0; for i = table.getn(table_ex_copy), 2, -1 do rand = math.random(i); table_ex_copy[i], table_ex_copy[rand] = table_ex_copy[rand], table_ex_copy[i] end -- for return table_ex_copy; end -- function
×
×
  • 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.