Project 137

A forum to show of the stuff you did for your server.

Moderators: osRose dev team, ospRose dev team, osiRose dev team, Moderators

Re: Project 137

Postby PurpleYouko on Thu Mar 17, 2016 2:44 pm

L3nn0x wrote:Lol that should be the other way around actually :?

Anyway the pack macro is really only needed when dealing with raw buffer that you want to cast into a struct. Otherwise the best thing is just to let the compiler decide cause he's much smarter than us :mrgreen:

I've seen this kind of error twice and it's really when you're messing around with raw pointers and uncontrolled buffer writes. And it's a real pain to debug because you have to check every new/malloc/realloc/delete/free and manually keep track of where and how much you write to those buffers... I'm thinking about raw heap allocated arrays mainly.

One last thing that hit me when reading your messages again Purple is that the best list container is std::list and not std::vector. And iterators are the perfect way to iterate over lists.


The problem with using std::list as opposed to std::vector is that there is no easy way to use random access in a list. It literally has to be iterated from the start every time.
That wouldn't be a problem really with visibility lists except for my rewritten (more efficient if it actually ever works) version where I delete elements that are no longer needed from the middle and push new ones onto the end making it a dynamically variable structure.
If we just keep doing it the old way then we build up a local list from the old one then delete the old one and copy the temporary one into it. That would work great for std::list
In a lot of places we aren't really using vectors the way they are designed to be used. You will barely find an 'erase' command anywhere in the whole server.
You are right that std::list would be better if that's all we ever do.

Having said that though, I think the problem isn't with the vector at all, I'm pretty sure it's a memory management issue related to the inventory structure. Every time I find a problem it seems to be that an inventory item has been written over a bit of memory already allocated to another structure.
These structures are all arrays which are defined at compile time so i need to be looking for a sub-structure that is dynamically modified at run time. I'm betting that when I go through it with a fine tooth comb I'll find something like a vector inside the structure that's throwing out memory allocation on a big scale. Since Vectors guarantee a contiguous block of memory this would make sense. A list, on the other hand would just grab a free space somewhere and set a pointer to it so the same problem wouldn't be likely to occur.
Need to lookup information on NARose items, skills, quests?
Now featuring a newly completed skill tree for all classes
Formatting fixed for different resolutions
Image

"A Gazelle is nothing but a giraffe plotted logarithmicaly"
User avatar
PurpleYouko
Rose Guru
Rose Guru
 
Posts: 4733
Joined: Fri Aug 10, 2007 2:05 pm

Re: Project 137

Postby PurpleYouko on Thu Mar 17, 2016 2:46 pm

Hazuki wrote:Been a while since I've poked around Rose, good to see you still working on stuff Purple! Hope all's well :)

hey Haz

Everything's good here. Grats on the wedding :D
Need to lookup information on NARose items, skills, quests?
Now featuring a newly completed skill tree for all classes
Formatting fixed for different resolutions
Image

"A Gazelle is nothing but a giraffe plotted logarithmicaly"
User avatar
PurpleYouko
Rose Guru
Rose Guru
 
Posts: 4733
Joined: Fri Aug 10, 2007 2:05 pm

Re: Project 137

Postby L3nn0x on Thu Mar 17, 2016 2:56 pm

PurpleYouko wrote:
L3nn0x wrote:Lol that should be the other way around actually :?

Anyway the pack macro is really only needed when dealing with raw buffer that you want to cast into a struct. Otherwise the best thing is just to let the compiler decide cause he's much smarter than us :mrgreen:

I've seen this kind of error twice and it's really when you're messing around with raw pointers and uncontrolled buffer writes. And it's a real pain to debug because you have to check every new/malloc/realloc/delete/free and manually keep track of where and how much you write to those buffers... I'm thinking about raw heap allocated arrays mainly.

One last thing that hit me when reading your messages again Purple is that the best list container is std::list and not std::vector. And iterators are the perfect way to iterate over lists.


The problem with using std::list as opposed to std::vector is that there is no easy way to use random access in a list. It literally has to be iterated from the start every time.
That wouldn't be a problem really with visibility lists except for my rewritten (more efficient if it actually ever works) version where I delete elements that are no longer needed from the middle and push new ones onto the end making it a dynamically variable structure.
If we just keep doing it the old way then we build up a local list from the old one then delete the old one and copy the temporary one into it. That would work great for std::list
In a lot of places we aren't really using vectors the way they are designed to be used. You will barely find an 'erase' command anywhere in the whole server.
You are right that std::list would be better if that's all we ever do.

