Jump to content

[Done!] Animated 3D Monsters in RO


DoSS

Recommended Posts


  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  22
  • Reputation:   44
  • Joined:  08/07/12
  • Last Seen:  

Well, as you have seen, the converter should work with multiple meshes in a single model. Granny viewer, in fact, does work with those and shows all of the meshes correctly. It might be due to some naming convention in the ragnarok models, but I'd need to further investigate this: could you please attach an original RO model with multiple meshes along with the multimesh model you were trying to convert?

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  87
  • Topics Per Day:  0.02
  • Content Count:  1335
  • Reputation:   932
  • Joined:  10/26/11
  • Last Seen:  

Original RO Model---> https://dl.dropbox.c...uardian90_8.gr2

Our Model for testing ---> https://dl.dropbox.com/u/52175822/house1.GR2

You are right, the converstion shows the multimesh on there, but for a reason in game, well you see the result. Perhaps this is something more in our side, since it has to do with the game. However your help is greatily appreciated in case you will take a look to the original model.

=====

To everyone:

We are ready to update our project (In case someone wonders, since Doss is not good at english I have to do it with his account =P). Changes are listed below:

  • Changelog of our current progress so far
  • Our current state. -For now, we are looking for people skilled with hooking packets in the client (we are aiming to contact Yommy again, since we are able to use custom granny now) so as a core developer (we are aiming to contact Greenbox for his help, since he shows interest before) who is able to dig into animation indexes in the server side emulator . Everyone is welcome.
  • A video example To show you how to rip Ragnarok 2 -Gate of New World- gr2 mobs as 1 example, into Ragnarok 1. This includes how to handle the 3DS Max granny 2.6.1.X importer. So you can do your own testings. This is to improve the community participation, I'm sure most of people is willing to do his own testings now.
  • Contact of Ricky92, and his donation link. I know he doesn't asks for this but this is more because myself wants it.

Thanks for reading.

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  22
  • Reputation:   44
  • Joined:  08/07/12
  • Last Seen:  

Okay, the problem seems to be in the GR2 file itself, and not in the converter. As you can see, the original RO GR2 file holds several meshes, but just one model, while the other holds the same number of meshes and models. This means the game will read only the first model of the GR2 file, which, in this case, is just composed of the first mesh. I'm not quite sure how to solve this, but it's something that has to be fixed at export time (when you export using 3DS Max).

EDIT: Found a solution, and I already told Olrox on Skype about it. Just group the meshes when exporting and they will be considered a single model by the granny exporter.

Edited by ricky92
  • Upvote 4
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  87
  • Topics Per Day:  0.02
  • Content Count:  1335
  • Reputation:   932
  • Joined:  10/26/11
  • Last Seen:  

You are awesome.

Exactly that was the solution. Thanks a lot.

Now in game, the same gr2 testing house shows all the multiple meshes.

screenCUTE-RO001.jpg

All good. Now we are wondering about how to make the gr2 registrate a lower default position present from the red mark to the green mark *LINK* but don't worry about this, since I believe this goes with max and its granny dll importer.

@Ricky92

Is there some work to do with the granny animation indexes? we have been trying with the importer, but we are not sure if this feature is allready present, since we have encountered with some problems at testing it

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  22
  • Reputation:   44
  • Joined:  08/07/12
  • Last Seen:  

You need to move the pivot for the whole group, setting its Z position to 0,0 should be enough. As for the animation indices, I really don't think there's something RO-specific for the animations to be done, I suppose you just have to understand how the filenames work and sort the files according to that logic.

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  26
  • Topics Per Day:  0.01
  • Content Count:  331
  • Reputation:   63
  • Joined:  11/29/11
  • Last Seen:  

Can someone explain how to extract vdk file, I have RO2, but files are in vdk. please send me a direct link to extract vdk files.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  87
  • Topics Per Day:  0.02
  • Content Count:  1335
  • Reputation:   932
  • Joined:  10/26/11
  • Last Seen:  

RO2 LOS is not possible yet. Or at least some months ago that we tried with DoSS Only RO2 GOW for now, for which we are using "uModelGUI".

@Ricky92

Thanks for the info about the position, I will tell him to try. Now about animation I guess we will have to try harder then, and leave some info of our tests.

Which I'm aiming to do this week.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  87
  • Topics Per Day:  0.02
  • Content Count:  1335
  • Reputation:   932
  • Joined:  10/26/11
  • Last Seen:  

Hello everyone.

