EJ's mistake and the decline of Xenimus

For general discussion of Project Volucris

Moderators: Joe M., Karl G.

EJ's mistake and the decline of Xenimus

Postby Ratiotile » Wed Jul 11, 2007 9:06 am

From Words from EJ:
"About the update 10/21/02

THE DAMAGE SYSTEM - I did make a change to the damage system. It has nothing to do with resist settings. Basicly it works like this, a player or monster will always do 20% of the damage they tried to do. So if they hit you, your going to take at least some damage. "


EJ's 20% damage system was the beginning of the decline of Xenimus. Around the same time he created no-trans zones, removed the old mystic chests, and implemented retroactive stats. Then the next year he did the spell system update and completely killed old xen. This is about the time when Xenimus stopped being fun to me and many other players. The 20% update basically killed Xenimus for me.

The 20% damage rule was one of the factors that influenced the rise of the cons mages (which EJ hates but is clueless on how to stop, as he doesn't think that it is possible for him to make a mistake). Back before the update there were legendary mages like FLIPP and this crazy mp-cleric whose name I can't remember. Nowadays we have people like HiTwo with all-cons builds. 20% damage made leveling as a newbie even harder than it was before. I'll never forget leveling my lvl 1 cleric with 4hp after the update. How am I supposed to level when I am killed in 2 hits by rogues? At least pre-update I could load my guy up with armor and only take 1hp damage each hit and actually stand a chance! EJ needs to play his own game starting from level 1.

20% damage also made resists worthless. It used to be that one could pump up wisdom and get incredibly good resists that allowed them to fight adepts and such taking almost no damage. It seems like EJ didn't like that and so he made the mages pump cons instead, which is coming back to bite him. Now mages get a lot of cons so they can tank as well as fighters, because they are FORCED TO. It doesn't matter that they have more armor spells, because most damage comes from that 20% leaking through. The new damage rule was a horrible idea that EJ put in because he was too lazy to re-evaluate and fix the hp/damage system.

In fact, many stupid ideas directly result in EJ being too lazy to make a better system. He doesn't care about his game! But no, he would rather spend most of his time playing WoW (where he copied good vs. evil and the map from. The other stuff he copied from Diablo 2). EJ keeps adding on new features that only touch the surface problems with his game. The damage system needed to get fundamentally reworked but it is still there, festering. It seems like players have gotten used to their 15% damage going through, because I've stopped seeing any posts about it in recent years, what a shame.

When I found out about Project Volucris I was overjoyed. Finally the players could have a better game with a dev team that actually listens to what the players want and create intelligent updates, and deal with dupers effectively rather than being lazy and simply clearing items. EJ singlehandedly piloted his game down the drain, which wouldn't happen with more developers who keep in touch with the playerbase. I'd take a more democratic system over EJ's iron-fisted dictatorship any day.

I definitely want this project to succeed, so I am prepared to help in any way I can. I am proficient at C++ and I can help with game mechanics. Creating a game like this is hard for one man alone, so please tell me how I can help.
User avatar
Ratiotile
Sheriff
Sheriff
 
Posts: 109
Joined: Tue Jul 10, 2007 7:13 am

Postby a_link_to_the_past » Wed Jul 11, 2007 11:39 am

Awesome, I am sure Karl could use the help of another programmer... I wish I knew what Xenimus was like before the spell update and the 20% dmg update
User avatar
a_link_to_the_past
Sheriff
Sheriff
 
Posts: 157
Joined: Tue May 22, 2007 3:37 pm

Postby Karl G. » Wed Jul 11, 2007 6:19 pm

Ratiotile,

I could definitely use a hand with the game mechanics programming. I need to know more about your C++ proficiency before assigning you any tasks, however, because there are a lot of considerations. At this point, you've come at a perfect time because I haven't started implementing the complete forms of the core game mechanics (leveling, hp/mp, damage, spells, cast rate, etc). I've just been using stand-ins to return generic values (GetPlayerMaxHP always returns 10, for example).

Would you be comfortable implementing a set of interfaces that details the leveling process? It would essentially mean implementing the Xenimus stat-calculator but in a more flexible way--I'd like to be able to "tweak" the game mechanics without too much hassle. Could you describe your experience?
User avatar
Karl G.
Lesser Spirit
 
Posts: 2453
Joined: Sat Mar 04, 2006 10:26 am

Postby Ratiotile » Wed Jul 11, 2007 8:55 pm

Proficiency-wise I have used everything in the language besides the bitwise operators, sets and stuff. I don't have any experience in writing network code however. I could definitely write behind-the-scenes code for hp, leveling, spells, inventory, skills, and other mechanics. Using OOP it wouldn't be hard to integrate code written by different programmers. It would be easiest if you sent me a short piece of code so I could see how I measure up. As for the stat/level interface my first thought was to build it into the character class. For example:

Code: Select all
class Character
{
public:
   Character(string charClass, string name);
   string getName();
   string getClass();
   int getBaseHP();
   int getBaseMP();
   int getMaxHP();
   int getMaxMP();
   int getLevel();
   void levelUp();
   int getFreeStatPoints();
   bool addPointToStat(char whichStat);
   void getShrineStatus(bool shrineArray[]);
   void setShrineStatus(bool shrineArray[]);
   void getJelocStatus(bool shrineArray[]);
   void setJelocStatus(bool shrineArray[]);
   int getHPBases();
   void setHPBases(int HPbases);
   int getMPBases();
   void setMPBases(int MPbases);
   int getAlignment();
   void setAlignment(int align);
};


I understand that you might want it in an actual 'interface', but I couldn't think of a good way to design it. Should I have defined an interface Levelable? It doesn't seem to fit, as the class character would be the only class implementing that interface.

Anyway, if you could send me a small sample of code I can tell you if I'm up for it. It would probably be better if it wasn't network based though. I should be alright with some graphical stuff, as I have used some OpenGL before. I don't know Directx but I can learn to handle anything 2d fairly quickly.
User avatar
Ratiotile
Sheriff
Sheriff
 
Posts: 109
Joined: Tue Jul 10, 2007 7:13 am

Postby Karl G. » Thu Jul 12, 2007 5:20 am

Can you understand this?

Code: Select all
//------------------------------------------------------------------------------------------------
// Name: CreateNewCharacter
// Desc: Generates a new entry in the character database
//------------------------------------------------------------------------------------------------
BOOL AdminDatabase::CreateNewCharacter( const CHAR* pName, Gender g, Race r, Class c, BYTE Str,
                                        BYTE Agi, BYTE Con, BYTE Int, BYTE Wis,
                                        DWORD* pReturnedCharacterID )
{
    // This structure temporarily holds all of the information about the character
    Character character;
    ZeroMemory( &character, sizeof(Character) );

    // Copy in data directly from the parameters
    strncpy_s( character.Name, 32, pName, 26 ); // TODO: get rid of numeric constants
    character.avatarGender = g;
    character.avatarRace = r;
    character.avatarClass = c;

    // Get the maximum value for each stat for this race and make sure the stats aren't
    // messed up.  They can't exceed the maximum or dip below 10, and the total must be
    // between (5*10) and (25 + 5*10)
    BYTE maxStr, maxAgi, maxCon, maxInt, maxWis;
    GetMaxStartingStats( character.avatarRace, &maxStr, &maxAgi, &maxCon, &maxInt, &maxWis );
    int totalStats = Str + Agi + Con + Int + Wis;
    if( (Str > maxStr) || (Agi > maxAgi) || (Con > maxCon) || (Int > maxInt) || (Wis > maxWis) ||
        (Str < 10) || (Agi < 10) || (Con < 10) || (Int < 10) || (Wis < 10) ||
        (totalStats <5> 25 + 5*10) ||
        (character.avatarGender >= __GENDER_COUNT__) ||
        (character.avatarRace >= __RACE_COUNT__) ||
        (character.avatarClass >= __CLASS_COUNT__) )
        return FALSE;

    // Save the character stats into the structure
    character.Str = Str;
    character.Agi = Agi;
    character.Con = Con;
    character.Int = Int;
    character.Wis = Wis;

    // Initialize default character settings
    // TODO: add initializers here
    character.Level = 1;
    character.MapID = 0;
    character.MapX = -37224.020f;
    character.MapY =   4887.287f;
    character.CurrentHP = character.MaxHP = 10;
    character.CurrentMP = character.MaxMP = 10;

    // Make sure this name isn't already taken (this algorithm is really slow and could probably
    // be improved by some sort of hashing)
    BeginCharacterCS();
    for( CharacterIterator ch = m_Characters.begin(); ch != m_Characters.end(); ++ch )
        if( 0 == strcmp( ch->second.Name, pName ) ) { EndCharacterCS(); return FALSE; }

    // Get the next ID for this character
    character.UniqueID = ++m_NextCharacterID;

    // Add this character to the database
    CharacterInsertResult result = m_Characters.insert( CharacterEntry( character.UniqueID, character ) );

    // Leave the critical section
    EndCharacterCS();

    // Make sure it succeeded
    if( !result.second ) return FALSE;

    // Return this ID
    *pReturnedCharacterID = character.UniqueID;

    // It has been added successfully
    return TRUE;
}
User avatar
Karl G.
Lesser Spirit
 
Posts: 2453
Joined: Sat Mar 04, 2006 10:26 am

Postby Ratiotile » Thu Jul 12, 2007 5:56 am

I understand perfectly. You're using the windows datatypes. What is the advantage for using them? Is it because they are smaller and more efficient?
Maybe consider using larger datatypes for future flexibility?
I agree that the characters should be stored or indexed using a large hashtable if speed is critical. Are you using a map right now?
I recently took a course that covered data structures so this stuff is fresh in my mind.
User avatar
Ratiotile
Sheriff
Sheriff
 
Posts: 109
Joined: Tue Jul 10, 2007 7:13 am

Postby Karl G. » Thu Jul 12, 2007 6:16 am

I'm using the Windows-style data-types because that's what I learned to use; I understand the appeal of intrinsic types, but the Windows types can be faster at times (BOOL is actually a 32-bit integer, for example, which is faster to push around because it fits the register size).

I'm using std::hash_map for the characters (and pretty much everything else) because it provides near O(1) lookup time for character indices. Also: although I respect OOP, I do not use it for everything--for example, Character is simply a struct because so many different things need access to its members that it would be pointless to abstract them at this point.

My general philosophy:

1. Make it work
2. Make it efficient
3. Make it secure
4. Make it "pretty" <-- OOP goes here


Also, as you can probably tell, I have a very different code style than you may be used to. Although I have in the past, I don't use the Java types right now because they make the code ugly. If it only takes simple things like changes in capitalization, I'm all for making appealing, readable code. For example, using a lower-case first letter in class member functions looks dumb when you have to write it after a "::" or "->". I'm not sure why, but that's just my feeling....anyway, I'm getting philosophical about my code, but if you can understand it, then I think we can definitely work something out. Have you looked at this and can you understand that code? It's a bit higher on the complexity level but shouldn't be bad at all.
User avatar
Karl G.
Lesser Spirit
 
Posts: 2453
Joined: Sat Mar 04, 2006 10:26 am

Postby Ratiotile » Thu Jul 12, 2007 7:29 am

Good philosophy.
As for code formatting, I usually use camel notation, indents, and newlines with squiggly brackets to make the code more readable.
If you like to use pascal notation, that's fine with me.
I got hooked onto the OOP bandwagon because it made my code easier to understand and more modular.
The best part was that my code often ran correctly the first time it compiled. :D

Your networking code makes networking look much easier than I expected. I gave up on CCNA 3 years ago because those Cisco guys are really good at making networking look hard. Maybe they get paid more that way...

Once I got past the D3d stuff I was pretty much alright with the code. (I know packets, but must read up on sockets)
Haven't used the winsock api before, seems that I can work with it. I will need to study it before writing anything using it.
Generally I understood what you were trying to do. It wasn't crystal clear like English, not was it Greek to me.
I feel that if i played around with it for a while I may be able to do something with your code, like add in chat.

On another note, I gather that Thadius has been looking at the code. How is he doing? I remember seeing Thadius on Xentales as "the C++ Programmer".

EDIT:
Oh, and if you want the stat calc functions I could write it up and put them in their own class. It would be usable on it's own but could be transplanted into the character body if needed later. I would just have to reverse-engineer the formulas from the stat calc. It would go faster if we could get the original source
User avatar
Ratiotile
Sheriff
Sheriff
 
Posts: 109
Joined: Tue Jul 10, 2007 7:13 am

Postby thadiusofx3 » Thu Jul 12, 2007 11:28 am

Yeah, I understand it fine. It's just hard to collaborate on a project without some formal system setup to do so.
Also, I can't get heavily involved right now because I work 10-12 hours a day, and if I'm depended upon to write some code and I don't have time, I don't want to be responsible for that.

That isn't to say I haven't been doing anything, though. I've written some small games, and am working my way up in Directx. Also wrote a UDP chat client for fun.

I haven't looked at the network code, Karl, but I assume you are using UDP?
Image
Thus spake the master programmer, "After three days without programming, life becomes meaningless"
User avatar
thadiusofx3
Knight
Knight
 
Posts: 887
Joined: Mon Dec 18, 2006 11:46 pm
Location: Jonesboro, AR

Postby Karl G. » Thu Jul 12, 2007 2:17 pm

Yep, UDP is the way to go

Ratiotile, you can use any notation you wish--I'm just saying that's what I'm going to use because I built a system that I like around it. If I ever get around to changing everything at once, I might move to the newer notation, but I don't want to have a bastardized version of both.

So I was thinking on my way to work this morning: could you develop a system that keeps track of all the "actors" in the world? I'm thinking some sort of graph that allows me to, very quickly, check to see whether or not two things should be interacting. For example, when a player says something, who should the message be sent to? Which monsters should I check for damage if the player has some sort of area effect? That kind of thing. The implementation should be based around:

struct Actor
{
FLOAT MapX, MapY;
};

Also, it can't scale with map size, and should scale minimally with number of actors (this way, we can have more actors in the world!) The class should return a list of actors near a given location if provided with that location, and be able to find a list of actors "near" another actor. Nearness should be a defined constant (it will eventually be the size that is visible in the screen)
User avatar
Karl G.
Lesser Spirit
 
Posts: 2453
Joined: Sat Mar 04, 2006 10:26 am

Postby Ratiotile » Thu Jul 12, 2007 6:58 pm

Sure, I'll give the graph a shot. How about creating a coding subforum? Or where should I post if I want to discuss it, the mechanics forum?

Do you still want that hp/mp calculator? I have deciphered part of Halloween's formula. It turns out that hp is quadratically related to level. Also discovered the ratio of HP between the classes. Maybe we should have a separate subforum after all if you want to keep formulas and such a secret. If I keep working on the HP calculations, I should be done in a week, pending unforeseen setbacks.
User avatar
Ratiotile
Sheriff
Sheriff
 
Posts: 109
Joined: Tue Jul 10, 2007 7:13 am

Postby Karl G. » Thu Jul 12, 2007 9:16 pm

Yeah, I'd like to keep the game mechanics private--not because I think they're "super secret" or because I'm trying to keep stuff from everyone, but I think that if things are unknown they're more interesting :)
User avatar
Karl G.
Lesser Spirit
 