Having said that though, I think the problem isn't with the vector at all, I'm pretty sure it's a memory management issue related to the inventory structure. Every time I find a problem it seems to be that an inventory item has been written over a bit of memory already allocated to another structure.
These structures are all arrays which are defined at compile time so i need to be looking for a sub-structure that is dynamically modified at run time. I'm betting that when I go through it with a fine tooth comb I'll find something like a vector inside the structure that's throwing out memory allocation on a big scale. Since Vectors guarantee a contiguous block of memory this would make sense. A list, on the other hand would just grab a free space somewhere and set a pointer to it so the same problem wouldn't be likely to occur.


Yes of course, but I don't really know how you want to modify the code so I can't really advise on it ;)

The problem you mention is exactly the kind of problem that came to my mind when you stated your error.
Try looking at the loops/memcpy that write to those static arrays and make sure they don't write outside of the structs. That's all I can think of right now, without the source code.
L3nn0x
osiRose dev
osiRose dev
 
Posts: 111
Joined: Wed Oct 21, 2015 8:22 pm

Re: Project 137

Postby PurpleYouko on Thu Mar 17, 2016 4:23 pm

I agree. It's what I first thought was happening when I encountered the weirdness with the inventory wiping the first 3 skills when the CItems->stats member was loading.
Now it's overwriting my wishlist so that 3 items are being added to the packet right in the middle, except that the values are in the wrong fields (item type -375, item number 12101). That sort of thing.

As for source, 90% of the source is unmodified rev 81.35 (drop rev immediately before DR2 was released)
All I've really done is modify the way in which data is loaded from the database and added/subtracted a few static members to a few structures.
I have one database entry for each character's items, tokenized for each member of the CItem structure so I no longer delete every entry for a player before rebuilding it from scratch the way it used to. Now it just modifies the existing entry when it saves. I've been using this system in KTRose source for years without any problems.
The issues seemed to arise when I started making changes to the CItem structure to add UStats and to redesign the way that item headers and data are added to a packet.

I suspect the underlying issues have been there all along in some form.

One change that I made was to add a union into the citem struct. Wonder if that caused it? shouldn't have really.
this is what I have now.
  1.  
  2. class CItem
  3. {
  4. public:
  5.     unsigned short GetPakHeader( );
  6.     unsigned GetPakData( );
  7.     unsigned GetVisInfo( );
  8.     void Clear( );
  9.  
  10.     inline bool IsStackable()
  11.     {
  12.         return (itemtype >= 10) && (itemtype <= 13);
  13.     };
  14.     union
  15.     {
  16.         struct
  17.         {
  18.             BYTE    itemtype;
  19.             WORD    itemnum;
  20.             BYTE    isCreated;
  21.         };
  22.         DWORD HEADER;
  23.     };
  24.     unsigned short    gem;
  25.     BYTE    refine;
  26.     short    lifespan;
  27.     UINT    durability;
  28.     bool    socketed;
  29.     bool    appraised;
  30.     unsigned short    count;
  31.     short    stats;
  32.     UINT    durabLeft;
  33.     int sp_value;
  34.     int last_sp_value;
  35.     UINT    type;
  36.     UINT    raretype;
  37.    
  38.     short   UStat[2];       //PY Unique stats that each item can have
  39.     short   UValue[2];      //PY The value in the unique stats
  40. };
  41.  

I needed the DWORD Header value for some of the old code. It used to come from the GetItemHead() function but that no longer exists.

ABE
Really can't find anything obviously wrong with the inventory. No data structures other than static arrays are ever used. best i can do here is get rid of all the 'int's to replace them with better defined variables such 'short's, 'DWORD's and such. Makes bitwise memory management a little easier but I doubt it's the underlying problem.

Looking through where vectors are used though may be a bit more fruitful
This concerns me a little.
  1. vector<CPlayer*>            VisiblePlayers;    // Visible players

in player.h
So basically every player's structure contains a vector of indeterminate size and inside each member of that vector there is another vector. ad infinitum. Nested vectors don't seem like the best idea to me.
I wonder if this vector would be better off as
  1. vector<DWORD>           VisiblePlayers;    // Visible players