Today I took my time to do my own tests with the amazing tool that Ricky did to us. And well I tried harder with importing a custom GR2 Animation in Ragnarok Online. Comparing the default gr2 mobs I just thought that [D]oSS and me were doing bad since we were importing the models with all the bones attached. And, it is only necessary to import the skin of them.

The following video is my first test I did, using the Granny Converter made by Ricky92, and using the Granny Importer for 3DS Max 7 *All tools are attached in the first post of this thread*. The original GR2 Monsters are from Ragnarok 2 Gate of The World!

[media=]

[/media]

Typo error: It is "Granny Converter". Sorry about that.

I believe Ricky92 will add a new version of the converter soon. However I can tell that the Alpha version of it, works pretty well.

Some notes

  • We are still doing tests with the Default Rotation of the Customs GR2.
  • We are kinda early to add a tutorial of importing your own GR2, since we are doing our own tests. However if you are familiar with 3DS Max 7 and Granny 3D, you might find these tips useful:
    • When importing with the 3DS Max Granny Plugin, import with the Bink Textures at "0" in all options
    • If you are importing Multi Mesh Models, you have to Group all the meshes and import them. Otherwise the Game Client will only show the first mesh of your Granny Model.
    • For testing animation, you have to import ONLY the default skin of your model in 3DS Max 7 using the Granny Importer. DON'T IMPORT the bones of your animation, or you will have errors in Game.
    • Seems that resizing the models increase the animation speed. Or, it is happening for a reason in the game client. We are still wondering why.

If you want to test....

I will attach the files used in the video so you can have fun with them. Just copy the files in "data/model/3dmob/" in your data, and, for now only name the files as "kguardian90_7". and test by using "@disguise 149". Please keep in mind that additional animation indexes are not supported YET, since those are stored in "data/model/3dmob_bone/" and they are reserved in the client ... So, if you attack or die, in disguise mode your game client will crash.

Also, keep in mind that these gr2 are for testing and the test I did was on a skymap. Since the default position of the gr2 mobs are kinda not ready (and I have no time to test today), I just tested in a map with a view clear area as the one in the video.

Our State:

I think we have enough with default animation, and I believe we are ready to move on with custom animation indexes (that means, walk, die, hit, etc) just as how the default WoE guardians are. (Yes, what I mean, is that a custom gr2 mob, can store multiple animations in the same model).

In this state we trully need help, of people skilled with client packets and source, since our knowledge is more practical we are limited to do our tests more in a Graphical purpose. We will move on to try this multiple animation, but again, we currently need this kind of help.

Thank you.

3d_Mob_default_animation_test.rar

  • Upvote 3
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  7
  • Topics Per Day:  0.00
  • Content Count:  133
  • Reputation:   189
  • Joined:  05/20/12
  • Last Seen:  

In this state we trully need help, of people skilled with client packets and source, since our knowledge is more practical we are limited to do our tests more in a Graphical purpose. We will move on to try this multiple animation, but again, we currently need this kind of help.

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?

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  87
  • Topics Per Day:  0.02
  • Content Count:  1335
  • Reputation:   932
  • Joined:  10/26/11
  • Last Seen:  

Because someone bringed some source code to our thread and I just can't take it out of my mind:

Seems like the animation indexes(?) are static and uses the following IDs:

void __thiscall C3dGrannyGameActor::SetAction(C3dGrannyGameActor *this, int action, int speed, int type)
{
C3dGrannyGameActor *v4; // esi@1
struct granny_control **v5; // edi@10
signed int v6; // ebx@10
int v7; // eax@12
v4 = this;
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 0;
switch ( action )
{
case 48:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 4;
break;
case 80:
case 88:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 2;
break;
case 64:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 3;
break;
case 0:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 0;
break;
case 8:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 1;
break;
case 24:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 5;
break;
case 32:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 11;
break;
case 40:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 12;
break;
default:
break;
}
this->m_nLastActAnimation = this->baseclass_0.baseclass_0.baseclass_0.m_stateId;
v5 = this->m_Control;
v6 = 20;
do
{
C3dGrannyModelRes::DeActAnimation(v4->m_GrannyActorRes, *v5);
*v5 = 0;
++v5;
--v6;
}
while ( v6 );
v7 = v4->m_nLastActAnimation;
LODWORD(v4->m_GameClock) = 0;
if ( type == 1 )
v4->m_Control[v4->m_nLastActAnimation] = C3dGrannyModelRes::ActAnimation(
v4->m_GrannyActorRes,
v7,
v4->m_Instance,
v4->m_Control[v7],
1);
else
v4->m_Control[v4->m_nLastActAnimation] = C3dGrannyModelRes::ActAnimation(
v4->m_GrannyActorRes,
v7,
v4->m_Instance,
v4->m_Control[v7],
0);
}

