Jump to content

curiosity

Members
  • Posts

    133
  • Joined

  • Last visited

  • Days Won

    23

Everything posted by curiosity

  1. How did you add the files? Did you remember to add a file with the standing animation to the 3dmob_bone folder? Taking the test files you provided in testing_animation_indexes.rar, here's an example of a configuration which is currently working for me. (All animations are showing with none of the edits I've posted except for the one in my previous post). If it doesn't work for you I'll honestly be very puzzled... Rename kguardian90_7.gr2 to dmob90_50.gr2, put in 3dmob folder Rename 7_move.gr2, 7_dead.gr2, 7_damage.gr2 and 7_attack.gr2 to 50_move.gr2, 50_dead.gr2, 50_damage.gr2 and 50_attack.gr2, respectively and put in 3dmob_bone folder Make another copy of kguardian90_7.gr2, this time to the 3dmob_bone folder and rename it 50_stand.gr2 Add [jobtbl.JT_DMONSTER] = "dmob90_50.gr2" to jobname.lua Add ["JT_DMONSTER"] = 2600 to npcidentity.lua Add monster ID 2600 to rAthena database I have verified that it really reads the standing animation from 50_stand.gr2 by also trying to use for instance the dead animation instead, and the client showed the spider repeatedly dying when standing still. I use the main GR2 file for 50_stand.gr2 here because I don't have the stand animation as a separate file. The cleanest approach is to export the standing animation as a separate file, but all in all it doesn't really matter if you don't care about the kilobytes of duplicate data. As for your other question: With the help of some scripts you could probably do it to some extent. For instance if the door had the "door opening" animation for its dying animation you could make a script kill the door NPC when it's supposed to open. After a while it would disappear though, like all monsters do after a few seconds. You could then spawn a new door with the "door open" as its stand animation in the exact same place and the player wouldn't notice they're actually two different monsters/doors. So all in all it would be cumbersome and to my knowledge you don't really have any more control over which animation to display than for ACT based game actors.
  2. Are you the same AppleGirl who founded eAthena? What happened to the Alpha and Beta emu projects? I used to follow the development, but suddenly the forum was gone
  3. Yes, I still think reading the stand animation externally is the best solution. If you are interested I attempted to explain where the client gets nType from on the previous page. I don't think there is any other table we need to concern ourselves with. Here a hex edit which makes it load the stand animation from %nType%_stand.gr2 from the 3dmob_bone folder instead of from the model. Nothing needs to be changed for the Gravity mobs. 2012-04-10a (verified to work) Find: 83 FE 09 0F 87 8A 00 00 00 83 FF 04 0F 87 81 00 00 00 Replace: 83 FF 04 0F 87 8A 00 00 00 83 FE 09 77 30 90 90 90 90 2011-03-15a (untested) Find: 83 FE 09 0F 87 84 00 00 00 83 FF 04 77 7F Replace: 83 FF 04 0F 87 84 00 00 00 83 FE 09 77 2C So to add a new mob with this, the stand animation needs to be exported as well and put in the 3dmob_bone folder. (For instance for "mymonster_100.gr2" you'd need to add "100_stand.gr2" as well as the other regular bone animation files.) After that it can just be added as a normal monster with any job ID you want. How this works: instead of returning NULL when invalid nType is found, it jumps to load from 3dmob_bone instead. It also moves the comparison on nAnimIdx so it's done first making sure it won't crash on animations which aren't available to GR2 monsters.
  4. I decided to try my luck with assembly and it seems to be working. With my amazing assembly skills I managed to come up with something like this: L_START: cmp esi, 10 jna L_ELSE mov edx, esi add edx, 9C4 jmp L_END L_ELSE: mov edx, job[esi*4] L_END: jmp L_REF ; back to function I tested by adding the test monster with nType = 20 and job ID 2520 and everything seems to be working perfectly without having to hex the new ID into the client. Gravity mobs work as normal. So with this it should be possible add any amount of monsters with no hex editing by putting some nType > 10 in the file name, then adding the monster with job ID = 2500 + nType in npcidentity.lua.
  5. The nType is the index used in the names of the bone animation files. I think it just gets it from the file name of the GR2 model, at least it very much seems that way. For instance if you add "spider90_10.gr2" to the LUA files, it means that the model is rotated 90 degrees and uses nType/animation index 10. It also means that it will try to get the bone animation files "10_move.gr2", "10_attack.gr2" and so on from the 3dmob_bone folder when displaying the model. The problem is just that standing animation, which it needs the job ID to get the job name for. So it first gets the nType from the job name/GR2 file name, then it "forgets" the job name and just has the nType when it needs to get the animations in this function. nType 0-9 are used by Gravity's models, so we know when nType is 10 or above it will be a custom monster. So if we could just make it do something like if(nType < 10) jobId = job[nType]; else jobId = 2500 + nType; ...instead of just the table look-up we could for instance just add a monster as "name_20.gr2" in the job name entry and ID 2520 in the LUA files. The nType = 20 would get passed to this function, which would instead of the table look-up just add the constant 2500 and end up with the right job ID. Or if you use nType 100 in the GR2 file names you would add it as mob ID 2600 in the LUA files. For Gravity mobs it would continue to use the table, since they are nType < 10. Well, that's at least one solution... @Diconfrost: Ha ha, thanks.
  6. The look-up is in the function which already has been posted in this thread (C3dGrannyBoneRes::GetAnimation). I think there's something a little wrong with the code Ai4Rei posted (looks like inner if and else blocks are switched), but if you look at his code the table look-up happens at the line sprintf(g_Unknown1, "model\\3dmob\\%s", g_session.GetJobName(g_Unknown2[nType])); g_Unknown2 is the table mapping from nType to job ID, and it's referenced exclusively by this function. Just to recap a bit: In order to load the requested animation it needs the file name of the GR2 file where the animation is stored. At the point where the mapping table is used it knows that the requested action is the standing animation. It needs the file name from the job name table since the default/standing animation is stored in that GR2 file with the model data. GetJobName requires the job ID, so it needs a way to get the job ID associated with the nType/bone animation index. For that purpose it uses the little table to look-up the job ID by nType. The above line of code in assembly: mov edx, job[esi*4] ; fetch job ID using nType from the table mov this, offset g_session push edx call GetJobName; push eax ; job name entry push offset aModel3dmobS ; "model\\3dmob\\%s" push (offset fileName) ; Dest call _sprintf add esp, 0Ch jmp short loc_43585F So in order to avoid the table something needs to be done with that first instruction there. At this point I know what could be done, but not how to do it because I don't have any experience with this kind of stuff. Maybe you know how to insert a new function and make it call that instead of the table look-up so we can do our own mapping from nType to job ID?
  7. Lemongrass has it right. This approach requires some handiwork, which is why it'll hopefully just be a temporary solution. Something like mapping a range of IDs could probably work OK. For instance, for nType > 9 set monster ID to some constant + nType instead of doing the table look-up. Hopefully someone more skilled than me can help out, because I'm falling a little short here. I'll PM you a little tutorial for your client, Olrox!
  8. LOL thanks! I searched so hard for it yesterday. Then I'll experiment a bit and see if I can get something working! Double posting for a little update. I managed to get almost everything working with custom monster ID. I used 2012-04-10aRagexeRE.exe and did the following: Added the test GR2 files to 3dmob, bone animations to 3dmob_bone and renamed with ID 10 Added a new monster entry in the LUA files (monster ID 2500) Patched max. 3D mob animation ID to 10 Moved the "GR2 animation ID to monster ID" table to a new offset in the executable where there's more room Added the monster ID (2500) as the 10th entry in the table So it's a hacky approach, but if anyone really want custom GR2 monsters it's a temporary solution for now. There seems to be a lot of space available in the client I used, so it should be possible to add many monsters. The downside is that you need to edit new entries into the client. Everything except for damage animation is working, but I'm wondering if it even works for any of Gravity's monsters anyway? 2012-04-10aRagexeRE.exe.patched2.zip
  9. I was hoping if it was done that way it would continue to work normally for all the Gravity GR2 files, but for customs (ID > 9) it would look for the standing animation in the 3dmob_bone folder. I could be wrong though. I guess the alternative would be to add the custom entries to the ID mapping table? 0 508h 1288 JT_EMPELIUM Empelium90_0.gr2 1 2D2h 722 JT_GUILD_FLAG Guildflag90_1.gr2 2 52Ch 1324 JT_TREASURE_BOX1 TREASUREBOX_2.gr2 3 3E8h 1000 JT_MON_BEGIN 4 3E8h 1000 JT_MON_BEGIN 5 3E8h 1000 JT_MON_BEGIN 6 3E8h 1000 JT_MON_BEGIN 7 506h 1286 JT_KNIGHT_GUARDIAN Kguardian90_7.gr2 8 505h 1285 JT_ARCHER_GUARDIAN Aguardian90_8.gr2 9 507h 1287 JT_SOLDIER_GUARDIAN Sguardian90_9.gr2 You can add custom 4 entries for the unused values, but if you want more I guess you'd have to relocate it. For some reason the guild flag model is initialized with ID 5 (which used to belong to Zombie Dragon) in the WinMain function. I really don't get what that's about. On an unrelated note I finally found out the PDB everyone seem to have comes from the HighPriest_081105 client, but it's no longer available for download anywhere... If anyone would be willing to upload HighPriest.exe and HighPriest.pdb I'd really appreciate it!
  10. Maybe the easiest solution would be to export the standing animation to the 3dmob_bone folder for custom monsters and just try to add in a "nType < 9" check which would prevent look-up in the table all together. if( nAniIdx && nType < 9 ) { sprintf(g_Unknown1, "model\\3dmob\\%s", g_session.GetJobName(g_Unknown2[nType])); } else { ... It that works there would be no need to do anything special when adding 3D mobs. By the way, where do you guys keep getting the debug symbols from?
  11. The entries are just the 5 strings for the names of the skeletal animation files. 0 = "stand", 1 = "move", 2 = "attack", 3 = "dead", 4 = "damage" The a_type in the function I posted comes from the value of m_nLastActAnimation/m_stateId from GreenBox's code. The first of the functions he posted calls C3dGrannyModelRes::ActAnimation, which in turn calls the function I posted. So the possible values a_type can contain are something like 0, 1, 2, 3, 4, 5, 11, 12, though what 5, 11 and 12 were supposed to be I don't know (as you can see my the code I posted it will ignore these). Anyway, I think all the switching in the code GreenBox posted is just used to map from "ACT actions" to "GR2 actions". Afterwards it just asks the Granny resource instance to change to another action. If it doesn't have the animation for the action loaded it will call the function I posted to load it.
  12. Hmm, that's not bad at all. I didn't really expect it to work so easy. Kinda strange that the default animation doesn't work, though. I wonder why Gravity decided to split up the animations into separate files in the first place... Maybe you can try to duplicate one of the guardian mobs by adding it as a custom monster to see if it's a problem with the RSM exporter? Otherwise some more client edits might be necessary, yeah. I'm not sure if the code I posted is responsible for only adding more animations to an existing loaded model, or if it's also responsible for loading the main models. If it's animation only we could perhaps just export the standing/default animation in the 3dmob_bone folder as well. For higher GR2 vertex count you can try to replace this: Find: 3D 10 27 00 00 (offset 0x3AE69) Replace: 3D 20 4E 00 00 That would increase the limit from 10,000 to 20,000. Keep in mind the check might be there for a reason. Testing a bit probably won't hurt though. Not sure about RSM vertex count. Do you know the limit? I can try to look into it later.
  13. Got it! Open the EXE in a hex editor (XVI32 is my favorite), find the hex sequence: 83 FE 09 0F 87 84 (offset 0x39749) 0x09 is the limit it compares against, so you just need to set it to a higher value, for instance 0x64 (100 in decimal). It's only one byte that's changed so I figured it'd be just as fast for you to do it yourself. If you can't figure it out I'll patch and upload for you. Edit: Also found out the client has a hard limit of 10,000 vertices per GR2 model. Might be good to know? I think we could set a higher value for that as well though.
  14. Okay, let's try that then. One thing though, I haven't really played Ragnarok in years, so I don't have an updated client. If you could give me a link to an exe you want to use I can try to patch that.
  15. Nice work Olrox, it's starting to look good. I know little of reverse-engineering, but here's a function I found which seems to be responsible for constructing the resource names for the Granny models, along with some guesses of what the variables are. int __thiscall getGrannyModel(void *this, int a_id, int a_type) { void *v3; // ebx@1 char *v4; // ebp@1 int v5; // eax@5 v3 = this; v4 = (char *)this + 4 * (a_type + 4 * (5 * a_id + 40)); if ( *(_DWORD *)v4 ) return *(_DWORD *)v4; modelResPath = 0; if ( (unsigned int)a_id <= 9 ) { if ( (unsigned int)a_type <= 4 ) { if ( a_type ) { sprintf(&modelResPath, "model\\3dmob_bone\\%d_%s.gr2", a_id, animTypeStringTable[a_type]); } else { v5 = sub_6E6000(dword_7CAA8C[a_id]); sprintf(&modelResPath, "model\\3dmob\\%s", v5); } if ( modelResPath && (unsigned __int8)fileExists(&modelResPath) ) { if ( a_id != 1 ) readGrannyModelFromDisk(v3, &modelResPath, a_id, a_type); return *(_DWORD *)v4; } } } return 0; } So from the looks of it the max animation index is hard-coded to 9, which would probably be the reason why nothing happens when you try to go higher. Perhaps it'd be possible to just change it to a higher number and it'd work. I could try to patch a client for you. Though from what you posted I think there may be many more hard-coded values somewhere else... I don't think it'd be as easy to add more animations per monster though, because the client probably wouldn't know when to use them.
  16. What for? I'm pretty certain the server has nothing to do with the distinction between 2D and 3D actors. The map server just gives notifications on movement, direction, attacks and so on. It's up to the client to pick the correct animation. I imagine there are some standard indices for the animations (perhaps even named?) which the client picks from in GR2 files as well. In ACT files there are usually five actions present; 0 => stand, 1 => walk, 2 => attack, 3 => hurt, 4 => die. Or did I misunderstand you completely?
  17. ricky92, do you have the GR2 all worked out? Would you mind posting a format specification?
  18. Thanks for all the kind compliments. I'll make sure to keep the topic updated on new development
  19. If you're not already tired of unfinished Ragnarok client projects - read on! This is a little project of mine I've been working on for a while now. It's basically the same as KeyWorld's RoBrowser project. I thought his client looked kinda cool and got tired of waiting for it, so I decided to make my own, but it's tough work! Mostly it's a learning project for my own sake with no real roadmap. This is, this is more of a share and tell than an announcement. The code-base so far is 100% JavaScript, using WebGL for graphics, WebSocket for server connection (using a WebSocket-TCP tunnel on the server side), HTML audio API for sounds and BGM and so on. Currently only running in WebKit-based browsers I think, I'll get around to other browsers later. The long term goal is to make a client implementing the features available back in the good old days of Ragnarok, around episode 6 or so. (Meaning this is not intended to be a replacement for the official client!) It a lot of work, but I'm getting closer to my first milestone; being able to log in and walk around. Some things are still left though. I need to fix my camera, implement actors, integrate my map viewer into the client and so on. Luckily I'll soon be done with all the 3D rendering related work, which is a huge relief because I have no idea what I'm doing. Now for the screenshots... Char select (as far as I've currently implemented the actual client): Morocc the old-fashioned way. Once I get the shadowing on models up and running it'll look even prettier! Lighthalzen in all it's glory. FPS is pretty good by the way. Even large detailed maps such as this go at a solid 60FPS, even when viewing the whole map at once with models animations and all that. I make sure to merge all the static geometry and build texture atlas for the models. This slows the map loading down by 5-10 seconds and uses lots of RAM (though only for a short while), so I'm considering trying to put this on the server side somehow. Unfortunately my GPU drivers are broken and crash a lot when using larger textures, so I only use atlas textures of size 2048x1024 for now, resulting in around 10 textures or so for all the models. By using atlas texture size 4096x4096 (which should work fine for most people) you only need a single texture for the whole map, speeding things up quite a bit. For fun I also tried to get my map rendering code running on my trusty iPad 1st gen. Can't say I expected much of it though. Which was why it was pleasant to see that it actually performed much better than expected, giving a great frame rate while rendering some GNDs. However it only has a grand total of 256 megabytes of RAM, of which only about 100MB is available to the browser. Another 100MB and I could probably safely load a map, but half of Alberta was the best I could do for now: Along with some grass. Don't mind the textures here, I accidentally replaced a lot of them with textures from the Alpha client so some maps look weird. Anyway, while my old iPad is a no-go I'm hoping to get this running on some of the newer mobile hardware available eventually. I don't think Android has any working support for WebGL yet, but it'll probably come soon. That's all for now. It's been an interesting journey so far through all the insanity Gravity has pulled over the years. To be continued...
  20. Wow, thanks, those are great. Are the vertex colors are always only applied to the top surface? At least I get the same results for those maps while only setting the vertex colors for those. Also do you just use black if one of the adjacent tiles doesn't have a top surface? I though I had it all wrong because some maps like pay_dun00 look like someone smeared shit all over them, but I checked with the official client and it turns out it's the same there.
  21. I'm trying to get this right in my own renderer, but it looks weird at the moment. If it's not too much of a bother, could you please share a picture of prt_maze01 or gl_church with only the vertex colors enabled? Also, one little detail: what did you mean by posterization levels 17.0 - 1.0? Just 16 levels, or something else? I tried to match the lightmap of your earlier screenshot of pay_dun01 and (I think) I got a similar result by doing pcolor = floor(255 * floor(15 * color / 255) / 15) with all steps being float operations (JavaScript, he he). This gives 16 levels (0-15), but the upper level contains only one intensity value. So I guess this was wrong? Could I just do rounding instead instead of flooring and get the correct values? Or should I use 16 instead and floor everything?
  22. Yeah, sure. I meant this one. Taking another look at it now it seems a change to C++ was made recently, though.
  23. There are a great many people active in the relevant communities with the necessary skill-set to do this. Those who are truly interested in this have already started their own projects and work at their own pace, which the above list of projects illustrate quite well. The only ones actually complaining about this situation are the self-entitled leeches who have grand ideas for modifications which they wouldn't even be able to implement if they had the complete source code a client. There's no reward in this save for personal satisfaction, which is why I'll give you this tip: Don't pick a language of your choice along with some specific technologies you like and wait for someone to join you. Not going to happen! If C# is your main point of interest there's even a recent client project done in just that language listed just a few topics below.
  24. Oh, okay. Quick question: Do you use bounding boxes to setup the RSM matrix?
  25. Norwegian here. I suspect those are actually supposed to be stylized lions, and the muzzle of the sculpture from the first post is just worn down. As in the pictures Wolfeh posted, you can see patterned carvings of a mane on the the neck. Keep in mind these people had never seen a lion in their life and probably just had a rough verbal description of a carnivorous quadrupedal beast. Point in case, this. Even familiar animals were often stylized in odd ways, see for instance this depiction of the Fenris wolf on a metal cross. Except for a few key elements I've noticed little actual influence from Norse culture in the game. I believe more of the inspiration came from early role-playing games based on the Dungeon and Dragons franchise, which in turn is heavily inspired by Tolkien's work. There's a few things though. Satan Morocc seems to be the same character as Surt from the comic, which is based on the jotun Surtr; a lord of the Muspell realm and also one of the creatures which will ultimately destroy the realms of gods and men alike.
×
×
  • Create New...