where the only thing stored in the vector is the clientid of each other player within view.
I'm still not really fond of using a dynamic structure that requires a contiguous memory space inside a structure like CPlayer which is subject to constant flux of players joining and leaving. It's kind of asking for trouble IMO
Need to lookup information on NARose items, skills, quests?
Now featuring a newly completed skill tree for all classes
Formatting fixed for different resolutions
Image

"A Gazelle is nothing but a giraffe plotted logarithmicaly"
User avatar
PurpleYouko
Rose Guru
Rose Guru
 
Posts: 4733
Joined: Fri Aug 10, 2007 2:05 pm

Re: Project 137

Postby L3nn0x on Thu Mar 17, 2016 5:40 pm

PurpleYouko wrote:I agree. It's what I first thought was happening when I encountered the weirdness with the inventory wiping the first 3 skills when the CItems->stats member was loading.
Now it's overwriting my wishlist so that 3 items are being added to the packet right in the middle, except that the values are in the wrong fields (item type -375, item number 12101). That sort of thing.

As for source, 90% of the source is unmodified rev 81.35 (drop rev immediately before DR2 was released)
All I've really done is modify the way in which data is loaded from the database and added/subtracted a few static members to a few structures.
I have one database entry for each character's items, tokenized for each member of the CItem structure so I no longer delete every entry for a player before rebuilding it from scratch the way it used to. Now it just modifies the existing entry when it saves. I've been using this system in KTRose source for years without any problems.
The issues seemed to arise when I started making changes to the CItem structure to add UStats and to redesign the way that item headers and data are added to a packet.

I suspect the underlying issues have been there all along in some form.

One change that I made was to add a union into the citem struct. Wonder if that caused it? shouldn't have really.
this is what I have now.
  1.  
  2. class CItem
  3. {
  4. public:
  5.     unsigned short GetPakHeader( );
  6.     unsigned GetPakData( );
  7.     unsigned GetVisInfo( );
  8.     void Clear( );
  9.  
  10.     inline bool IsStackable()
  11.     {
  12.         return (itemtype >= 10) && (itemtype <= 13);
  13.     };
  14.     union
  15.     {
  16.         struct
  17.         {
  18.             BYTE    itemtype;
  19.             WORD    itemnum;
  20.             BYTE    isCreated;
  21.         };
  22.         DWORD HEADER;
  23.     };
  24.     unsigned short    gem;
  25.     BYTE    refine;
  26.     short    lifespan;
  27.     UINT    durability;
  28.     bool    socketed;
  29.     bool    appraised;
  30.     unsigned short    count;
  31.     short    stats;
  32.     UINT    durabLeft;
  33.     int sp_value;
  34.     int last_sp_value;
  35.     UINT    type;
  36.     UINT    raretype;
  37.    
  38.     short   UStat[2];       //PY Unique stats that each item can have
  39.     short   UValue[2];      //PY The value in the unique stats
  40. };
  41.  

I needed the DWORD Header value for some of the old code. It used to come from the GetItemHead() function but that no longer exists.

ABE
Really can't find anything obviously wrong with the inventory. No data structures other than static arrays are ever used. best i can do here is get rid of all the 'int's to replace them with better defined variables such 'short's, 'DWORD's and such. Makes bitwise memory management a little easier but I doubt it's the underlying problem.

Looking through where vectors are used though may be a bit more fruitful
This concerns me a little.
  1. vector<CPlayer*>            VisiblePlayers;    // Visible players

in player.h
So basically every player's structure contains a vector of indeterminate size and inside each member of that vector there is another vector. ad infinitum. Nested vectors don't seem like the best idea to me.
I wonder if this vector would be better off as
  1. vector<DWORD>           VisiblePlayers;    // Visible players

where the only thing stored in the vector is the clientid of each other player within view.
I'm still not really fond of using a dynamic structure that requires a contiguous memory space inside a structure like CPlayer which is subject to constant flux of players joining and leaving. It's kind of asking for trouble IMO


Well first for you vector of CPlayer* it's not a vector of arrays but a vector of pointers to CPlayer, which means that the vector only holds a std::ptr_t (a size_t is usually a good estimation of the size) that points to a in heap memory zone containing your CPlayer. So no it's okay really. Maybe you could use std::unique_ptr instead of raw pointer if you can build with C++11 enabled.

I'm more concerned about the union actually. How do you populate it? I suppose it's with memcpy or some other cast of some kind, otherwise you wouldn't use an union. Did you try packing the struct inside the union? The compiler may add padding to your struct, resulting in a struct bigger than a DWORD, thus creating problems if you use it to separate things in the DWORD you are getting.