void __thiscall CGrannyPc::SetAction(CGrannyPc *this, int action, int speed, int type)
{
if ( this->m_GrannyActorRes )
{
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 0;
switch ( action )
{
case 48:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 4;
CGrannyPc::SetGrannyAction(this, type);
break;
case 80:
case 88:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 2;
CGrannyPc::SetGrannyAction(this, type);
break;
case 64:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 3;
CGrannyPc::SetGrannyAction(this, type);
break;
case 0:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 0;
CGrannyPc::SetGrannyAction(this, type);
break;
case 8:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 1;
CGrannyPc::SetGrannyAction(this, type);
break;
case 24:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 5;
CGrannyPc::SetGrannyAction(this, type);
break;
case 32:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 11;
CGrannyPc::SetGrannyAction(this, type);
break;
case 40:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 12;
CGrannyPc::SetGrannyAction(this, type);
break;
case 16:
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 6;
goto LABEL_12;
default:
LABEL_12:
CGrannyPc::SetGrannyAction(this, type);
break;
}
}
}

I'll try to discover what are each ActionID, maybe they are indexed like ACTs files are.

I prefer not to make conclusions of something I have not tested yet. Remember, this is our first time in our life to use a custom gr2 besides of the ones that Ragnarok has.

The gr2 animations inside /data/3dmob_bone are kinda not standard too, and I doubt they can be threated as how Act files are. "Action GR2" animations, have specifically sets of bones and dimentional enviroment sizes specifically for the original GR2 mobs they have been designed for.

In case we try to use one of those, for our mobs, that will not work. I can say it even without testing.

However I think you are right. We need to do our test before. And We will continue then on our own side, checking whats going on. Perhaps it is simple since I looked at:

jobname.lua:

[jobtbl.JT_ARCHER_GUARDIAN] = "Aguardian90_8.gr2",

Where specifically in data/model/3dmob_bone the files are listed as:

8_attack
8_damage
8_dead
8_move

Taking this example I can say this name of:

"Aguardian90_8.gr2"

  • 90 : Means Rotation of the GR2 Mob
  • _8: Id of the animation GR2 indexes. In this case, it matches.

Perhaps it is even that simple like the client will read the new entries by just adding the new entries in the luas for ex. I add a new id like 10, and then animations as 10_attack, 10_damage, etc.. (???) seems too much good to me to be real honestly, and then by adding the new gr2 animation files in the /data/3dmob_bone.

Or perhaps not.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  87
  • Topics Per Day:  0.02
  • Content Count:  1335
  • Reputation:   932
  • Joined:  10/26/11
  • Last Seen:  

Did some time today to test custom animations, for "walk, dye, hit, attack and stand". A video which explains our limitations too.

[media=]

[/media]

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?

Now that I have tested, now I can reply back this:

As I was expecting, it is not as simple as adding custom sprites. Adding the custom gr2 mobs in the corresponding luas, and using exactly the same gr2 files used in the guardian (which they work as all of you can see in the video) for a custom mob id. The result is a static model. With no animation, however the gr2 model appears.

Important:

  • Adding a cusom GR2 entry in the luas, and using the same spider GR2 used in the guardian id, which appears I'm using in the video, makes the -Z- value of the model decreases a lot, that means it looses height. Seems that the client or something we don't know adds an instruction that has to do with alltitude with the GR2 model. (again, we are not expert with customs in the client, which was the reason, saying it once again, that we were looking for help before)

  • The amount of gr2 animation files in 3d monsters in ragnarok as emperium or guardians, varies. The maximum set is 4 which corresponds to Guardians, but this is not a limitation in the gr2 file (which can handle any amount). We are looking onwards if in case we can add our own gr2 entries , that means to increase this amount of 4 indexes at max. Something I believe it has to do with client and instructions of the emulator.

  • Regarding further development that goes with interaction as we refered at the first post, and Greenbox stated as that needs to hook the client and source instructions, we are gonna leave that for the community development of people who are interested into this, as also join this project The first phase of being possible to add custom gr2 animation, and all that goes with graphic from our side it is ready to begin this kind of tests.

I have to say it once again then. [D]oss and me, we are not used to deal with client, and source. We are only used to deal with 3D and by our side after being possible to begin testing with the amazing tool that Ricky92 did for us, we have moved onwards our progress so far to understand how the animations are handled by RO and make possible to port our own to it

