-
Posts
65 -
Joined
-
Last visited
-
Days Won
19
Content Type
Profiles
Forums
Downloads
Jobs Available
Server Database
Third-Party Services
Top Guides
Store
Crowdfunding
Everything posted by Tero
-
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
It's funny that every time I say I'm done I still constantly make small tweaks, mostly still to monster skill use rates and stats. Something I've been looking at lately is monster sizes, which are all over the place and make no sense 95% of the time. For example, Dullahan is Medium size, while Loli Ruri and Bloody Murderer are Large size. Okay, that kinda makes sense, they are bigger than Dullahan. But wait, Argos is Large size. Is that because it's comparatively large for a bug? I mean, sure, it's huge for a spider, but it's much smaller than Dullahan. It's also smaller than Mantis, which is considered Medium. Rocker, Metaller, and Ashhopper are even bigger and are still Medium. Argiope is Large, even though Centipede, which uses an edited version of its sprite, is only Medium. Giant Hornet is Small, even though it has the word "Giant" right in its name. The list goes on and on. It would be impossible to ever get them to be totally consistent, but I think it's getting a little better. I'm sorry Knights and users of Size cards if this disrupts your farming. I'm glad to hear you've been enjoying the topic. I will note that in Ragnarok time, 10 seconds is an eternity. I actually once had a boss (Lost Dragon) that had a 10 second cast skill, not even intentionally, but because I didn't see it when it was editing its skill list. This boss then became absurdly easy to solo by simply running around, waiting for it to try to cast that skill, beating on it for 8 seconds, then dodging the skill and repeating the process. Of course, it would help if the skill was interruptable (then it would at least fight back), but that super slow charge bar is still basically a "come hit me" indicator. Generally, peak human reaction time is around 120ms, but in Ragnarok the network latency time plays into this because the boss starts casting when the packet is sent, not when you receive it. Generally though, I tend to use around 700-1200ms as charge time on spells I want to be fairly reactable, and 500ms on spells that you can avoid if you're really paying attention. Lower cast times are basically only for skills you can only dodge if you're already moving or hovering over the "Back Slide" / "Time Slip" key. But that's fine, you're not supposed to be able to dodge everything. A key element of Ragnarok's success in my opinion is that it's only semi action-based. You can dodge some stuff, but not everything, you're still definitely going to be hit, which makes both your skill as a player and your build and equipment vital to success. In a lot of games where skill has a very large impact (generally where almost every attack is potentially avoidable) gear tends to be kind of irrelevant, or at least you only care about offense, and they just don't have the endless replayability that Ragnarok has. This is actually a good segway though because it lets us talk about Boss Design, which is actually something I've never really talked about until now. My server has over 100 bosses, and I've pretty sure I've tweaked the skill lists of all of them a few times, so I guess I can talk about some of the bigger changes to bosses and a bit of how I generally try to design them. For starters, one change I've made pretty much across the board is that bosses have far longer cooldowns on their minion summoning skills. In base, many of them can cast these every few seconds, so killing their minions is almost a total waste of time, but on my server these cooldowns are much longer. For most bosses, the cooldown on their minions is 60-120 seconds, depending generally on how hard their minions are. This makes killing them pretty viable, especially if you're planning to facetank the boss. A couple bosses have faster minions, but they're generally very weak. Dracula can call his bats every 20 seconds, but they're so wimpy that you can actually abuse "when being hit" cards to farm them. Another skill that a ton of bosses have in their lists, which is in most cases outright gone is Teleport. Of course, they still have their Rude Attack teleport, but many other bosses can Teleport every 20 seconds or so, which is unspeakably annoying, because you spend 2 minutes finding them again, hit them once, then they just do another teleport. A few bosses can still do this, generally with a cooldown of about 2-5 minutes, but most can't. There are a couple skills like Crimson Marker and Wrath of the Sun, Moon, and Stars (which seals teleporting and works on bosses) that you can use to counter the ones that can still do it. Most bosses also can no longer cast Heal, but a few still can. So what about the skills bosses can use? In most cases it's still kind of similar to base, but with a few additions and deletions here and there. For the bosses that are totally original, it's generally just based on what I think they should be able to do. For example, let's take a random look at Anglerfish, which is an original boss. Here's a quick look at his skill list: His mob is 2 Tacnu, on a 2 minute cooldown. Tacnus are kind of scary upclose fighters. His standard spells are Lightning Bolt, Thunderstorm, Chain Lightning, and Holy Light. He can cast all of these near-constantly and he has high INT, so this is much of his offense. He also has level 8 waterball, though his waterball is actually interruptable. Obviously, high level Waterball is something you really don't want to be hit with since it hits like 100 times. His melee attacks are Bleeding, Critical Wound, Blood Drain, and Jupitel Thunder (although Jupitel is a spell, he only uses it in melee range). These are less threatening than his spells so melee is a good option when his mob is down. He has Static Field, which is a new spell that was mentioned earlier, this creates damaging electric zones on the ground that can paralyze you. His cooldown on this is pretty short too, so you may have to move him if he spams a lot of these. He has Wide Confuse, which is annoying, as this makes it very hard to move around. You probably want some way to heal this off or be immune to it. Finally, he also has Reflect Shield, though it's a low-level version and on a long cooldown. Obviously, you have to be pretty careful when this is up. So what's the general idea on how you deal with this? For starters, Lightning Armor is pretty strong. It both protects you from most of his spells and gives some defense against Water Ball. If you want more elemental defense you could take additional lightning or water defense, or just MDef in general. His physical attacks aren't that scary if you can get rid of the Tacnus. You probably also want confusion immunity. Then you just attack with strong Earth element stuff or criticals or something, though you may want to be careful of EDP in case he puts reflect shield up and you instantly delete yourself. This is sort of my boss design philosophy in a nutshell. The idea is that you want to know what a boss does, then create a setup to counter that. Since RO gives you so many options to work with, there's almost nothing that's insurmountable with all the tools at your disposal. As such, I basically never worry about whether or not a boss is "too hard" because I know someone will find a way to do it. Worst case there's always boss cards, which can generally turn you into a god with just 1 or 2 of them. Wow, this got surprisingly long, and I haven't even gotten to new skills yet, of which there's a couple. For starters, there's a bugfix. Here's a fun experiment. Play a Rogue and equip a bow. Run away from an enemy, then take a shot at them and use Back Slide. Assuming you clicked directly on them without moving anywhere else first, you'll slide TOWARDS the enemy! What is this "Front Slide" madness?! We only slide back around here! The problem here is that the game doesn't update the user's facing direction when you attack. This is easily fixed by adding this code to unit_attack, unit_skilluse_pos2, and unit_skilluse_id2 (probably somewhere towards the middle of the method, after the validity checks) // make the user face the target if (src != target) unit_setdir(src, map_calc_dir(src, target->x, target->y)); You now properly slide away from your target after attacking. I can't believe it took this long for this glitch to be found. Bow Rogue really is that bad, I guess. Onto new skills. For some time, I've felt that a few classes were a little low on skills, but at the same time I didn't want to give them a ton of new stuff because I didn't want to adjust the balance too much, so it took some time to come up with an appropriate adjustment. Lord Knight now gets Trample. This is a skill I was looking at for a long time. I like that it counters Trap cheese, but I also really don't like the idea of Paladin having it. Paladin is already almost unkillable and having them running around deleting your traps would almost certainly be too oppressive for Hunters. Surprisingly it took me a long time to come up with the rather simple solution of just giving it to Lord Knight instead. It's still a good skill, but it doesn't mesh nearly as well with what Lord Knight wants to be doing, they typically just want to use Berserk and rush the Emperium, which of course prevents you from using Trample since you can't use skills during Berserk. LK is actually deceptively less tanky than you'd think a lot of the time without Berserk, especially where magic is concerned, and Trample has cast time and is even uninterruptable, so you're probably going to have to commit at least some of your build to this if you want it to be effective. I think it's probably best for Blade Beam LKs who might be running Uninterruptable Cast anyway, but that's sort of a niche build and it could probably use the help. Also, I love how the Peco does a little stamp when you use this skill. Speaking of Paladin, they now get Prestige, which is renamed to Divine Will (and has a somewhat weaker effect). Paladin is a funny class in that it got an absolutely massive buff when I first started working on the game via the reworked of Pressure, and I've had to gradually scale back their power to prevent them from being a master of all. As such, while other classes kept getting new skills, Paladin kind of fell behind and now has among the lowest total skill costs of any class, which is the main reason they get this new buff. Divine Will gives you a small boost to VIT Def and a chance to dodge spells. This is a Royal Guard ability, and of all the third classes, Royal Guard probably has the least skills that I've ported over, mainly since I find a lot of their skills really boring and the ones that aren't boring give massive boosts to sustain that Paladin absolutely shouldn't have with the Pre-RE Def formula. Even this skill is maybe kinda pushing it, but it's buried pretty deep in the tree so you're probably not getting it on Magic-oriented Paladin, so it primarily exists to make non-magic Paladin a bit more bulky against spells. Also, the most interesting thing about it is that at level 6+ it becomes a party-wide spell, and I always find team buffs to be interesting. While Paladin kinda doesn't care about getting some flat VIT Def, to a class like Wizard this could be pretty big. Champion also now has a new skill in Full Throttle. On base, this is a skill that everyone gets, but here it's limited to Champion. It's actually an even better skill than in the base game, it retains its "heal to full and get boosted stats and move speed" effect but with no downsides whatsoever, as the rebound debuff is eliminated. Instead, it has a totally different drawback. To use it, you have to be in Fury Status, which it removes, and you can't cast Fury again while it's active, so no Boosted Asura for you (unless you're using Combo Asura and lol Combo Asura). This also means there's an inherent limit to how often you can get the heal, since it has to wear off before you can cast Fury again and thus recast it. This might give you some incentive to only use the level 1 version, which gives almost no stat boost, but doesn't last very long so it's a more reliable heal, though the big stat boost on the level 10 version is also appealing. Either way, it gives Monks something else to do besides combos and Asura, which has always been a challenge. Oh, speaking of Fury / Critical Explosion, it also now shows a status icon that shows you how much time it has left. I've been going through the game and fixing most of the statuses that didn't have this by swapping them to unused EFSTs. Very tech-savvy users might know that Fury's original EFST, despite not having any description, is responsible for the colour change that accompanies Fury's animation, though I ensure that you still get this by also sending Fury's EFST in status_change_start. This also finally allowed me to fix Bard / Dancer's Up Tempo not displaying the quicken afterimage. Last, but definitely not least, we have Whitesmith. I've long felt Whitesmith was one of the most dull classes in the game, and while the new skills have helped a lot, I still felt it was missing something fun. For a long time, I've wished Blacksmith could use more of the weapons it can forge. I'd like the class to be able to use 2 Handed Swords, but this is not attainable without Client Modification. Even if we give them a sprite file for using 2 handed swords, they will always use their Attack2 animation for this weapon type, which is a punch, so it will never look good. Maybe you could make a spear animation for that, but hey, if they already have a decent looking Punch animation, why not let them use Fist-type weapons? Fist has always felt like a bit of an underappreciated weapon type because even though Priests can use it, they basically never want to, but a Brawler like Blacksmith might get some use out of it! Since it just uses Attack2's animation it looks perfectly fine with no adjustments too. Of course, the second I decided to let Whitesmith use Fist Weapons I knew what the new attack had to be. RocketPunch.mp4 GET OVER HERE! This is a heavily reworked version of Mechanic's Knuckle Boost. Obviously, the biggest change is that it now pulls the target towards you, which is a cool effect that nothing else in the game currently has. Besides its obvious PVP uses, I think this is an interesting way to increase Blacksmith's tanking skills, since they can now pull enemies towards them that might try to target backliners. It's also quite deliberate that the pull effect isn't optional - this isn't intended to be a godlike kiting skill or replace the function of Cart Cannon, it's primarily to get enemies in range for a melee beatdown faster. On a technical level, you might notice that the pull effect isn't instant, it occurs after the damage. Most skills that do knockback actually inflict the knockback before the damage, but in this case this would cause the actual projectile to visually miss, which is very lame, so here the pull effect is a "timerskill" that occurs 200ms after the damage packet. There's also a bit of a weird issue where this attack normally locks the Whitesmith into a strange hammer animation that they can't directly attack out of, which is why the skill does 2 hits, with the second being a normal attack packet. It took a deceptively long time to get this skill working properly, but I'm very happy with the result. Well, that's it for now. This is probably the end of major skill changes, though I say that every time. Still, there's now not really any classes where I'm unhappy with their skill selection, which is a good feeling. It took a long time to get here. -
I tried for like an hour, I couldn't get it working either. The issue was trying to list what costume items you have equipped, getequipisequiped doesn't seem to work properly if the slot is a costume slot. This is unchanged in latest rathena and I wasn't able to figure out why it's not returning the right values, so I'm stuck.
-
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
It's hard to believe it's been almost 2 full years since I started this thread. I continue to make small tweaks here and there, like the occasional new enemy or tweaked card or skill effect, but not much that's too major. At a certain point, you have to know when to say "it's done!". I've also started working on a new project that is even more ambitious that I can't talk about, but I hope that someday everyone will know about it. One of my biggest bugbears with Ragnarok tends to be monster skill lists. I'll just be fighting some random mob, minding my own business, and all of a sudden, oneshot by sonic blow! Where did that come from?! It'll turn out that this mob has level 5 Sonic Blow in its skill list but only uses it 5% of the time. I will typically adjust this to be something like level 2 Sonic Blow but used 15% of the time. I also typically make weaker skill use rates more like 20 or 30%. This generally has the effect of making the mobs somewhat harder in general, but there's less random one shots. I also often give mobs with very limited skill lists a few new skills, especially if they're otherwise powerful or give a lot of exp. (Mobbing up tons of anolians may be hazardous to your health) In terms of slightly more major changes, I've also been taking another look at Star Gladiator. That was one of my first major reworks and over time it has slightly fallen off in terms of total skill point count, but I also think it plays really well so I don't want to change it too much. Something that's kind of unique about Star Gladiator is that even beyond your skill point allotment, much of the build comes from the maps and monsters you select with it, so even if builds tend to be somewhat samey there's still room for personal expression. I also definitely don't want it to be the case that the optimal Star Gladiator build is just to focus on one of the Sun, Moon, or Star sets and ignore the others. But at the same time, with 80 skill points you will be able to max almost every relevant skill and I don't like that either. So I figured if it was going to get some kind of new skill, it'd have to be pretty situational and not necessarily build defining. I had thought for some time about giving Star Gladiator a set of new kicks, similar to the spells that it has, that would function similarly to the Star Emperor Kicks and only be usable on their respective maps, but I feel like this would be too centralizing. That kick would almost certainly be your best offensive option and it makes playing the class outside of your special maps feel even more lame. So instead, I decided to give it another standard Taekwon kick that you can use anywhere. Enter Chain Kick. By itself, Chain Kick is kinda trash. It's the weakest of all the Taekwon kicks, and it does 2 real hits, which means it gets hit by defense reduction twice. Its only notable trait is that it can crit, which is not terrible if you're running a crit Star Gladiator (which is secretly really good), but it's not intended to be amazing by itself. What's really notable about it is that it can be linked into any of the other Taekwon kicks after it hits. One of the things I like about Star Gladiator as a class is that it's one of the only classes where the skills you take in your first class really matters. The choice of whether to run 2 or 3 different kicks is important, as well as what those kicks are, but for some time I think it's clear that 3 kick builds are slightly better. Chain Kick throws a wrench into this calculation, since it can basically allow you to use one or your other kicks twice as often, and it can do that even at level 1, which only requires 2 skill points invested (you also need the stance). In particular, this makes Whirlwind Kick way better, since it can now act as a much more reliable AOE with Chain Kick doubling its activation rate. Of course, you do have to spend your precious Star Gladiator points to get it if you want it, and you also really want to spend those points elsewhere. It's an interesting option at least, I think. We also haven't ever really talked much about Union Mode for Star Gladiator, which isn't surprising because it's kind of a forgotten part of the class. I did buff it a long time back by having it no longer drain your HP to use (it now consumes SP instead), but it's still a bit underwhelming sometimes. I had toyed around for a while with the idea of it having an exclusive skill, which I was originally going to make Nova Explosion before I realized I already assigned that visual effect to the Stars magic attack. While looking through effects, I found this cool black Esma-like effect, and that gave me the idea for Eclipse Kick. Eclipse Kick is a Union-only kick that works a bit differently than the others. It does not have a stance, instead, you can link it after any of the 4 standard Taekwon kicks. It hits quite hard, though it takes a LOT of SP, and of course if you run out of SP you exit Union mode. It also makes you go through the opponent, and I've always loved visual effects where you end up on the other side of your target. They just look badass. Since it's hard to get a feel for what this does in a single screenshot I decided to take a full video of the full Chain Kick -> Regular Kick -> Eclipse Kick combo. Rathena made the resolution on this super big for some reason, it was originally like half this size. EclipseKick-8.mp4 Sure, this is not that much damage, but this character also isn't geared out at all and this is also only level 1, it goes up to level 5. With full investment it hits like a truck. Incidentally, the one thing I haven't been able to figure out is how to get that Blue Starburst to appear for the new kicks. I suspect it's actually a visual effect packet, but I haven't been able to find it. Oh well. I also made a couple small tweaks to Soul Linker, but nothing too major. The biggest changes were to Eska and Eswoo. The Es-line of skills for Soul Linker tends to be very overlooked in favour of their magical skills, and for good reason, these skills are all kinda mediocre and trolly. By far the worst culprit is Eska, which causes a target to instantly get 90 MDEF. Do you see a mage trying to kill stuff? You can just Eska his target to make him unable to do any damage. The non-troll use cases for this skill are pretty limited, so I totally reworked its effect to instead make a monster move faster but attack slower. There's still a tradeoff here but it's one that's likely to be more favourable most of the time. As for Eswoo, it still does mostly the same thing, but it now actually does change the target's size modifier. I just think this is a potentially interesting effect, particularly as many of the Soul Linker spells do different things based on the target's size. I also made some small changes to Kaina. It now no longer gives bonus SP (Soul Linker never needs it, their SP multiplier is super high), instead it makes some of your spells cost significantly more SP in exchange for slightly more power, which is usually probably worth it as this class has near infinite SP with high INT. Also, the prerequisites for some of these skills were moved around a bit, just so not every skill relies on Priest Spirit or Wizard Spirit. Finally, Soul Linker also gets one new skill in Kaulo. It's another Ka-skill (so you can only use it on yourself and family members without Soul Linker Spirit), and it's quite hard to get, having a lot of prerequisites and being a rebirth skill. It has an interesting effect of adding up to a flat 15% chance to active many positive effects, like Auto Guard and Auto Spell (including autospells granted by cards). It doesn't affect negative effects on enemies though, so no boosts to status infliction or other things like critical rate. This is a totally new effect so I'm not sure how powerful it is, but I think it gives a bit more value to the support-oriented Soul Linker build. That's about it for now, and possibly for a long time, but I hope this community will continue to grow and thrive. I've enjoyed seeing some of the cool things other people have come up with, and I hope my posts can inspire people to do more interesting things. -
So, for a variety of reasons that's a bit harder. In theory it would basically just be the reverse operation, where you would try to find a matching item by look id that ISN'T within the rejoin where the costume items are, but there's some extra challenges here. So the basic gist of it would be you'd need a method that basically does something like this: int itemdb_findmatchingnoncostume(struct item_data* data) { for (auto &tmp_item : item_db) { std::shared_ptr<item_data> item = tmp_item.second; if (item->look == data->look && item->nameid < 19432 && item->nameid > 20500 && item->nameid != data->nameid) { return (int)item->nameid; } } return -1; } Then just add a new option in the script that starts with a costume item and calls that method to find the item that gives you. The challenge though is that while there's generally only a single costume item having a given look id, this is not the case with regular items. This is essentially the reason my implementation specifically doesn't support it. For example, consider a simple Helm. Both item ids 2228 and 2229 are called Helm and have look id 40. There's of course also Costume Helm, which is id 19526. Why are there two Helms? The first is a 0-slot helm, and the second is a 1-slot helm. The problem is, either helm will convert into Costume Helm, and the information about what slots it had is completely lost, so we don't know which one to choose when going back. You could simply always choose the first one in the DB (the solution above works this way), I think this will generally prevent abuse. Realistically, people probably aren't going to socket enchant an item, then turn it into a costume, so maybe returning the first item is fine. But by that same token, most items you get back from the transition probably won't be highly valuable items, so it may be a lot of work for a feature not too many people will actually use.
-
The vast majority of the headgears in the game should already have costume equivalents in renewal's item-db, you can simply copy these into pre-re's item-db if your server is pre-re and they will work. Similarly, these ones should already be present in iteminfo.lua. It is only necessary to add them manually for the handful of headgears that aren't already there. If you're getting "unknown item", check that the id number in the lua matches the id number of the item in the item-db. For example, slotted jacket is id number 2304, so the entry in the lua file must be [2304]. If you're adding new items to the item-db, make sure the id numbers in both locations match up. For that script error you're getting, it's complaining that it doesn't recognize the "costume" function. I'm not familiar with that code (it's not from my implementation), but it would need to be declared in script.hpp and script.cpp so scripts can use it.
-
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
Oh, I don't necessarily think crit katar is OP in base, it's just that the specific changes I made benefitted it a lot. My server is also Pre-RE and I don't claim to know a ton about Guillotine Cross, I think Katar GC's tend to use Cross Ripper Slasher a lot? Of course, if that got nerfed / adjusted then maybe crit katar with the advanced poisons would be desirable. RO's balance is a delicate ecosystem where many things hold each other in check, so if you add a strong new option or reduce the power of existing ones it can have wide-ranging effects. I certainly don't get always get it right the first time, there's a ton of things I've had to go back and tweak because they were just too far out of line with everything else. On a related note, while crit katar got the nerf stick on my server, I did restore a bit of power to Soul Breaker Katar, by allowing Advanced Katar Mastery to influence the damage of the magical portion of Soul Breaker. When I played the game way back when, the elemental katars were very good for PVE with a Soul Breaker build, but at some point this was nerfed and they became vendor trash. Apparently it was due to a bug with Advanced Katar Mastery causing Katar to be inordinately good for Soul Breaker, and I have no idea if this is what it was (the description of Advanced Katar Mastery does kind of imply that it's a boost to all damage and not just physical, so perhaps at one time it was coded that way), but I think it's nice to kind of bring that playstyle back. I also think it's very fun to see what other people do with the game. I had an interesting discussion the other day with someone who has done something maybe even more bonkers than what I've done with the game (I won't go into detail because it's not really my story to share), but it reminded me of how much fun it was to come up with wacko ideas and implement them in this game. I hope other people will continue to have that experience. I take it that means it was changed on official? Gravity does make smart changes sometimes. A few of the skills I "buffed" on my pre-re server were just applying the official Renewal updates to them. Sometimes I would instead come up with my own buff only to find out that Gravity had also buffed it in a different way. I do think it's cool that Gravity continues to update the game, even if the direction they took it in isn't something that appeals to me that much anymore. -
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
Wow, I can't believe it's almost been 3 months, I was sure it was only a month and a half or something. For the last little while I've mainly been working on small tweaks (tiny changes to weapon attack values, monster exp yield, things like that), as well as fixing a few things that I broke previously re-adjusting some previous changes. A few mechanics have gradually become something of a problem based on various other adjustments in the game. SP Regen: SP Regen has been a problem on my server almost since the beginning. It just scales way too well with INT, so low INT characters basically never get SP, while high INT characters have basically infinite SP. I think it should be the case that if you use skills frequently, you should probably take a little INT, but characters with high INT shouldn't just have unlimited SP, this makes many game mechanics redundant, like making SP pots useless and making SP-related skills dump skills. I've tried tweaking it a few times, but it just shifts the problem in one direction or another, I knew it was going to take a full overhaul of the SP regen formula. The only way I was able to figure this out was to come up with a bunch of examples of characters with certain amounts of INT and max SP and figure out how much SP I thought they should regenerate, then work the formula around that. The new formula is: SP_Regen = SQRT(INT) + INT/10 + SQRT(MAX_SP / 50); The magic here is the square root parts of the function, which effectively causes severe diminishing returns in terms of SP regen. For the first bracket, you can get a pretty respectable 4 SP per tick for 16 INT, but it takes a whopping 64 to get 8 SP, so it decreases fast. Something pretty similar happens with the maximum amount of SP you have, where you need an absurd amount of SP for that bracket to give you much. Generally, this feels like it works, though I still had to tweak the SP costs for some skills (for example, Bolt spells now cost a little more) to get it to feel right for all classes. I imagine another pass will probably be needed on skill SP costs at some point because a lot of them are still kind of arbitrary. Incidentally, HP regen is untouched. I think because it operates on much higher numbers it has lesser problems. Crit Rate: Crit hasn't been changed significantly, but the big issue here is that there are many new weapons and cards that grant increased crit chance and / or crit damage, leading to critical builds being somewhat overly strong, especially for Assassins who can get near 100 crit rate with relatively minor investment. As such, I've made the somewhat drastic choice to cut the Katar crit bonus to 1.5x instead of 2x. To be honest, 2x was always probably too much, it makes crit inordinately good for Katar, which in turn cannibalizes Sonic Blow and Grimtooth. However, I have slightly boosted the amount of critical you get per point of Luk to compensate, which makes it slightly easier for other weapons to run crit builds. This is a fairly substantial nerf, but I think requiring 10 extra points of luk out of a build that's already very strong isn't a huge ask. Incidentally, I wonder what percentage of my changes have targeted the assassin class, it feels high. That's no problem, I've never intended to claim that I have a copyright over these ideas or something. Many of them are quite simple to implement so I encourage people to experiment if they think something here is interesting. Incidentally, I also have a version of that Blacksmith buff, it's mentioned on the first page as "Weapon Enchant". On my server it costs a Red Gemstone to use, which I think balances it out. Interestingly, I also recently added something like this, though my version is a thief skill that gives more crit chance against poisoned enemies. I guess great minds think alike. The issue here to my mind is that Envenom is kind of a dump skill that you never want to put too many points into. It wouldn't be hard to buff it, but a buffed Envenom basically just becomes bash, which makes Thief into Swordman, so I think it has to remain kind of bad as a direct damage skill to preserve the identity of the class. The problem is that Poison is also a bad status, so the fact that it can inflict Poison kind of doesn't matter either. Assassin does get some options to make Poison more dangerous on my server, though they also get other ways of inflicting it, and it doesn't do much good for Rogue. I think this is a decent low-cost option to get more value out of poison (for example, this is pretty good for a Crit Katar build that also has Enchant Poison) and gives a little more competition for Thief skill points, even if the Bleed skill is also pretty good. This is actually a really good starter project for learning how to mod the game, these were also some of the first things I fiddled around with. The sograt desert maps are actually still in the game as-is, the warps to them are just disabled, so if you figure out how to open up the warps file and make some small changes you can easily bring them back. Older Morroc is a bit harder, you can find the map file here on the forums, but you have to know how to edit the mapcache and GRF files to include it, but that's good practice for later. -
Can you elaborate a bit more on the error or what's not working?
-
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
The idea of critical spell damage doesn't really exist within classic Ragnarok. If you look at what criticals do, they have two main effects: - They ignore the target's physical defense - They always hit Magic already has both of those properties all the time. You could potentially make a magic critical ignore the target's magical defense, though there's already cards and equipment which have the effect of ignoring a portion of the target's magic defense. It also wouldn't be possible to implement the blue critical graphic shown there without modifying the client, since the damage types are specified in the client damage packet. Anyway, if you actually wanted to implement something like this, you'd mainly have to change the "is_attack_critical" method. There's a check to determine if a given attack can critical that looks at whether the attack is a normal attack or one of a small list of skills that can crit, you'd have to add a check to see if the skill is magical, and if it is, it looks at your magic critical rate. You'd also have to modify the defense calculation later to ignore magic defense on a critical. It could certainly be done, though I feel like it'd be a slightly weird mechanic. -
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
I think you're saying you want an item or card script that can trigger the Wizard's Magical Amplification ability? That's fairly straightforward. If you want a consumable item that gives you magical amplification, put this script on any usable item (the 10 is the level, it could be set to something else). { itemskill "HW_MAGICPOWER",10; } For a card or weapon that triggers it, you could do something like this. This gives a 10% chance to autocast level 10 magical amplication when using magic. The "100" is the chance, so if it was instead 500 you'd have a 50% chance to get it. { bonus5 bAutoSpell,"HW_MAGICPOWER",10,100,BF_MAGIC,0; } For more detail on how these types of scripts work, see the item_bonus.txt file in rathena's doc folder. -
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
Well, I'm not quite done yet. Whenever I'm away from Ragnarok for a while, I tend to come up with new ideas for skills, so I figured I'd do one last round of custom skills for classes that were a bit low in terms of total skill count. Pretty much every one of these skills required some kind of unique nuance to get it working, so it was a good test of all I've learned coding this game so far. Assassin: Assassin is one of the most changed classes on my server, as I feel it is a problematic class in a number of ways. It is simultaneously super strong and extremely basic to play, with among the fewest skills in the game and a large portion of its skill tree that no one ever uses. It also has the second-highest base HP of any class in the game for some reason, despite being extremely hard to hit. As such, I've endeavored to flesh out their skill tree to encourage build diversity while simultaneously scaling back their tankiness (they now have the lowest max health of any non-mage class). I think this has mostly worked, but it's had the side effect of making it a significantly harder class to play, and in particular it feels much harder to level at endgame because it's far less self-sufficient now. I wanted to restore a little bit of that feeling of being a one man army without turning them back into a one man army in guild war, so I came up with this. Soul Absorption is a fairly simple passive that restores some HP and SP when you kill things, significantly increasing the levelling efficiency of the class, though it's also now a prerequisite for Soul Breaker, which also scales back the strength of that build to some extent (it was somewhat outperforming the other Assassin builds, especially at low levels). If you think the idea behind this sounds very similar to the Wizard skill Soul Drain, you're not wrong, and mechanically it's implemented very similarly, though unlike Soul Drain it works with any type of attack, not just single target skills. This skill does also work in PVP, though I doubt it would be worth the skill points in guild war. It is fun to grimtooth down a bunch of enemies and get a full heal, though. Rogue: Besides build diversity, something else I want to encourage within the game is class diversity. In vanilla Ragnarok Online, there's quite a lot of classes to choose from to construct your party. Most of the classes can do just fine for DPS. For tanking, you'll usually use a Swordsman class or an Assassin, or maybe a Blacksmith. Then for healing, you bring a Priest. See the problem here? Pretty much no matter how you construct your party, the Priest is kind of essential. As such, one of the main things I've tried to address is to give various classes more options in terms of healing and support to make non-Priest parties more viable. For example, Summoner, Bard, and Alchemist all have better healing options, Monk is better for support, and Star Gladiator and Blacksmith are better at tanking. However, I wanted one more healing option available, but I didn't just want to give another class a standard heal spell. So I came up with a fairly unique healing option for everyone's favourite jack of all trades, the Rogue. Herbology is a unique skill in a bunch of different ways. For starters, it's a heal spell that has cast time and is interruptible, so it's not super great to spam during combat. It also requires an item to use, specifically a Hinalle Leaflet for Levels 1-5, and an Aloe Leaflet for Levels 6-10. The power of the heal actually resets at level 6, but the level 6+ version is an area heal that can heal multiple people close together, while the former version is single target. It also removes certain statuses at certain levels, level 3+ removes Bleeding, level 7+ removes Paralysis, and level 9+ removes Infection (which is a new status that Assassin has access to). Notably, these are all statuses that are hard to get rid of since many status heals don't affect them. It's intended to be used as a kind of backline heal spell, so it's part of the Bow Rogue skill tree, giving them a bit more support power to compliment their backline DPS, though you can certainly also use it as an out-of-combat heal for standard Rogue if you're willing to spend a few points for it. It's probably not a particularly class-defining skill but I feel like the idea behind it fits well with the class. From an implementation standpoint, this is actually kind of complicated due to the fact that it requires different items at different levels, which is not a concept that rathena supports natively (the only other skill that works this way is Potion Pitcher). Also, you might remember from before that the list of skills that target allies is defined client-side, so I had to cannibalize an existing skill for this. There was actually only one ally-targeting skill left in the game that wasn't already used, which was GC_Antidote, which was kind of a funny coincidence since this skill actually also heals Assassin's special poison status (infection is actually a modified version of SC_Toxin). Wizard: Of all the classes in the game, Wizard was probably one of the ones I touched the least. It was always a pretty good class, but with all the other classes getting new skills, it had kind of fallen behind in terms of the number of skills (I was actually a bit shocked by just how small its skill tree was). For some time now, I've sort of wanted to give Wizard some kind of utility spell, but I hadn't come up with any idea I really liked. However, the new Assassin ability gave me an idea. Soul Drain has always been kind of mediocre ability for Wizard, the class doesn't tend to have problems with SP and it doesn't use a ton of single-target spells either, and that ability just felt like it made way more sense for Assassin, so I completely reworked the ability into something totally different. Power Drain is now a regular spell with a totally new effect. It's basically Marionette Control but backwards, when you cast this on an enemy you steal some of their stats for a little while, with the level of the spell determining which stat is stolen. Like Marionette Control, there's both a status for the caster and the victim, and the caster's stats are increased by 1/10th of the victim's value for the chosen stat, while the victim's stats are decreased instead. Casting this on an enemy with high stats is very powerful, for example you could steal 12 Dex from an enemy who had 118 Dex, which is a ton, though the effect doesn't last especially long. I think it's still fun to play around with though. High Wizard also gets another attack spell in Explosion. This is just a reworked version of Warlock's Soul Expansion, where it's a slow-casting single target fire spell that hits really hard. Not too much to say about this, I just always felt that Wizard's fire spells seemed kind of weak. If you stone curse someone and then do magical amplification before this spell it does bonkers damage, so I guess this increases Wizard's dueling potential in PVP. That's not all for Wizard, though, they also get another new attacking spell in Static Field. This is kind of like a wind-element version of the Ninja's Blaze Shield spell, in that it creates a zone of damaging magic that can also inflict a status, in this case Paralyse. It doesn't hit as frequently, but it's still a decent way to slow down attackers. This skill is actually a reworked version of Shadow Chaser's Chaos Panic skill. It looks much more like an electric attack to me. Speaking of Shadow Chaser skills there's also this. This is actually what I always expected Shadow Chaser's Dimension Door would do, as similarly-named spells in other games usually have this effect, but instead what it does is it creates a zone on the floor that simply teleports you to a random location if you step on it, which is kind of a troll spell that you can't even use in GVG. Instead, my version of the spell creates an exit portal wherever you cast the spell, and an entrance portal wherever you were standing. This results in you warping to the new location immediately, but your allies can use it too. This is a fun way to take shortcuts or bypass traps in War of Emperium, though Dex does not reduce the spell's casting time and the portal doesn't stay open for very long, so it's not super abusable. Actually, Wizard also gets Teleport and Warp Portal as well, which are both prerequisites to get this spell, so even if this doesn't have a lot of use outside of WoE they still gain some extra utility. I think this is enough new tools to play with that Wizard doesn't feel neglected anymore. This was probably the hardest one to program. The entrance portal is actually Manhole, which didn't otherwise exist on my server, but obviously its functionality is totally changed. The exit portal is the actual Dimension Door spell, but it no longer does anything at all since the trip is one-way (save for the fact that it can be removed by spells like Ganbantein, which also eliminates the entry portal as they are linked to each other). Anyway, that's probably it for new stuff for a bit. The classes are looking pretty good now, there's probably mainly just going to be relatively small balance adjustments to skill power and enemy skill lists and such for the next little while. -
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
I'm glad that people enjoyed reading it. When I started, I figured that maybe I'd somehow find a way to allow rebirth for the classes that couldn't do it (always my pet peeve with the original game), I never figured it would turn into this. Still, my journey is probably nearing its end. I know I've said that before, but with any project there does come a time when you have to say "it's done!". At a certain point, there's simply not much you can add any more that meaningfully adds to the game. And I've pretty much run out of stuff I can feasibly add. There are no more maps I can harvest from Renewal. I've used almost every distinct weapon sprite in the game. There aren't really that many more skills that can be added without compromising the identity of the classes. For a few months, updates on the server have slowed as we've approached something resembling "stability". However, there remains one final frontier to tackle, and that's Guild War. I've always considered Guild War to kind of be the glue that holds Ragnarok Online together as a game. Ragnarok (at least PRE-RE) does not really have any story of defined goal. Sure, you can grind your way to max level, and my server does include significantly expanded end-game content in the form of the past, but ultimately the grind on its own can feel a little hollow at times. One of my beta testers who is new to the game asked me "sure, we can kill some of these bosses now, but what do we really need their items for other than to kill more bosses?". Of course, we all know the answer is "TO CRUSH OUR ENEMIES WITH AN IRON FIST!". Ragnarok Online is an incredibly complex game with a nearly infinite number of possible builds you can make, but the complex interplay of these builds can only shine when they're pitted against each other. The War of Emperium is an incredibly deep and interesting mode that takes all of the elements of the game and gives them their own unique and interesting way to shine. It is also an absolute nightmare to balance. I'm not actually talking about the actual gameplay balance of the mode itself. That is a concern too, of course, but it's something I've had in mind since the very beginning when designing and tweaking skills, so I don't think it should actually be too bad. No, what I'm talking about are the rewards from the mode that serve as the incentive to play it. On the official servers, the main incentive to play WOE is to get the God Items. The God Items are deliberately monstrously overpowered, which is (somewhat) balanced out by the fact that you need rare items from many different castles to assemble them. (As an aside, I see that in recent patches the god items have actually been nerfed, but to me Mejingjord will always give +40 STR). This is a problem for smaller servers, though, because you need a massive population to run War of Emperium with many castles at once. What a lot of small servers do is they only open one castle at a time. This works well, but it makes the god items impossible to get, which, to be honest, is probably a good thing because they're so gamebreaking, but it also kind of feels lame since most of the other rewards are fairly common things that you can get easily. No one is really that excited by slotted chainmail anymore. It was clear from the start that Guild War was going to need new, exclusive rewards. This was not easy, because I already added a ton of new items to the game. Clearly, the rewards from the guild war have to be good enough that you actually want them, but not so strong that gaining control of the guild castles quickly becomes an insurmountable advantage. This is a very delicate balance. Beyond this, there's the question of how to distribute the rewards. If we're adding new weapons, different classes equip different weapon types. We don't want to intentionally favour certain classes or builds by mainly adding good equipment for a single class. Each castle can spawn 2 distinct treasure boxes, which are unique to that castle. If only one castle is used, this gives us a total of 16 item slots to work with, which is not even enough for 1 of every weapon type in the game (and we want some lesser rewards like eluniums and OCAs as well). 1 castle isn't enough. My clue for how to handle this came from the classes in the game. The game has 10 base classes: Swordman, Acolyte, Mage, Archer, Thief, Merchant, Taekwon, Ninja, Gunslinger, and Summoner. We can pair these up two classes to a castle, which allows for roughly one box per class. This sounds pretty good! Under this scheme, 5 castles would be needed, which would presumably be available on a rotating schedule. We're getting somewhere, but there's just one more problem. There are four different guild war realms, Prontera, Geffen, Al De Baran, and Payon (for now, we're leaving War of Emperium 2 out of the equation). It seems to make sense to pick one castle from each. But what about the fifth castle? Well, clearly a sane person would just pick a second castle from one of the realms, but you should know by now that's not going to happen. No, of course the answer is that we're going to create a totally new fifth castle in its own realm. The cats have been disrespected for too long, so it's finally time for Malangdo to get its own guild castle. Well, maybe "totally new" is overselling it a bit. It's more like a "significantly altered version of a castle that already exists". Of the castles I didn't pick, the castle with by far the most interesting layout was payg_cas04, so this will become the basis for malg_cas01. To the map editor! There's a few things I like about this layout, but I think the most interesting thing about it has got to be this Emperium room. It's huge, there's two routes you can take, you can snipe across the gaps, and there are little barriers that protect you in certain areas. The coolest thing about it though are those double entry warps at the top! Spamming spells and traps on warp points is a super strong strategy in WoE, so having a second warp in to the emperium room is a huge deal. However, in payg_cas04, only one of the warps is actually used! This won't do, so the first thing we needed to do was to add a new route that could let you get to the second warp point. Looking at the layout of the castle, which I wasn't planning to change too drastically, there was really only one feasible place that could lead to a new warp, and that's this corridor here at the bottom of this map (the red square indicates where the warp would go). So this is where the new route would start. However, this is actually the first interior room in the castle, the warp on the far left leads to another interior room, so clearly this can't just skip you right to the emperium room. A totally new room is needed that leads to the emperium room. I decided to keep things fairly simple. The new room is a kind of back hallway that leads to a storage room, with a staircase leading down to the emperium room. Rather deliberately, this room kinda sucks for the attackers. It's super narrow, and it's very easy to trap the one-cell passage by that little barricade, or camp behind it. You can hide in the storage room to avoid someone walking through the hallway with Sight and try to slip past, but it's not hard to check the storage room since it has only one exit. However, having a second route that leads to the emperium room is already very powerful, as the defenders now need to cover both routes if they don't just want to try to hold the final room. I think there's an interesting strategy tradeoff if this route is clearly worse than the other route. Do you check it less often because clearly people won't take the bad route? Then that kind of makes it actually the good route, because you might encounter much less opposition that way. In any case, I think this layout is interesting. Of course, I couldn't just slap in a new room and call it a day, I also had to Malangdo up the place. It now has much more of a tropical theme. Interestingly, there are actually some GATing errors on this map (the GAT defines where you can and can't walk). There's a wall on the lower side of this map that you can simply walk through on the official servers, as well as a few misplaced snipe tiles. I fixed them. Still, it kind of made me feel good in a way to know that the original map creators are human too. I also retextured the entire map and replaced all of the objects with Malangdo-themed ones, which no one will probably ever notice because you really don't have time to sit and enjoy the scenery in the middle of guild war. Putting all that food on those plates is a huge pain! Oh well. I feel like if you can't tell that I made something, it means I probably did a good job of it. The gold standard is for it to look like something that could have been in the game originally. I also continue to be impressed by the ingenuity of the original level designers. Did you know that those apples on the table beside the bananas are actually christmas tree ornaments from Lutie? You'd never guess. So we have our new map, all that remains is to rig it up to work in the game. Surprisingly, Rathena provides space in agit_controller for you to insert your own custom guild castles. Has anyone other than me ever used this? Adding the new castle is surprisingly easy, you just have to remember to put it into castle_db. And here we are! Shh, no one give away my awesome hiding spot. Oh, and of course, Malangdo also needs its own Guild Dungeon! Luckily, we happen to have an unused cat-themed dungeon left over in lasagna dungeon! It's like I planned it all along! This place also plays the unused track 175. Now let's all enjoy Cat on Bullet. Only one question remains. How the heck do we actually get here? Well, the first couple screenshots may have given a clue. See, it's an intentional balancing mechanic that the guild realms aren't just inside the town. The necessity to walk back to the entrance to the guild castle increases the length of time it takes the attackers to respawn, compared to the defenders who can simply warp into the castle. So we need a spot that takes a little bit of time to walk to. How about the otherwise pointless boat in the middle of Malangdo? (I don't apologize for this dialogue). And there we have it, 5 castles (or four castles and one cattsle). All that remains is the rewards. Here's a taste of a few of them (there's actually 30 new equipment items in total) Which one do you think is the most gamebreaking? (Incidentally, "Finale" mentioned in the Dancer weapon is Amp. Someone complained that calling it Amp made no sense, which is true). Actually, a key element of this is that most of the gear is significantly restricted in terms of which classes can use it, so even if an item like the Light Manteau maybe outclasses the Heavenly Wings (Dex +1, 3 Def), the fact that only a few classes can use it prevents it from making the other item useless. In any case, they're not really out of line with a lot of the gear that's already in the game (and I don't think they're nearly as bad as a lot of the nonsense that was added in renewal), but they are probably things you would actually want, which of course is the point. Anyway, that wraps it up for this time. it might be a long time before another update, if there even is one, but I hope everyone has enjoyed reading this thread. -
A possible fix for the position bug when attacking (Netcode)
Tero replied to Tero's topic in Source Releases
Oh, it's possible the change from range -1 to range might have been something else I tweaked at some point, because it looks like the version you have is the same as mine. In any case, you'd just have this. // Remember the skill request from the client while walking to the next cell if(src->type == BL_PC && !battle_check_range(src, target, range)) { if (ud->walktimer == INVALID_TIMER) { unit_walktoxy(src, target->x, target->y, 8); } ud->stepaction = true; ud->target_to = target_id; ud->stepskill_id = skill_id; ud->stepskill_lv = skill_lv; return 0; // Attacking will be handled by unit_walktoxy_timer in this case } For the second block, you can actually leave that one. That is for ground-targetted skills, which cannot experience this issue. The third block looks like this. // Remember the attack request from the client while walking to the next cell if(src->type == BL_PC && !battle_check_range(src, target, range)) { if (ud->walktimer == INVALID_TIMER) { unit_walktoxy(src, target->x, target->y, 8); } ud->stepaction = true; ud->target_to = ud->target; ud->stepskill_id = 0; ud->stepskill_lv = 0; return 0; // Attacking will be handled by unit_walktoxy_timer in this case } -
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
Well, after a while of no major changes, I'm back at it again. Sage's Dragonology has always felt like one of the most lame skills in the game to me. It's a mastery skill that only works against Dragons, which is even worse than most mastery skills. Sure, if you max it, you get 3 INT, which is ok, but it still feels really lame, it's basically just "dump 5 skill points for 3 int". It seems to me, that if you were going to spend all that time studying dragons, rather than just becoming marginally stronger against them, wouldn't you want to become a dragon instead? Now this is more like it! Dragon Form is essentially Mini Berserk for Professors, albeit with a number of different nuances. For starters, you can only use Dragon Form when over the four elemental field spells, Volcano, Deluge, Violent Gale, and Gaia Power. (Astute readers might note that Gaia Power doesn't exist in the base game, but it's an Earth-version of the other field spells). Which Dragon you turn into depends on which field you're standing on when you activate it. Here's the Wind dragon after casting it on top of Violent Gale. Becoming a Dragon gives you a boost to Attack Power, Maximum HP, and Movement Speed, albeit to a way lesser extent than Berserk (only 150% HP at max level compared to Berserk's 300%). It also sets your attacking and defending element to be the same as the Dragon. This not only means that you'll instantly get the buff from the elemental field spell you're standing on, but it's also one of the only sources of Level 2 elemental armor for players, so if you become Water Dragon, you're instantly immune to Storm Gust. Take that spamming Wizards in WOE! Of course, a dragon with level 2 water armor would not enjoy Jupitel Thunder very much, so there are drawbacks. Also, don't think you're going to get sneaky and change your weapon or armor element after becoming a Dragon because you can't, like with Berserk your ability to change your equipment is locked and it also blocks all spells that change your weapon or armor element. In Dragon Form, you also have Large Size and are Dragon Race, which is interesting. This means that Hydra and Thara Frog cards instantly become useless against you, which is pretty great, though it does mean that the various Anti-Dragon equipment becomes a problem. Probably still worth it though. It also takes a lot of skill points to get Dragon Form, as Dragonology now has 10 levels and it must be maxed, and you need at least one elemental field spell too. As a Dragon, you can still cast spells. You gain access to the new Dragon Breath skill, which can only be used as a Dragon, and does strong physical damage and knockback, but your regular spells work just fine too. There's nothing stopping you from casting spells that don't match your element, either. This is probably kind of a silly change, but I think it's fun. Who doesn't want to run around as a Dragon? It also finally gives battle Professor the survivability and damage it needs to be competitive with the traditional caster Professor, and gives more value to the elemental weapon / field side of the skill tree, which is often overlooked. Under the hood, the transformation into the monster is actually very simple, it just uses the built-in SC_MONSTER_TRANSFORM. It's not difficult to check to see if you're over one of the elemental fields, as it can simply check to see if you have any of the elemental statuses like SC_VOLCANO, which are granted while standing in those fields. The biggest pain was getting it to properly apply the field bonus after you become a dragon and your armor changes, as the original implementation does not allow this (if you do not have the right armor type when entering the field, it does not check to see if you acquire it later), this took a bit of re-implementing. -
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
No problem, that's an easy one to fix, though I'll also explain what's happening. In rathena, a block_list, or bl, represents an entity in the world, like a player, a pet, or an enemy. Since this type of variable can represent many different types of entities, the information available about them is very general. You can determine what map they are on and what their position is, but you can't, say, check their equipment because many types of entities don't have equipment. As such, something that is frequently done is to check the type of entity, then perform something called a "cast" to convert it to a more specific variable type so we can get more information out of it. When you see session_data, or sd, that specifically represents a player, so it's a specific type of bl. The code "if (sd)" basically checks to see if the entity in question is a player, which is relevant to this logic because we only want players to get the new pathfinding logic. However, to run this statement we first have to declare sd. In the version of rathena I have, this was declared at the top of the method, but they moved it further down in the method in the newest version, and it's now below the if statement where we were looking for it, which causes that error. This is no problem though, we can easily move it back to the top without impacting anything. First, find and cut this line from later in unit_walktoxy: TBL_PC *sd = BL_CAST(BL_PC, bl); Then paste it under this line: unit_data* ud = unit_bl2ud(bl); It should now work, but we might also want to make one more tiny change just for consistency with their code. Where we have this: if (sd && !(flag & 1)) { Let's instead make it this: if (sd != nullptr && !(flag & 1)) { I'm fairly certain this makes no difference, it's probably just a stylistic choice, but we might as well keep the codebase clean. -
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
Having now mostly finished with custom content for the time being, I decided to take a look at some player complaints that I previously ignored saved for later. Among players who are new to Ragnarok, by far the most common complaints involve the game's netcode and pathfinding. I've played Ragnarok for so long that I've learned to just automatically adjust for it. For example, I know I don't need to tell anyone from here this, but when moving around in RO you generally want to keep the mouse cursor about this far from your character and hold the mouse button down. This works pretty well, as long as you keep the mouse cursor about that close you shouldn't have any issues with your character not going where you want them to. I imagine this is probably kind of a holdover from the very early days where you couldn't zoom the screen out much at all. An RO vet would know you definitely wouldn't ever try to do something like this to move: But it's hard for people who are used to more modern games to get used to this, no matter how many times I pointed out that it was all their own fault. So I decided to see if I could do something with the pathfinding algorithm to make it work a bit better. For starters, it turns out there's actually something incredibly easy you can do to improve pathfinding a lot! All you have to do is disable this line in core.hpp: #define OFFICIAL_WALKPATH And instantly pathfinding is way better! It turns out that rathena's pathfinding algorithm is way better than the one that the official game uses, but they include a reproduction of the original for the sake of accuracy to the originals. Just disable this line and suddenly you can walk about twice as far. The example above works now! However, there are still some situations where it doesn't work, generally when walking a long distance in a straight line, oddly enough. I think this is because the way the pathfinding algorithm works is it tries to explore all possible options to get to a destination, so if there are too many choices (like in a very open area) it kinda gets stuck. You can see this in action in a more compact area like clock tower where the pathfinding is actually really good now. However, we can improve it further. The code that handles pathfinding is in unit.cpp, in unit_walktoxy. We can see that it has two algorithms that it uses, an easy one that attempts straight line movement, and a hard one that is more complex. However, it turns out there are some situations where the easy path finds the answer and the hard one doesn't. As such, what we really want is to try both, but currently it never does this. We want to replace this code: if (!path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS)) // Count walk path cells return 0; With this: if (sd && !(flag & 1)) { // check easy path, but don't give up if it fails if (path_search(&wpd, bl->m, bl->x, bl->y, x, y, 1, CELL_CHKNOPASS)) { ud->state.walk_easy = 1; } else { if (path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag & 1, CELL_CHKNOPASS)) { ud->state.walk_easy = flag & 1; } else return 0; } } else { if (path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag & 1, CELL_CHKNOPASS)) { ud->state.walk_easy = flag & 1; } else return 0; } The idea here is that if the flag is not set to try the easy path, it will do it anyway, but if it fails, it will try the hard path. If the flag is set to try the easy path, it only tries the easy path, as before. Also, it only applies this logic to players and not enemies. You can remove the sd in the first if statement to apply it to enemies as well, but this actually makes the game a little harder as the AI is now better at chasing the player. In any case, pathfinding is now drastically better, you can click at least twice as far away and automatically path around many obstacles. Try it out for yourself, it's very noticeable. Next on the list of complaints was that sometimes when you click on an enemy, you don't attack. This is one that I've encountered a fair bit myself. I'm pretty used to automatically clicking near the enemy to move closer to account for it, but it is pretty annoying and sometimes it can get you killed. It turns out this happens at extremely precise ranges where you're too far to attack but too close to move closer automatically, and then attack. It took me ages to isolate the exact problem, but I finally got it, and the details can be found in this thread: After running a boatload of tests against this I determined it to be fixed, but when partying with a Dancer we were encountering the problem again! How frustrating! But it turns out, this was actually not the same problem at all, but rather a limitation in the client. See, if you read a couple posts above this one, I mentioned that I added a skill to the game that allows Bards and Dancers to enthrall monsters and use them as minions for a little while. The Alchemist also has something similar to this with Bio Cannibalize. In both cases these create mobs that are friendly towards the player because they have their master_id set to the player's id. The server knows that these monsters are not valid targets for the player because the routine battle_check_target checks the master_id, but the client doesn't know this, and so it lets you attempt to target them like any other monster. Note the sword icon on the captivated monster and targeting caret: This is not so much of a problem when out of combat, but when fighting enemies, the minion can kind of get in the way and "absorb" your clicks in a way that another type of minion like a pet or homunculus can't (because they aren't considered targetable by the client). Strictly speaking, this is an unfixable problem because there's no way to tell the client that you shouldn't be able to target that monster, there simply isn't any field that does this within the monster packet. So I opted for a more creative solution. Instead of preventing you from clicking on the monster, the game will simply try to guess what you meant to click on instead, and change your target to that. The way it does this is that if you try to use an enemy-targetting skill or normal attack on a minion (which isn't allowed), it will instead assume that you mean to target whatever the minion is targetting, so it sets your target_id to the minion's target_id. I doubt anyone else would actually need this code (it doesn't really matter for bio cannibalize, it's mostly just for the custom skill on my server, but it's accomplished by this code snippet here in unit_skilluse_id2, which goes right before the comment at the end. if (inf == 1 && battle_check_target(src, target, BCT_ENEMY) <= 0) { if (target->type == BL_MOB && ((TBL_MOB*)target)->master_id && ((TBL_MOB*)target)->target_id && battle_check_target(src, map_id2bl(((TBL_MOB*)target)->target_id), BCT_ENEMY)) { target = map_id2bl(((TBL_MOB*)target)->target_id); target_id = target->id; } } // Fail if the targetted skill is near NPC [Cydh] For some reason that's not totally clear to me, this also requires making this change slightly later when it sets the stepskill: ud->target_to = target->id; It was originally set to target_id instead. If this change is not made it sometimes wrongly sets the target_to to 0. Yet one more complaint was that when you reset your skills, it resets everything, and not just the skills for your current job. I agree that this is annoying, but I looked at it a long time ago and decided it was too hard to fix. See, you would think this would be straightforward, but actually the way the skill trees for the classes are specified, each class knows all the skills it can potentially learn, including those from its previous classes, and there's no real distinction for which skills are new and which ones aren't. So to figure out what skills you can only learn in your current job we have to check the previous jobs and this requires a ton of bitflags and such. Once again, I made a separate thread that has this version of the NPC, if you want this functionality on your server: Finally, I took one more pass on the achievements. I had previously overhauled the achievement system to actually work, but the treasure chest achievements were still a bit lacking. In particular, there were none in many of the newer dungeons (not just the ones I added myself, but many of the official dungeons too), and of course the past area had no treasures at all. So I revamped the treasures, including consolidating some of the categories so I could add a new one for the past areas. This is a lot of work for a feature no one really cares about! Actually, I do kind of think these treasures are useful for discovery - the achievements let you know that certain dungeons exist, so you can keep exploring if you haven't found them all. And then on top of that I also fixed many other maps in the past that had the same map culling issue I previously mentioned for pro_fild01. Geez, that was hard work, I need a vacation. What do you mean I already had my vacation and I spent it all working on Ragnarok? -
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
My server started out simply by implementing content into PRE-RE that already existed in the game, but was exclusive to Renewal, and then when I ran out of Renewal content I started harvesting content from the Korean version, and then the alpha, but we've reached the point where there simply isn't any more content that is usable for what I want to do. Actually, we probably reached that point a few months ago. Unfortunately, I still have new ideas. While the "present" on my server is pretty well filled with stuff, there are still a few places in the past that feel a bit sparse. As such, I had an idea for a castle in the middle of the desert that would feature the "abyss arthur" boss, which is one of the only MVPs that isn't in my server already. I knew there was an unused desert castle map at moc_vilg00 that I don't use because I don't think the past version of Morroc particularly needs to have a castle (and Morroc's Fortress is south of it), so it was just sitting around unused in the GRF. There are also a couple maps representing the inside of the castle, which also might be usable. The outside map is actually kinda usable! It'll only be enterable from one side (the bottom) and I'd like to move the castle up towards the top of the map so there's more space, but this is a good start! The inside maps, though, are just a mess. Renewal actually has a few maps like this (ie, Octopus Cave, Misty Forest Labyrinth), but they simply don't play well (neither of these maps are on my server). Having a map that's made up exclusively of extremely small rooms with teleporters every few feet gives you no space to fight, and it's very common to teleport into a room full of enemies and get ganked immediately. These maps are also designed solely as indoor maps and thus only have walls on the northeast side, as the indoor camera doesn't allow you to rotate the map any other way. These are not usable. So if I wanted to make this dungeon, I'd have to create the indoor maps from scratch, which is far more complex than anything I'd ever done with the map editor before. However, at least I have the old maps as a general guide for the aesthetics of the map, as I do like the general feeling of these maps, they're just not suitable for gameplay. The first step was to alter the outdoor map to move the castle. This was comparatively fairly straightforward. There's no kind of "multi select and drag" feature here (at least, not in this old version of Browedit), so I had to move the terrain and objects manually, but having the old version as a guide this was not overly hard. I did have to learn a fair bit about how walls worked for this (as the moat around the castle has a ton of walls, which was useful practice for later. Here's my version of the outdoor map. It's a little more open, befitting its status as a combat map, but it's still pretty similar overall. Now came the hard part, creating the indoor maps. For each one, I started out with the floorplan, just laying out the rooms and hallways using texture tiles, then building walls around them, and finally filling them with objects. Here's my version of the upper floor of the castle. This has a sort of generally similar feel to the original, and in particular I liked the idea of the water room, which I kept and expanded for my version. It feels appropriately decadent for a desert castle. And here's the bottom floor. This part of the castle has more of a pyramid feel. I like the idea that perhaps the castle was built on top of an ancient tomb or some such. It's also divided into two halves that are linked by a portal, making it feel a bit more like it's in three pieces. The boss always spawns in the big room in the upper right. I learned a ton about the way Ragnarok maps are constructed while working on this. For example, let's take a look at this guest bedroom on the lower right of the upper floor. You might think that those paintings on the walls are objects, for example, but they are actually simply wall textures, and ditto for the windows. The wall graphics contain a ton of different variants for different wall textures, all shoved into the same texture file, and the walls are made out of one section of that larger texture. Similarly, those carpets are floor textures, but do you think they store the entire carpet? Oh no. Only the corner is actually part of the texture, which you then have to rotate and overlay upon itself to create the full thing. These sorts of little efficiencies are everywhere. Many of the objects you see in the maps are actually made up of multiple objects. For example, let's appreciate this little shelf in Payon: You might think this is a single object, but no, this is dozens of objects meticulously aligned together. Each one of those little sets of 2 doors is an object. So the bottom layer is made up of 3 objects, and so is the second, the third layer is 4 objects, The top 4 rows are made up of 10 objects each! It probably took an hour to create this shelf, and this house has two of them on opposite walls. For as many crazy things as I've done with Ragnarok, I can't even come close to what the original creators did. It's amazing how much they were able to do with such a simple engine. It's probably part of why the game feels as compelling as it does, and how it's still interesting to tinker with even 20 years later. With the maps finally done and added to the game, it was time to fill them with enemies. Having gone to all that work, simply adding effects to clone monsters using monster_size_effect_sak_new.lub didn't feel like enough, so I used my newfound knowledge of how to recolour sprites to create some entirely new palette swaps. I quite like the new blue bird. I also went back and created new sprites for a few enemies who just had effects before, like this harder version of Isis from Past Pyramid. Dang, I kind of want a Green Isis pet now. Adding new sprites to existing monsters is quite easy, you just have to change their sprite file in jobname.lub and add the new act and spr files to the monsters folder in your GRF file. I also went back and improved the dungeon I made out of 1@jorchs some time back. It now has significantly more objects. I had wanted to put lab objects in here before, but slabw doesn't load in my browedit for some reason. However, 1@lab and biolab both load, so I was able to steal some of their objects. This map is much creepier now. Anyway, that's enough map editing for now, and hopefully for quite some time, as I think the past finally has enough dungeons now. It definitely gave me a deeper appreciation for the map design in this game, and makes me even more impressed with Toy Factory, which I've always considered to be the best-looking map in the game. Look at how many different texture pieces are used in this tiny section of the map. The attention to detail is crazy. Seriously, open this map up in the editor, it's worth seeing how this was put together. It just goes to show that there'll never be another Ragnarok. The amount of love and care that went into this game isn't something you see every day. -
A possible fix for the position bug when attacking (Netcode)
Tero replied to Tero's topic in Source Releases
So it turns out there's actually another version of this glitch where sometimes your character will fail to attack because they're at an extremely precise range where they are out of range to attack, but too close to move closer and then attack. This seemingly requires some degree of client desync and is rare, but it annoyed me enough that I spent many hours tracking down the exact problem. Find this in unit.cpp: if(src->type == BL_PC && ud->walktimer != INVALID_TIMER && (!battle_check_range(src, target, range-1) || ignore_range)) { (it occurs twice in the file) In both instances, replace it with this: if(src->type == BL_PC && (!battle_check_range(src, target, range) || ignore_range)) { if (ud->walktimer == INVALID_TIMER) { unit_walktoxy(src, target->x, target->y, 8); } Do not touch anything below this code, leave everything about the stepskills untouched. If your rathena is old, the ignore range part is not present so you are instead looking for this: if(src->type == BL_PC && ud->walktimer != INVALID_TIMER && !battle_check_range(src, target, range)) { Which you replace with this: if(src->type == BL_PC && !battle_check_range(src, target, range)) { if (ud->walktimer == INVALID_TIMER) { unit_walktoxy(src, target->x, target->y, 8); } The problem is that if the user is too close for the client to execute a move to attack instruction, but not close enough to attack, the walktimer will not be initialized, but the range check will fail. It should execute a stepskill in this situation, but it does not because it requires a valid walktimer to execute a stepskill. This handles this boundary case by forcing the user to approach the target, as the client would do automatically under all other circumstances. This is maybe not the most graceful solution (maybe they should just move one tile closer to the target?) but it works and the problem can no longer occur. -
This has been a request that I think everyone has made at one point or another, but I initially looked at it and said "too complicated". Well, today I decided to finally code the thing. Basically, this is an adjustment to the Reset NPC that gives you the option to only reset your current class, leaving your previous classes untouched. This requires code changes to support it, and you'll have to recompile your server afterwards. A quick caveat, though this includes code to support third and fourth classes (for Renewal), that code is untested. It's similar to the second class logic so it should work, but if you have some kind of weird issue it's probably there. In pc.cpp, find the pc_resetskill method Find this line: int i, skill_point=0; Replace it with this: int i, j, k, l, baseClass, secondTransClass, thirdClass, currentClass, skid, skill_point = 0; bool previousClassSkill, isSecondClass = false, isThirdClass = false, isFourthClass = false; Find this line: if( flag&4 && (sd->class_&MAPID_UPPERMASK) != MAPID_BARDDANCER ) return 0; Insert this below it (don't replace the code above). If your server has fourth classes, uncomment that line. baseClass = pc_mapid2jobid(sd->class_ & MAPID_BASEMASK, sd->status.sex); secondTransClass = pc_mapid2jobid(sd->class_ & MAPID_UPPERMASK | JOBL_UPPER, sd->status.sex); thirdClass = pc_mapid2jobid(sd->class_ | JOBL_THIRD, sd->status.sex); currentClass = pc_mapid2jobid(sd->class_, sd->status.sex); if ((sd->class_ & MAPID_BASEMASK) != sd->class_ && (sd->class_ & MAPID_BASEMASK | JOBL_UPPER) != sd->class_ && (sd->class_ & MAPID_BASEMASK | JOBL_BABY) != sd->class_) isSecondClass = true; if ((sd->class_ | JOBL_THIRD) == sd->class_ && (sd->class_ & MAPID_BASEMASK) != sd->class_ && (sd->class_ & MAPID_UPPERMASK) != sd->class_) isThirdClass = true; //if ((sd->class_ | JOBL_FOURTH) == sd->class_ && (sd->class_ & MAPID_BASEMASK) != sd->class_ && (sd->class_ & MAPID_UPPERMASK) != sd->class_ && (sd->class_ | JOBL_THIRD) != sd->class_) isFourthClass = true; currentClass = pc_class2idx(currentClass); baseClass = pc_class2idx(baseClass); secondTransClass = pc_class2idx(secondTransClass); thirdClass = pc_class2idx(thirdClass); Find this line if (lv == 0 || skill_id == 0) continue; What you need to add next depends on your version of eathena. If you are on latest, which has the new skill tree, add this below that line: if (flag & 16) { previousClassSkill = false; if (baseClass != currentClass) { std::shared_ptr<s_skill_tree> firstTree = skill_tree_db.find(baseclass); if (tree != nullptr && !tree->skills.empty()) { for (const auto &it : tree->skills) { skid = skill_get_index(it.first); if (skid == skill_id) previousClassSkill = true; } } } if (isThirdClass) { std::shared_ptr<s_skill_tree> secondTree = skill_tree_db.find(secondTransClass); if (tree != nullptr && !tree->skills.empty()) { for (const auto &it : tree->skills) { skid = skill_get_index(it.first); if (skid == skill_id) previousClassSkill = true; } } } if (isFourthClass) { std::shared_ptr<s_skill_tree> thirdTree = skill_tree_db.find(thirdClass); if (tree != nullptr && !tree->skills.empty()) { for (const auto &it : tree->skills) { skid = skill_get_index(it.first); if (skid == skill_id) previousClassSkill = true; } } } } If you are on an older version, which has the old form of skill_tree, add this below that line instead: if (flag & 16) { previousClassSkill = false; if (baseClass != currentClass) { for (j = 0; j < MAX_SKILL_TREE && (skid = skill_tree[baseClass][j].skill_id) > 0; j++) { if (skid == skill_id) previousClassSkill = true; } } if (isThirdClass) { for (k = 0; k < MAX_SKILL_TREE && (skid = skill_tree[secondTransClass][k].skill_id) > 0; k++) { if (skid == skill_id) previousClassSkill = true; } } if (previousClassSkill) continue; } We're pretty much done with pc_resetskill, but if you want, you can add this to the comment at the top of the method, as the final line: * if flag&16, Only reset skills that the current class can learn Almost done with code changes, now we just need to add the script function. The remainder of the changes are in script.cpp: First, find the definitions of the script functions by searching for this: struct script_function buildin_func[] And add the following line somewhere, ideally below the one for resetskill BUILDIN_DEF(resetskillcurrentonly, "?"), Now add this method somewhere, ideally below resetskill but it can in theory go anywhere. /** * Reset player's skill, leaving previous classes untouched * resetskillcurrentonly({<char_id>}); **/ BUILDIN_FUNC(resetskillcurrentonly) { TBL_PC* sd; if (!script_charid2sd(2, sd)) return SCRIPT_CMD_FAILURE; pc_resetskill(sd, 17); return SCRIPT_CMD_SUCCESS; } With this done, you can recompile the client and everything should be set. Now all you need is the new version of the resetnpc script below and you'll have the new functionality. Man, this was a lot harder than it should have been. Rathena should really just add this option by default. resetnpc.txt
-
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
Well, break time's over, I'm back to it with more crazy new mechanics. I know what you're thinking: "I love the Bard / Dancer class, but I'm a total loser with no friends so the party support aspect of the class isn't useful to me!". Well, there's an easy solution to that problem, we'll just have to make some friends! Not through tedious social interaction, but with a new skill! Introducing Captivate, a new skill for Bard / Dancer. Just find a friendly-looking mob and cast the skill on them to make them your new friend! (This spell does have a lengthy cast time so if you're planning to cast this on a hostile mob or a monster that can cast-detect you might want to find a source of uninterruptable cast) After captivating your target, they'll follow you around and attack things that attack you or that you attack, kind of like a pet. If you'd prefer to take a more active approach, you can also direct them using the Conductor skill: Go my minion! You can even support your new friend with your song and dance abilities to enhance their fighting abilities or heal. Of course, nothing lasts forever. After the skill's duration expires you'll be all alone again. But there's plenty of mobs in the dungeon! Now to have my new friends do my dirty work in PVP. The way this works under the hood is that when you use the spell on a monster, they are despawned and recreated as a minion using "mob_once_spawn_sub", similar to AM_CANNIBALIZE. Most of the heavy lifting is already done by the follower AI, though some tweaks to "battle_check_target" were needed to allow mobs and players to attack them. At any rate, I think this is a fun ability. It's not actually super powerful (of course, you can't use it on bosses or monsters that are higher level than you, and it has a cooldown so if you're going through minions fast you'll have to wait), but it's unique and I think it fits with the character. Speaking of minions, Blacksmith also now has the ability to summon these. Nothing crazy here, this was already a Mechanic ability that has few changes. For Blacksmith, you need the forging abilities to learn this skill, which gives forgers a little more offensive presense. Also, I fixed the Magic ones. In the base game, they're all Yellow, regardless of element, so I recoloured them to match their element. Here are the fire and earth ones. It turns out this is actually super easy. Using Act Editor, you can use the "Quick Palette Edit" to instantly swap out the colours across the entire Act file. It only took a couple minutes to create the palette swaps. I encourage anyone else who wants them recoloured to learn how to do this, because you could easily use this to recolor other sprites too. Makes you wonder why Gravity didn't bother. -
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
Apparently my forum account is now 1 year old, which means it's also been a year since I started working on my server. I actually haven't made a ton of big changes since the last post, mostly small tweaks like bug fixes and the occasional new item or enemy. Still, I wanted to put up some sort of update, so I decided to make a video showing some gameplay of the past area. I've thought about doing a video before but I've held off on it because Gravity is apparently pretty aggressive with takedowns, so it's unlisted (and all of my videos are unmonetized anyway). I still may not leave it up forever, so enjoy a brief look at past gameplay (make sure to set the video to 1080p in case it doesn't do that automatically). -
Thanks for finding that and testing out the potential solution. I've added the fix to the first post.
-
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
Another small update, but no less time-consuming. I got my hands on the GRF file with the information from the beta, and I was able to harvest the last removed map, etc_cave01. This map did not initially load properly as its textures are looking at some nonexistent location, but hex editing the GND file easily allowed these to be replaced. It seems to use the same textures as Dungeon001, so I've added it to the game as another floor to that dungeon. There's a few new enemies here, like Papare and that Black Bat enemy. I found a new item I wanted the black bat to drop, the Black Devil Mask. It's a neat-looking mask that covers one eye. However, there's a big problem with it! If you turn in certain directions, the eye that it covers changes! This looks super stupid and I wasn't willing to put it in the game like that. So, because I'm way too picky about stuff like this, I decided to see if I could fix the sprite myself. There's a pretty good tool that can be used to do this called Act Editor which I used a little bit before for editing enemy sprites. A naive person (ie, me before I did this) would probably think that because the character can be displayed from 8 directions, this will only require 2 new sprites (only 2 directions are messed up). Oh no. The game manually specifies the position of the headgear for every possible animation frame the character can have. I'm sure there's probably some automatic way to update this but I didn't find it, I just did them all manually by calculating how much the sprite moved each frame. There are also different sprites for male and female characters since they have different animations. This took a while. Since I was already spending my whole evening on this, I decided to see if I could fix the Kitty Band as well, which has a strange issue where the inside of the ear always faces outward regardless of which direction you face, causing people on my server to joke about it being the worst headgear in the game. This was comparatively much easier because I didn't have to reposition anything, I just had to add some new sprites and then swap out the sprite index in the animations. Interestingly, the male act file for the Kitty band already specifies a back sprite, it's just identical to the front sprite, but the female act file does not. Did two different people work on these? At any rate, here's what they look like once they're fixed. Should you want these sprite edits for your own server, I've attached a GRF file that contains the updates. You'll probably just want to merge this into one of your grf files, since it's very small. headgearfix.grf -
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
A very small post, but I wanted to share something in case anyone else ever runs across it. As I've mentioned previously, my server contains the maps from the alpha, albeit with new monsters and warp points and such. However, there's a strange problem on one of the alpha maps. On pro_fild01, there's this bizarre culling issue where parts of the map will sometimes disappear while you're walking through it (look at the top part) It flickers on and off while you walk through the map and is generally very annoying. But what's going on? No other map in the game does this. I decided to try to investigate it in the map editor. Everything looks normal enough. There's nothing in the map to indicate any "culling zones" or anything strange like that. I even tried replacing the rsw with one from another map of the same size and the problem persists. The one thing I noticed is that if you look at the map boundary, the map is actually sunk below it (notice how the yellow walls are above the map rather than below), which is a bit weird. Actually, most of this map is sunk pretty far into the ground, with many parts having Y values in the 30s and 40s. I decided to try moving the entirety of the map up by 50 units, to see if the height of the map was the problem. Note that the map now sits above the yellow wall. This is not too hard using the "global height edit" function, which also thankfully adjusts the GAT tiles. However, it was also necessary to manually adjust the height of each object, which was moderately time consuming but not difficult using the object list. And surprisingly, it works! The weird culling effect is eliminated and the map displays normally now. So it seems like the game has issues if map geometry goes too far below the ground, though this isn't an issue on any other official maps that I've seen. I wonder if this bug existed in the alpha? My guess is that the client worked slightly differently back then so this issue didn't occur, but who knows. -
Thanks for keeping RO alive + Tero's wacky modding adventures
Tero replied to Tero's topic in rAthena General
It's not the greatest implementation ever but I can show you the gist of it. In the struct mob.hpp, there is a new field in the struct mob_db: unsigned int pity; In mob.cpp, this value is initialized to 0 in mob_parse_dbrow, near the bottom (its exact position doesn't really matter) entry.pity = 0; Also in mob.cpp, in the method mob_dead under "player specific drop rate adjustments", we add bonus drop rate based on the pity value, if the item is a card. This is the part that is kind lackluster. // Increase the drop rate based on pity if it's a card if (it->type == IT_CARD) drop_rate = drop_rate * (50 + md->db->pity) / 50; The way this formula works is that the value "50" here is the number of kills required to double the drop rate of the card. On my server, cards drop at a rate of 1/200, so this feels kinda reasonable, but if you rate was, say, 1/1000, this would be way too high and you'd probably want to set this value to like 200 instead (make sure both numbers are set to the same value). For an optimal implementation this value should probably derive from the server's card drop rate in some way but I kinda hastily coded this one in. Also in Mob_dead, we need to make a slight change later on to increase or reset the pity based on if the card drops or not. // attempt to drop the item if (rnd() % 10000 >= drop_rate) { if (it->type == IT_CARD) { md->db->pity++; } continue; } // Reset the pity if the card drops if (it->type == IT_CARD) { md->db->pity = 0; } And that's really all there is to it, recompile the code and you have the pity system. Note that, as I mentioned when I first brought it up, the pity is shared among all players, and it also gets reset every time you reset the server. But for midrate servers, it does help make hunting for cards feel more tolerable. I haven't had to kill 1000 Santa Porings with no card drop since I implemented it.