Again it's just throwing ideas at the screen :D
L3nn0x
osiRose dev
osiRose dev
 
Posts: 111
Joined: Wed Oct 21, 2015 8:22 pm

Re: Project 137

Postby PurpleYouko on Thu Mar 17, 2016 6:27 pm

the Citem class does contain a constructor which I added after these issues started to show up
  1.  
  2. CItem()//constructor
  3.     {
  4.         itemtype = 0;
  5.         itemnum = 0;
  6.         isCreated = 0;
  7.         HEADER = 0;
  8.         gem = 0;
  9.         durability = 0;
  10.         lifespan = 0;
  11.         socketed = 0;
  12.         appraised = 0;
  13.         count = 0;
  14.         stats = 0;
  15.         UStat[0] = 0;
  16.         UStat[1] = 0;
  17.         UValue[0] = 0;
  18.         UValue[1] = 0;
  19.         refine = 0;
  20.         durabLeft = 0;
  21.         sp_value = 0;
  22.         last_sp_value = 0;
  23.         type = 0;
  24.         raretype = 0;
  25.     };

There is no memset or memcopy functions involved with loading data into this structure
On initial creation of the inventory, memory is reserved for a static array.
  1. CItem items[MAX_INVENTORY];

where MAX_INVENTORY is defined as 140.

itemtype, itemnum and iscreated (and all the other stuff) are specifically set whenever an item is created. HEADER is not since I need it to be read from the same 32 bits of memory that the other 3 values populate.
My loading code reads in all 140 'itemtype's, then all 140 'itemnum's and so on from the database.
It is at the point where i set the 'stats' value for all 140 elements that the skills were being overwritten so this structure is definitely the prime suspect.
It might be better to just figure out where the HEADER variable is used and rewrite that code. then I won't even need the union so i can at least rule it out as the culprit.
I haven't really used unions a lot in the past so I'm not completely familiar with the potential pitfalls that they might introduce.
The main reason I did it this way was to mirror what the client is doing for the same structure. makes packet creation easier that way.
Also the old way of making the itemhead involved all kinds of nasty bitshifting on the server side and a whole lot of defined bitfields in the client. I stripped all that out so it uses bytes, shorts and DWORDs now on both sides.