Whatever it has to do with making the client reads sucessfully a custom GR2 job view id (which is not working for a reason we obviously don't know, again, static model not animation) is beyond of our knowledge.

For now I will leave the custom GR2 mob attached. Totally in dispossal and ready to any kind of tests that this generous member who is willing to help us might do.

testing_animation_indexes.rar

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  7
  • Topics Per Day:  0.00
  • Content Count:  133
  • Reputation:   189
  • Joined:  05/20/12
  • Last Seen:  

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.

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  87
  • Topics Per Day:  0.02
  • Content Count:  1335
  • Reputation:   932
  • Joined:  10/26/11
  • Last Seen:  

curiosity

Thank you a lot for your time and your interest on this. At this level that is almost all it is left and we truly appreciate your help on this.

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 know what you mean, but perhaps we can only try to increase that max value of GR2 IDs for now. That would be enough for us :P. Now Regarding increasing the animation indexes per one model being complex, it was just a thought and forgive me if that is gonna be to complex, don't pay attention to me on that.

As you said, I'm almost sure that this instruction about max 9 GR2 IDs are hardcoded since when I tested exactly the same GR2 mob I used with the guardian reference, but with a custom ID the mob appeared with all its 3D stuff but no animation on it.

We will look further for that patched client you will bring us. We will be glad to add our thanks to you in our main project too.

Btw there are some gr2 entries that they are no longer used now, that probably we can use those are:

   [jobtbl.JT_ZOMBIE_DRAGON] = "dragon_5.gr2",
   [jobtbl.JT_HUGELING] = "Hugeling90_6.gr2",

So just as provitional I guess we have 2 available for our own purposes.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  7
  • Topics Per Day:  0.00
  • Content Count:  133
  • Reputation:   189
  • Joined:  05/20/12
  • Last Seen:  

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.

  • Upvote 1
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  87
  • Topics Per Day:  0.02
  • Content Count:  1335
  • Reputation:   932
  • Joined:  10/26/11
  • Last Seen:  

Currently I'm using 2011-03-15a, here is the client I'm using (I assume you want it allready diffed?) ---> https://dl.dropbox.com/u/52175822/2011-03-15a_Olrox.rar

Thanks!

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  7
  • Topics Per Day:  0.00
  • Content Count:  133
  • Reputation:   189
  • Joined:  05/20/12
  • Last Seen:  

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.

Edited by curiosity
  • Upvote 2
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  87
  • Topics Per Day:  0.02
  • Content Count:  1335
  • Reputation:   932
  • Joined:  10/26/11
  • Last Seen:  

You are awesome!... Tested!.

Good news: Testing now a custom entry in the luas now with your change. Now, the animations under "data/3dmob_bone/" are appearing for the custom mob id! Now the client is showing the animations for walk, die, attack for custom mobs ID! before It was all static.

However... default animation, that is stored in the default model in "data/3dmob/" is still as static.

In short, with your change, the animations under "data/3dmob_bone/" are working now. There is left the default animation "standing" which they are stored in "data/3dmob/" where in your past quote, I can tell it is refering at:


else
{
v5 = sub_6E6000(dword_7CAA8C[a_id]);
sprintf(&modelResPath, "model\\3dmob\\%s", v5);
}

Perhaps an additonal hex sequence edit is needed?

Edit: ​ Just read your line about the max vertices. That limit is pretty much more than the limits of default RSM Models. If you want to increase that value that would be awesome! since we will be able to use high detailed custom mobs 3d as the dragon we posted quite ago and it crashed due to the high polygons.

Now I wonder if the client also is storing a limit in vertices for RSM Models too.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  7
  • Topics Per Day:  0.00
  • Content Count:  133
  • Reputation:   189
  • Joined:  05/20/12
  • Last Seen:  

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.

  • Upvote 2
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  87
  • Topics Per Day:  0.02
  • Content Count:  1335
  • Reputation:   932
  • Joined:  10/26/11
  • Last Seen:  

Did a test with the default WoE Guardian as a custom ID Mob with your hex change.

Same result, default animation is static. But additional animations are working... just like my previous test with a custom GR2. So, I believe it doesn't has to do with the exporter. There must be another thing to tweak on!

I have not tested a high polygonal GR2 mob yet, with your change. Gonna make it trough the day and add my feedback about it. About RSM Limit, I don't have an exact value. In my experience doing custom RSM models, I can tell it its between 2,000 and 1.500.

But anyway, maybe we can refer for those details later?, I'm kinda clueless with this default animation, and the other bones working!

Link to comment
Share on other sites


  • Group:  Developer
  • Topic Count:  28
  • Topics Per Day:  0.01
  • Content Count:  547
  • Reputation:   270
  • Joined:  11/08/11
  • Last Seen:  

Could you maybe post the content of the field "animTypeStringTable" as it should show, which animation types are possible so we can line them up more easily.

Also it seems that you should find the method that calls getGrannyModel since it already sends the a_type which leads to the animation type, which is 0 for the default animation.

Edit:

Seems like the animation indexes(?) are static and uses the following IDs:

void __thiscall C3dGrannyGameActor::SetAction(C3dGrannyGameActor *this, int action, int speed, int type)
{
 C3dGrannyGameActor *v4; // esi@1
 struct granny_control **v5; // edi@10
 signed int v6; // ebx@10
 int v7; // eax@12

 v4 = this;
 this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 0;
 switch ( action )
 {
case 48:
  this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 4;
  break;
case 80:
case 88:
  this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 2;
  break;
case 64:
  this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 3;
  break;
case 0:
  this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 0;
  break;
case 8:
  this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 1;
  break;
case 24:
  this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 5;
  break;
case 32:
  this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 11;
  break;
case 40:
  this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 12;
  break;
default:
  break;
 }
 this->m_nLastActAnimation = this->baseclass_0.baseclass_0.baseclass_0.m_stateId;
 v5 = this->m_Control;
 v6 = 20;
 do
 {
C3dGrannyModelRes::DeActAnimation(v4->m_GrannyActorRes, *v5);
*v5 = 0;
++v5;
--v6;
 }
 while ( v6 );
 v7 = v4->m_nLastActAnimation;
 LODWORD(v4->m_GameClock) = 0;
 if ( type == 1 )
v4->m_Control[v4->m_nLastActAnimation] = C3dGrannyModelRes::ActAnimation(
										   v4->m_GrannyActorRes,
										   v7,
										   v4->m_Instance,
										   v4->m_Control[v7],
										   1);
 else
v4->m_Control[v4->m_nLastActAnimation] = C3dGrannyModelRes::ActAnimation(
										   v4->m_GrannyActorRes,
										   v7,
										   v4->m_Instance,
										   v4->m_Control[v7],
										   0);
}

void __thiscall CGrannyPc::SetAction(CGrannyPc *this, int action, int speed, int type)
{
 if ( this->m_GrannyActorRes )
 {
this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 0;
switch ( action )
{
  case 48:
	this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 4;
	CGrannyPc::SetGrannyAction(this, type);
	break;
  case 80:
  case 88:
	this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 2;
	CGrannyPc::SetGrannyAction(this, type);
	break;
  case 64:
	this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 3;
	CGrannyPc::SetGrannyAction(this, type);
	break;
  case 0:
	this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 0;
	CGrannyPc::SetGrannyAction(this, type);
	break;
  case 8:
	this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 1;
	CGrannyPc::SetGrannyAction(this, type);
	break;
  case 24:
	this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 5;
	CGrannyPc::SetGrannyAction(this, type);
	break;
  case 32:
	this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 11;
	CGrannyPc::SetGrannyAction(this, type);
	break;
  case 40:
	this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 12;
	CGrannyPc::SetGrannyAction(this, type);
	break;
  case 16:
	this->baseclass_0.baseclass_0.baseclass_0.m_stateId = 6;
	goto LABEL_12;
  default:
LABEL_12:
	CGrannyPc::SetGrannyAction(this, type);
	break;
}
 }
}

I'll try to discover what are each ActionID, maybe they are indexed like ACTs files are.

GreenBox could you also please post this function

CGrannyPc::SetGrannyAction(this, type);

Thanks in advance. :)