Posts: 2453
Joined: Sat Mar 04, 2006 10:26 am

Postby thadiusofx3 » Fri Jul 13, 2007 12:28 am

I thought the hp/mp calculations were well known
I could probably get them from halloween if I ask him.
Image
Thus spake the master programmer, "After three days without programming, life becomes meaningless"
User avatar
thadiusofx3
Knight
Knight
 
Posts: 887
Joined: Mon Dec 18, 2006 11:46 pm
Location: Jonesboro, AR

Postby Ratiotile » Fri Jul 13, 2007 11:09 am

It would help if you could get Halloween's HP/MP methods. I wanted to see the general trend of HP as level increases(done), and the effects of stat points on the HP(not done). We will probably need to make a new system that works like the old cumulative HP system.
User avatar
Ratiotile
Sheriff
Sheriff
 
Posts: 109
Joined: Tue Jul 10, 2007 7:13 am

Postby Ender » Fri Jul 13, 2007 2:30 pm

The original system had a large random factor to it. Is it safe to assume we won't be having any of that? Getting bad chest pulls is bad enough, but add a chance for bad hp/mp gains every level and it tends to disgruntle players.
Ender
Traveler
Traveler
 
Posts: 98
Joined: Fri Dec 22, 2006 12:48 pm

Postby Vitriol » Fri Jul 13, 2007 10:15 pm

I tried to come up with some damage formulas and the like and kept working myself into a hole. Every formula I came up with was either too level dependent (i.e. level 16 woops a level 15 way to easy) or not level dependent enough (level 5 can compete with level 10)
Id like to know if there are any tips or tricks to coming up with a system like that. I looked D&Ds formulas and I hate them. Its just retarded. Xenimus' algorithms are really a better way. It just needs to be like old xenimus.
Vitriol
Lord
Lord
 
Posts: 307
Joined: Thu Dec 21, 2006 9:48 pm

Postby Vitriol » Fri Jul 13, 2007 10:21 pm

Ender wrote:The original system had a large random factor to it. Is it safe to assume we won't be having any of that? Getting bad chest pulls is bad enough, but add a chance for bad hp/mp gains every level and it tends to disgruntle players.

I agree, even though retroactive stats is a good thing, HP/MP gains should be predictable.
Vitriol
Lord
Lord
 
Posts: 307
Joined: Thu Dec 21, 2006 9:48 pm


Return to Volucris



Who is online

Users browsing this forum: No registered users and 1 guest