just for interest, here is the CItem structure from the client as it now stands. I left in the old code at the top with the bitfields showing.
Note that a lot of the comments are translated from the original Korean. I signed most of my own.
  1. struct tagBaseITEM
  2. {
  3.    
  4.  
  5.  
  6.     union
  7.     {
  8.         // Equipment item structure
  9.         struct
  10.         {   
  11.             // LSB ::
  12.             // One of the two is a bit stale as.
  13.             /*
  14.             unsigned int    m_cType         : 5;    // 0~31     Item types(ITEM_CLASS)      (1 ~ 20)           
  15.             unsigned int    m_nItemNo       : 26;   // 0~1023   Ah system number(ITEM_ID)       (0 ~ 999)
  16.             unsigned int    m_bCreated      : 1;    // 0~1      The item is manufactured ?
  17.  
  18.             unsigned int    m_nGEM_OP       : 9;    // 0~512    Jewelry number(m_bHasSocket==1) Or a number of options(m_bHasSocket==0)
  19.             unsigned int    m_cDurability   : 7;    // 0~127    My old
  20.  
  21.             unsigned int    m_nLife         : 10;   // 0~1023   Life
  22.             unsigned int    m_bHasSocket    : 1;    // 0~1      Jewelry, whether or not a socket
  23.             unsigned int    m_bIsAppraisal  : 1;    // 0~1      Options verification whether or not
  24.             unsigned int    m_cGrade        : 4;    // 0~15     Rating                      (0~9)
  25.             // 16 + 16 + 16 => 48
  26.             // MSB ::
  27.             */
  28.            
  29.             //PY recode without bitfields because they are such a frickin pain in the ass
  30.             byte    m_cType;                        // 0~31     Item types(ITEM_CLASS)      (1 ~ 20)           
  31.             short   m_nItemNo;                      // 0~9999   Ah system number(ITEM_ID)       (0 ~ 999)
  32.             byte    m_bCreated;                     // 0~1      The item is manufactured ?
  33.  
  34.             short   m_nGEM_OP;                      // 0~512    Jewelry number(m_bHasSocket==1) Or a number of options(m_bHasSocket==0) or stats number
  35.             byte    m_cDurability;                  // 0~100    Durabilty 0 to 100%
  36.  
  37.             short   m_nLife;                        // 0~1023   Life span
  38.             byte    m_bHasSocket;                   // 0~1      Jewelry, whether or not a socket
  39.             byte    m_bIsAppraisal;                 // 0~1      Options verification whether or not
  40.             byte    m_cGrade;                       // 0~15     refine
  41.             //short m_uiCount;                      // 0~999    The number of items in the slot
  42.         } ;
  43.  
  44.         // Consumption, other items structure
  45.        
  46.         struct
  47.         {
  48.             /*
  49.             unsigned int    m_cType_1       : 5;    // 0~31     Item types(ITEM_CLASS)      (1 ~ 20)
  50.             unsigned int    m_nItemNo_1     : 26;   // 0~1023   Ah system number(ITEM_ID)       (0 ~ 999)
  51.             unsigned int    __dummy_0       : 1;
  52.  
  53.             unsigned int    m_uiQuantity    : 32;   // The number of (money)
  54.             */
  55.             //PY recoded
  56.             byte    m_cType_1;                      // 0~31     Item types(ITEM_CLASS)      (1 ~ 20)
  57.             short   m_nItemNo_1;                    // 0~1023   Ah system number(ITEM_ID)       (0 ~ 999)
  58.             byte    __dummy_01;                     // space keeper
  59.  
  60.             DWORD   m_uiQuantity;                   // money (note this takes up the same memory as Gem and Durability and half of life in non-stackable items)
  61.  
  62.         } ;
  63.  
  64.         // µ· ¾ÆÀÌÅÛ ±¸Á¶
  65.         struct
  66.         {
  67.             /*
  68.             unsigned int    m_cType_2       : 5;    // 0~31
  69.             unsigned int    m_nReserved1    : 26;
  70.             unsigned int    __dummy_0       : 1;
  71.  
  72.             unsigned int    m_uiMoney       : 32;
  73.             */
  74.             //PY recoded
  75.             byte    m_cType_2;                      // 0~31
  76.             short   m_nReserved1;
  77.             byte    __dummy_0;
  78.  
  79.             DWORD   m_uiMoney;                      // for some reason money transfers are sent as items with type 31, no item number and m_uiMoney as the amount
  80.         } ;
  81.        
  82.         struct
  83.         {
  84.             unsigned int    m_wHeader       : 32;   //The server is the name of a heck of a place to fix fixes m_dwHeader.
  85.             unsigned int    m_dwBody        : 32;
  86.         } ;
  87.        
  88.         struct
  89.         {
  90.             unsigned int    m_dwLSB;
  91.             unsigned int    m_dwMSB;
  92.         } ;    
  93.  
  94.         unsigned int    m_dwITEM;
  95.        
  96.     } ;
  97.  
  98.     struct  //PY added new stats structures
  99.     {
  100.         short m_UStat1;
  101.         short m_UStat2;
  102.         short m_UValue1;
  103.         short m_UValue2;
  104.     };


ABE
HEADER is only used ONE time
in the crafting packet.
I still need to completely recode that anyway so i might just as well get rid of that union and test it out without it. :D
Need to lookup information on NARose items, skills, quests?
Now featuring a newly completed skill tree for all classes
Formatting fixed for different resolutions
Image

"A Gazelle is nothing but a giraffe plotted logarithmicaly"
User avatar
PurpleYouko
Rose Guru
Rose Guru
 
Posts: 4733
Joined: Fri Aug 10, 2007 2:05 pm

Re: Project 137

Postby PurpleYouko on Thu Mar 17, 2016 7:00 pm

Got rid of the union completely and recompiled.

Same error. It gets to the visibility lists and crashes when copying newVisibleNPCs into VisibleNPCs

Here is the weird bit.
Yesterday I added a couple of lines of debug outputs into the visibility list code. It prints the size of both lists before and after the code checks for NPCs.
Before the crash it shows that the local vector (newVisibleNPCs) has a size of 4 and the master list (VisibleNPCs) has a size of zero.
Debugging just shows that the list is there and the current player has valid structures.
When I close the debugger, usually the program stops but not this time. it just keeps running around the visibility check, printing out the sizes of the two vectors over and over while otherwise greyed out and impossible to close in any way other than with the task manager.
Strangely though, BOTH vectors now have a size of 4 so it must have actually copied it over despite throwing an error :?

Also I tried to replace the vector with a list but it completely failed to compile. Kept telling me it was missing a ; before <
The header was loading fine and intelisense was seeing the list<DWORD> VisibleNPCs as a valid definition
The compiler just wouldn't play. very strange. i tried defining test lists all over the place and got the exact same error every time.

I think my computer just hates me.

I bet if I take this thing home and try it there it will all work perfectly without a hint of an error.
Need to lookup information on NARose items, skills, quests?
Now featuring a newly completed skill tree for all classes
Formatting fixed for different resolutions
Image

"A Gazelle is nothing but a giraffe plotted logarithmicaly"
User avatar
PurpleYouko
Rose Guru
Rose Guru
 
Posts: 4733
Joined: Fri Aug 10, 2007 2:05 pm

Re: Project 137

Postby Raven0123 on Thu Mar 17, 2016 7:11 pm

Did you try to use gflags? It is part of the visual studio install and would tell you exactly what is causing the issue.

if you want the command line version it would be:
  1. gflags /p /enable ImageFileName


That should give you the info you need and if it does not, add /full at the end.
User avatar
Raven0123
osiRose dev
osiRose dev
 
Posts: 379
Joined: Tue Sep 11, 2007 11:06 pm
Location: USA, NJ

Re: Project 137

Postby L3nn0x on Thu Mar 17, 2016 7:24 pm

So first, list<DWORD> VisibleNPC
I don't really know how you use this list but it should be std::list<CPlayer*> VisibleNPC with the #include <list>. Cause if you are pushing a CPlayer* onto the list and trying to cast it to a DWORD it'll technically work, but if you want to use the object you'll have to cast it back to CPlayer* and it's nasty.

Secondly, debuggers usually have some mechanisms to avoid memory management errors, so the error can disappear when you are using a debugger, don't ask why but I already saw it once...

Try the option Raven talked about, otherwise you'll have to comment out the piece of code you feel is creating the mess and test, commenting in/out at a time.
L3nn0x
osiRose dev
osiRose dev
 
Posts: 111
Joined: Wed Oct 21, 2015 8:22 pm

Re: Project 137

Postby PurpleYouko on Thu Mar 17, 2016 8:19 pm

L3nn0x wrote:So first, list<DWORD> VisibleNPC
I don't really know how you use this list but it should be std::list<CPlayer*> VisibleNPC with the #include <list>. Cause if you are pushing a CPlayer* onto the list and trying to cast it to a DWORD it'll technically work, but if you want to use the object you'll have to cast it back to CPlayer* and it's nasty.

Secondly, debuggers usually have some mechanisms to avoid memory management errors, so the error can disappear when you are using a debugger, don't ask why but I already saw it once...

Try the option Raven talked about, otherwise you'll have to comment out the piece of code you feel is creating the mess and test, commenting in/out at a time.

I'm using a DWORD to hold the clientid.
It seems wasteful of resources (memory particularly) to make a list using the entire CPlayer structure for each element.
It's really easy to just cast the NPC from the list when needed.
The same trick has already been done for the monster and player lists so I just changed NPCs to use the same method. The error were happening with the old method. I've only just made this change now for testing.

Haven't tried the gflags thing yet.
Mainly because I'm still not entirely sure how or where to use it.
I'm reading up on it at MSN and other places.

Ok so it seems that my computer doesn't have gflags.exe anywhere on it.....
Now i have to figure out how to get it without installing something which will cause problems with my win7 64 bit installation
found this on the microsoft site
Important: Newer versions of the Visual C++ 2010 Redistributable can cause issues when you install the SDK for Windows 7. For more information, see support for the Windows SDK.


When I say "debugger" I don't mean that I'm running from a prompt.
I'm running the exe then when it crashes I'm loading it back into VS2010 in a frozen state so i can examine all the variables and see the call stack and so on
Need to lookup information on NARose items, skills, quests?
Now featuring a newly completed skill tree for all classes
Formatting fixed for different resolutions
Image

"A Gazelle is nothing but a giraffe plotted logarithmicaly"
User avatar
PurpleYouko
Rose Guru
Rose Guru
 
Posts: 4733
Joined: Fri Aug 10, 2007 2:05 pm

PreviousNext

Return to Pimp My Rose

Who is online

Users browsing this forum: No registered users and 4 guests