Edited by Lemongrass
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  7
  • Topics Per Day:  0.00
  • Content Count:  133
  • Reputation:   189
  • Joined:  05/20/12
  • Last Seen:  

Could you maybe post the content of the field "animTypeStringTable" as it should show, which animation types are possible so we can line them up more easily.

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"

Also it seems that you should find the method that calls getGrannyModel since it already sends the a_type which leads to the animation type, which is 0 for the default animation.

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.

Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  22
  • Reputation:   44
  • Joined:  08/07/12
  • Last Seen:  

Just wondering, what is the exact problem now? The "default" animation is the wait one, which is included in the gr2 file holding the model data. What you're trying to do is... change this? I don't understand o.o

Link to comment
Share on other sites


  • Group:  Developer
  • Topic Count:  28
  • Topics Per Day:  0.01
  • Content Count:  547
  • Reputation:   270
  • Joined:  11/08/11
  • Last Seen:  

No, we just want to know how we have to edit/hex the client to accept custom GR2 mob IDs.

Or that is how I understand it, correct me if I am wrong please. :D

Edited by Lemongrass
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  87
  • Topics Per Day:  0.02
  • Content Count:  1335
  • Reputation:   932
  • Joined:  10/26/11
  • Last Seen:  

Ricky92 Hi man, let me explain.

