Leaderboard
Popular Content
Showing content with the highest reputation on 08/12/23 in all areas
-
The *getcharinfo doesn't exist. Replace: set saveMap$, strcharinfo(3); set saveX, getcharinfo(0); set saveY, getcharinfo(1); With: getmapxy(saveMap$,saveX,saveY,BL_PC); Rynbef~2 points
-
It really work thank you for your effort, now im reading the change and analyze it so next time i can do it by myself btw i start learning first the breakpoint in visual studio so if i had map crash error i easily detected,1 point
-
Let the necessary changes in the 'mob.cpp' file: change it: int mob_getdroprate(struct block_list *src, std::shared_ptr<s_mob_db> mob, int base_rate, int drop_modifier, mob_data* md) to: int mob_getdroprate(struct block_list *src, std::shared_ptr<s_mob_db> mob, int base_rate, int drop_modifier, mob_data* md, int nameid) still in the same file, in the same function, change this: if (sd->sc.getSCE(SC_ITEMBOOST)) drop_rate_bonus += sd->sc.getSCE(SC_ITEMBOOST)->val1; to: if (sd->sc.getSCE(SC_ITEMBOOST)) { int mob_id = mob->id; int item_id = nameid; int excluded_item_ids[] = {1202}; // Knife_ = 1202 int excluded_mob_ids[] = {1002}; // Poring = 1002 bool is_excluded_item = false; bool is_excluded_mob = false; for(int i = 0; i < sizeof(excluded_item_ids)/sizeof(excluded_item_ids[0]); i++) { if(item_id == excluded_item_ids[i]) { is_excluded_item = true; break; } } for(int i = 0; i < sizeof(excluded_mob_ids)/sizeof(excluded_mob_ids[0]); i++) { if(mob_id == excluded_mob_ids[i]) { is_excluded_mob = true; break; } } // Only apply the SC_ITEMBOOST if the item and mob aren't in the excluded lists if(!is_excluded_item && !is_excluded_mob) { drop_rate_bonus += sd->sc.getSCE(SC_ITEMBOOST)->val1; } } inside the loop "for (i = 0; i < MAX_MOB_DROP_TOTAL; i++) {" Change it: drop_rate = mob_getdroprate(src, md->db, md->db->dropitem[i].rate, drop_modifier, md); to: drop_rate = mob_getdroprate(src, md->db, md->db->dropitem[i].rate, drop_modifier, md, md->db->dropitem[i].nameid); in archive 'mob.hpp' change it: int mob_getdroprate(struct block_list *src, std::shared_ptr<s_mob_db> mob, int base_rate, int drop_modifier, mob_data* md = nullptr); to: int mob_getdroprate(struct block_list *src, std::shared_ptr<s_mob_db> mob, int base_rate, int drop_modifier, mob_data* md, int nameid); and finally in the 'atcommand.cpp' file, change it: int droprate = mob_getdroprate( &sd->bl, mob, mob->dropitem[i].rate, drop_modifier ); to: int droprate = mob_getdroprate( &sd->bl, mob, mob->dropitem[i].rate, drop_modifier, nullptr, mob->dropitem[i].nameid ); I had to use a breakpoint in visual studio to find out that the md->mob_id was null and that's why the @mi command was closing the map-server. soon I realized that inside the function there is already mob data just by accessing the 'mob->id'. the item_id conflict I solved by adding a new parameter, consequently it is mandatory to change the parameters for the other calls, maybe there is a better way to access the item_id but this way works great for me.1 point
-
I found the issue about @mobinfo but i use the excluded_item_ids since both are same concept and it work, when i use @whodrops 1202 the Knife rate will not affected on SC_ITEMBOOST but when i use @mi the Knife is affected by SC_ITEMBOOST all i can say is its working we need to find the logic on @mi command thanks1 point
-
For mob_id: If you're in a context where a monster is being handled (like in the drop function), you might have access to a mob_data structure or something similar, from which you can get the monster ID. It might look something like this: int mob_id = md->class_; 'md' is a commonly used abbreviation for mob_data in rAthena source code.1 point
-
- script DryadKillCounter -1,{ OnPCKillEvent: if (killedrid == DRYAD_MOB_ID) { .@kills = killcount(DRYAD_MOB_ID); if (.@kills == 100) { set saveMap$, strcharinfo(3); set saveX, getcharinfo(0); set saveY, getcharinfo(1); warp "sec_pri", X_COORD, Y_COORD; // Teleport player to sec_pri (Replace X_COORD and Y_COORD with actual coordinates) } } end; } sec_pri,X_COORD,Y_COORD,5 script Returning NPC 722,{ if (killcount(DRYAD_MOB_ID) > 99) { mes "I noticed you've killed 100 Dryads in um_fild01."; mes "Do you want to return to where you were?"; next; if(select("Yes:No") == 1) { set killcount(DRYAD_MOB_ID), 0; // Reset the kill count for Dryads warp saveMap$, saveX, saveY; // Return player to their saved location } } else { mes "You have no reason to interact with me."; } close; } pay attention to items: X_COORD Y_COORD DRYAD_MOB_ID Just make the appropriate substitutions1 point
-
if (sd->sc.getSCE(SC_ITEMBOOST)) { // List of item IDs and mob IDs to exclude int excluded_item_ids[] = {1202}; // Knife_ = 1202 int excluded_mob_ids[] = {1002}; // Poring = 1002 // Check if the current item_id and mob_id are not in the excluded lists bool is_excluded_item = false; bool is_excluded_mob = false; for(int i = 0; i < sizeof(excluded_item_ids)/sizeof(excluded_item_ids[0]); i++) { if(item_id == excluded_item_ids[i]) { is_excluded_item = true; break; } } for(int i = 0; i < sizeof(excluded_mob_ids)/sizeof(excluded_mob_ids[0]); i++) { if(mob_id == excluded_mob_ids[i]) { is_excluded_mob = true; break; } } // Only apply the SC_ITEMBOOST if the item and mob aren't in the excluded lists if(!is_excluded_item && !is_excluded_mob) { drop_rate_bonus += sd->sc.getSCE(SC_ITEMBOOST)->val1; } } You can test this or at least get an idea to follow1 point
-
1 point
-
I don't think this is possible without a source code change, since there is no event to know when a specific mob is attacked by a player.1 point
-
prontera,167,163,4 script Lotto Girl 72,{ mes "[ " + .npc_name$ + " ]"; mes "I'm " + .npc_name$ + "! I'll exchange"; mes "Random Prizes for every"; mes "^ff0000" + F_InsertComma(.pull_price) + " zeny^000000."; next; mes "[ " + .npc_name$ + " ]"; mes "Our Grand prize is:"; mes "^ff0000 x1 TCG Card^000000"; mes "^ff0000 x1 Costume set^000000"; mes "Consolations are:"; mes "^ff0000 x?? Gold Coin^000000"; mes "^ff0000 x?? Gold^000000"; mes "^ff0000 x?? Treasure Box^000000"; mes "^ff0000 x?? Oridecon^000000"; mes "^ff0000 x?? Elunium^000000"; mes "And many more!!"; next; mes "[ " + .npc_name$ + " ]"; mes "Do you want to pull?"; next; if(select("Sure!:No.") == 2) { mes "[ " + .npc_name$ + " ]"; mes "Come back if you change"; mes "your mind."; close; } mes "[ " + .npc_name$ + " ]"; mes "How many pulls do you want?"; next; .@range = input(.@pullAmt, .min_pulls, .max_pulls); if(.@range != 0) { mes "[ " + .npc_name$ + " ]"; mes "The " + ((.@range > -1) ? "maximum" : "minimum") + " number of pulls is " + ((.@range > -1) ? .max_pulls : .min_pulls) + "."; close; } if (Zeny < .pull_price * .@pullAmt) { mes "[ " + .npc_name$ + " ]"; mes "You don't have enough zeny."; close; } freeloop(1); for(.@i = 0; .@i < .@pullAmt; .@i++) { if (Weight * 100 / MaxWeight >= .weight_cap) { mes "[ " + .npc_name$ + " ]"; mes "You can't do anymore"; mes "pulls because you are"; mes "nearing your weight limit"; close; } Zeny -= .pull_price; .@priceNo = rand(0, getarraysize(.prices) - 1); .@priceIdx = .@priceNo * 4; if (rand(1, 100) <= .prices[.@priceIdx]) { .@itemId = .prices[.@priceIdx + 1]; .@itemAmt = rand(.prices[.@priceIdx + 2], .prices[.@priceIdx + 3]); if(.prices[.@priceIdx] <= .announce_limit) { announce("Hey! " + strcharinfo(0) + " just received " + getitemname(.@itemId) + " x " + .@itemAmt + " from " + .npc_name$ + "!", bc_all); specialeffect2(248); } } else { .@itemId = rand(.default[0], .default[1]); .@itemAmt = rand(.default[2], .default[3]); } getitem(.@itemId, .@itemAmt); } freeloop(0); mes "[ " + .npc_name$ + " ]"; mes "Here you go!"; close; OnInit: .npc_name$ = strnpcinfo(1); .pull_price = 50000; .announce_limit = 5; .weight_cap = 90; .min_pulls = 1; .max_pulls = 500; //<Chance in %>, <ItemID>, <MinAmount>, <MaxAmount> setarray(.prices[0], 1, 35031, 1, 1, // demoniac mid 1, 35081, 1, 1, // demoniac upper 1, 35099, 1, 1, // demoniac low 2, 7227, 1, 1, // tcg 5, 7539, 1, 2, // diablo coin 8, 969, 1, 3, // gold 10, 604, 1, 3, // deadbranch 8, 7444, 1, 3, // treasurebox 8, 12208, 1, 2, // battle manual 20, 985, 3, 8, // elu 25, 7063, 2, 5, // alice apron 25, 7047, 2, 5, // soft feather 20, 984, 3, 8, // ori 15, 748, 1, 3 // witherless ); //<MinItemID>, <MaxItemID>, <MinAmount>, <MaxAmount> setarray(.default[0], 901, 926, 5, 15); delwaitingroom; waitingroom("Try your Luck?", 0); }1 point
-
Being doing some behind the scenes stuff lately, most of which is hard to show off. For starters, I've been fiddling with autocast. I've mentioned before that I always felt Professor felt mediocre and part of this is because autocast kind of sucks. Whenever you trigger an autocast, it cancels your attack and you just pose, similar to casting the spell normally. For Professor, this makes autocast kind of pointless since you can just cast the spell normally and attack with free cast and you get a similar effect, except you call the spell at the maximum level. I've always felt that they way it should work is that you should keep attacking and the spell should just go off, so autocast is just like bonus DPS on top of your regular attacking. This is actually extremely hard to change, because the posing actually takes place client-side, and it does not respect any of the fields sent in the packet like amotion. There is a flag that is sent to skill_attack that can suppress the casting animation, but it doesn't work for multi-hit or NPC skills (ie, almost every spell that can be autocast) and it has its own share of problems. My first change to try to change this was to shift the "src" of the attack to the target. For mobs, this works perfectly, because mobs don't have casting animations. We can now auto-attack and throw bolts without stopping! The problem is PVP. If you use this approach for PVP, the person being hit by the bolts does the casting animation instead! This is obviously not what we want. There isn't a great solution to this. What I've done is to change the damage type to splash when used against a player (this is also how the animation flag works). However, this has several issues. When casting a multi-hit spell, it only hits once (for bolts, all the bolts come down at once). It also deals the damage instantly, rather than after the animation. This is not ideal, but I don't think there's any other way without changing the client. Notice the 501 damage from the bolts already happened a bit ago even though they haven't hit yet. Speaking of, I've been working on PVP. I wrote a pretty simple script to add some PVP arenas, which I've added to this post if anyone wants it. It does require you to set the mapflags on these maps (pvp_n_1-5, pvp_n_2-5, and pvp_n_3-5), all of them need to have the nightmare flag removed and the nopenalty flag added, and the first arena needs noparty, and the last needs noexp and noloot. The first two arenas are pretty straightforward, the first is FFA and the second is Team-Based. The third arena is fun though, as it also spawns some enemies! It can get pretty chaotic, but you might be able to use the Monsters to your advantage. You can also just use this area to test out your builds without any risk, since you don't lose exp if you die here (though you don't get exp or drops either). Finally, I also added a pity system for cards. Whenever a card fails to drop from a monster, the rate very slightly increases until the card drops, at which time it resets. This increase is server-wide and it doesn't persist if the server is shut down, but I think it makes card hunting feel a lot better. It doesn't make a huge amount of difference most of the time, but it makes it very unlikely to go super dry on getting a card. The chance of taking like 4x the expected amount of kills to get a card is now effectively nonexistent. Programming-wise this is actually pretty simple. I might maybe eventually make a topic about it if people want it. pvp.txt1 point
-
O ACT Editor, there's a little feature on the right that is meant for adding sounds on a specific frame. All you need to do is to add your own (that must be also patched on your wav/ folder on your GRF or data folder). Click on the list and then on add new... A pop-up will show asking for the WAV name, I like to add it with the file extension, just to be sure it will get the correct file: After that, go on all frames (yes, it must be on the specific frame) you want to add the sound and select it on the list we previously discussed about. Patch your sounds to your GRF/Data and test it InGame. HINTS: • Usually, the best way to make a sound fits with the animation is setting it to play on the frame prior the action, as an example, a footstep will sync better if it's set to play one frame prior to the foot reaches the ground. • Sounds set on the first frames usually will not be played, go on the second or third frame of the animation to be sure. • You can play multiple sounds on consecutive frames to mix their effects. That's all, folks!!1 point