Ragnarok Online handles 2 types of -monsters-. Sprite mobs and 3D mobs.

After Installing Ragnarok Online, they stores the gr2 resources at these paths when installing:

  • "data/model/3dmob/" <-- Common gr2 files which includes the default animaton. The default last gr2 in the game installacion is named as "sguardian90_9.gr2". This "_9" is the id of this model.
  • "data/model/3dmob/bone" <-- Aditional gr2 files which has only bones of the previous gr2 listed. The max amount is 4 per monster. To our previous example, the animations are named as "9_attack.gr2", "9_damage,gr2","9_dead.gr2","9_move,gr2".

Additional, the "sguardian90_9.gr2" file is listed easily and handy (thanks by a previous decompiler of these lua files, made by our community) at;

  • data/lua files/datainfo/jobname.lua <-- Basically its function is about giving a name of the files listed, in our case "sguardian90_9.gr2" to only "SOLDIER_GUARDIAN".
  • data/lua files/datainfo/npcidentity.lua <-- Asigns an additional ID to this "SOLDIER_GUARDIAN" . This ID is used at the rAthena server emulator database, which it is asked at summonning the monster.

When "sguardian90_9.gr2" is summoned in the game, the monster appears by first in its "default standing animation", which is the one included by default in this gr2 file (as you see we are not changing this, it is just as how you said that the default animation is included in the gr2). Then, if it is asked to attack , move, or die (by our server instructions) the client reads, the corresponding id bones animations of this monster id.gr2 files And, shows it.

This Ragnarok game has 9 reserved ID monsters as the example I said, installed by default. Which they all follow this same structure of working. All these time doing our examples has been by replacing one of those 9 ID monsters.

Until some days we have been only testing our custom GR2 monsters thanks by your exporter, by naming our GR2 files just by replacing one of the installed by default. And all tests regarding this are good.

==================================

From this, we are moving onwards to the second part of this project:

It is about, using our custom gr2 files without having to replace one of these IDs. This is not new to us, since we are allready able to do it by only adding the new entries in the lua files I listed before. So as adding the new entry in the rAthena server database.

Our concern is, that, by doing this. this same GR2 monster that we have tested all these time and works pretty well by replacing an existing ID, now, as a new custom entry ID, it is summoned sucessfully in the Game, however,

it appears as a static model when you are standing. So as when you are walking, it continues to be static.

What is happening is that the Game Client, the exe, has a hardcoded function which tell what gr2 monster will have animation, and what not. At this point, This member: Curiosity accepted to give a try to this, and by looking at the client (for what we use IDA Interactive Dissambler) he found this function:

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;
}

Exactly quoting this line of the previous code, this is what limits the "Sguardian90_9.gr2". being the last "9" ID reserved to be readed as an animated monster.

"if ( (unsigned int)a_id <= 9 )"

Increasing this value hardcoded in the Game Client, overrides this limit, and makes possible that now, it reads additional gr2 files,and shows its animation by custom gr2 IDs besides the lastest listed as "_9" . What it has no sense until now, is, that it only shows the animations under "data/model/3dmob_bone/" So when the monster is standing it continues to be static, but when moving/attacking/etc, it is showing animation.

I thought that it was good to explain it all. (Since Ricky92 doesn't has to do with our emu, our client or data files it uses) But in short:

No, we just want to know how we have to edit/hex the client to accept custom GR2 mob IDs.

That is!

  • Upvote 2
Link to comment
Share on other sites


  • Group:  Members
  • Topic Count:  0
  • Topics Per Day:  0
  • Content Count:  22
  • Reputation:   44
  • Joined:  08/07/12
  • Last Seen:  

I understand, thank you for the explanation Olrox :)

I know how to use IDA Pro, so I might as well try to check why it's behaving like that. I'll analyze the launcher you've uploaded on DropBox.

  • Upvote 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...