Simple MORPG project planning

Started by
23 comments, last by Sky Warden 11 years ago


So if you're already familiar with Python, stick with it. It's a fine choice. =)

Whoa. Thanks! That reliefs me. I've asked some seniors and they say the same. "You should pick a programming language based on your own skill set and the needs of the project." Also, that's a very useful link you gave me there. I will have it a read soon. I'm writing the database class at the moment.

Yes. I choose Python because it's easier to develop and therefore, will make it easier for the team if a new programmer comes to the team.

As for the client-server play, I later decide to separate the client-side team into two parts. One part handles the resources along with the spiters, while the another one handles the sent data with the network guy and server-side programmer (me).

About database, I'm concerning about the normalization. It's good for some reasons, but it slows down the reading process a bit. I think I need to denormalize some of them, but not sure about the best way to do it. I can decrease the writing performance if I do it wrong. Some ideas or links will be very appreciated.

Thank you everyone! :)

About the database, and this database class you're working on:

First, if you already have 42 tables, but haven't started coding yet, you're doing it wrong, in my opinion. You're also likely to run into surprises once you start using the database. Perhaps for the moment the best approach is to use your schema as a design guideline, but build the actual db from scratch, adding what you need as you go along. It's good to look ahead and try to anticipate, but don't try to look too far. :)

Second, are you using an ORM? If not, do it, especially if you're dealing with 40+ tables. If you don't use one, you're going to end up basically writing one yourself--and it's going to suck. That's not a criticism of your programming skill, it's just that these things already exist. Use them. Sqlalchemy is nice, and you can also use Django. Django includes a bunch of other stuff you won't need, but the ORM is quite good. This will make your life easier, especially when you find yourself writing generic insert, update, and delete code. There is a learning curve, but please, for the love of god, use an ORM.

Finally, about normalization. My favorite quote about this is, "Normalize until it hurts; denormalize until it works." This goes back to my previous point: try to build what you need, as you go. Change when necessary. Iterate.

Hope that helps.
Advertisement
Oh, slightly off topic. Learn to use a version control system, if you haven't already. This is necessary even for solo projects, in my opinion, and absolutely critical for a team.

If you already are, great! And sorry for the assumption. If not, git and svn are good choices. I prefer git for several reasons, but I will stop now before initiating a tool choice holy war.


Oh thank you. They're really important indeed. I will keep them in a list. The client-side programmers want to work with Unity 3D along with the spriters.

By the way, I'm not very sure about the way I handle things like buff. At the moment, I handle it like this :

  1. There are some tables in the databases which store information like "Thing A has effects X, Y, Z, etc."
  2. The program looks for the effects the triggered thing (just say magic or buff) has with the database. Maybe it has damage reduction by X percent.
  3. The result will be a list of effects. I have functions which represent every effects. The function name is the same name which is stored in the database. Like a function to count the damage reduction, etc.
  4. From that list of effects, I will do a loop to call the effect function one by one according to the effect name, and then count the total damage.

Is it good? Maybe you have a better way? smile.png

Thanks for the reply guys.

I'll Show you my Buff table I used in my Database. I actually grouped spells as buffs so they had a type. (note statement is for a SQLITE3 database)

CREATE TABLE Spells (
spell_id INTEGER PRIMARY KEY AUTOINCREMENT,
school_id INTEGER,
school TEXT,
class_id INTEGER,
name TEXT,
desc TEXT,
attack_value NUMBER,
range NUMBER,
cost NUMBER,
cast_time NUMBER,
recast_time NUMBER,
spelltype INTEGER,
duration INTEGER,
stuns INTEGER DEFAULT 0,
mezs INTEGER DEFAULT 0,
tick INTEGER DEFAULT 0,
forever INTEGER DEFAULT 0,
passive INTEGER DEFAULT 0
);
Notice this is kinda denormalized because I only have 36 spells in my game so I lumped things into one table, for easy querying at the start of the game. I ended up have 3 types of spells.
1. Target is Hostile
2. Target is Ally (friendly) for heal spells
3. No Target.
So obviously any Damaging spell needs to be type 1 because those spells require the user to be targeting an enemy. Can be damage, or a stun, etc.. If I want a spell that heals or a buff that you must click on people i set that type to 2 in the database. I also made a rule about type 2 spells. If targeting noone or an enemy, the spell will still cast but the allied target will be yourself. So you can self heal without having to click on your avatar/player etc... Type3 is where any group spells came in to play. No target is required, and it uses the range value in the database. Again, another rule in my game was all type3 spells casted work on yourself. So If I wanted a self buff I would make it range = -1.
THen I had various flags for all the buffs I wanted:
Tick- calls the buff to do something every tick amount. Lets say I have a power song that my Bard class can give to the group. But i want it to chant every 5 sec so they have to stay near him. This tick value is set to 5. I set the type to 3, and the range to 20. Now this is a group pulsing buff that will pulse every 5 sec, and i set the duration to 30, so if they leave the presence of the bard the buff will fall off in 30 sec. Notice the bard spams the buff everytime because I will set the Forever flag to true (see below).
Amount - If type 1 spell this is used as a base number for damage. If type2 I use this for healing amount. If type3, depends on buff but could be stat increasing, torns amount, an HP/MP regen rate, etc....
Stun/Mez - Will this spell stun or mez the enemy. Use Duration (in some formula of the game) to figure out how long.
Forever - This tells the buff to RECAST itself to the owner. I used this for my bladeturn ability. If bladeturn buff is on, then the next time you get hurt from an enemy, the attacks damage is reduced to 0. The buff comes off, but the Bard's bladeturn will reapply itself every (duration) secs. That way you have to BE near a bard to get the benifits of the buff. The buff will last until you logout, but it won't get reapplied unless you are near him.
Passive - This flag tells the game to ignore duration. The buff will stay on forever. I used this for buffs that increased stats.
cast_time - How long does it take to cast the spell. Can be zero for instant cast spells
recast_time - How long till you can recast this spell. Can be Zero (but you shouldn't have cast time and recast time = zero or someone can cast a lot of spells in 1 sec!)
Things like amount and duration are actually base values that get thrown into a formula so the spell scales with INT and Level etc..... Maybe this can help you out, but at least it shows one approach to spells. Also, having all the datapoints in a database made it easy for me to give the game to my friends to play, and I can make quick database changes while attempting to balance, without having them redownload the game, or recompile it, etc. So remember to try and avoid any hardcoded values in your source code.

KnolanCross, I think you are confusing Python the language with cPython, _one_ implementation of the Python language.

Why? I do know the difference between the multiple implementations.

Can anyone point me where I am wrong? I just would like to know why people are giving me negative posts, I am not saying anything wrong in my posts, If I am, I want to know it.

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

KnolanCross, I think you are confusing Python the language with cPython, _one_ implementation of the Python language.

So... it's fine to use Python for the server?

First, if you already have 42 tables, but haven't started coding yet, you're doing it wrong, in my opinion. You're also likely to run into surprises once you start using the database. Perhaps for the moment the best approach is to use your schema as a design guideline, but build the actual db from scratch, adding what you need as you go along. It's good to look ahead and try to anticipate, but don't try to look too far. smile.png

Actually I've designed it on my papers (a poorly-drawn schema with lines, squares, and pieces of script here and there). What I meant with writing the database class is putting those script pieces on that papers into text editor in files. I hope I can merge it right. Hmm... maybe I do it wrong indeed. XD

Second, are you using an ORM?

Yes, SQLAlchemy, but I'm still learning about it.

My favorite quote about this is, "Normalize until it hurts; denormalize until it works."

I like this. By the way, this sounds promising to me :

"Keep the logical design normalized, but allow the DBMS to store additional redundant information on disk to optimise query response."

But I don't know how to implement it with Python.

Learn to use a version control system, if you haven't already.

Oh I will! Please list the things I need to learn and throw it to me, sir. I really am eager to learn as much as possible. :)

I'll Show you my Buff table I used in my Database. I actually grouped spells as buffs so they had a type. (note statement is for a SQLITE3 database)

That's interesting. I will keep them in mind.

By the way, what do you think about the way I handle buff? I store the spell information in one table (name, description, mana_cost, etc) and store the effect in another table (contains the spell_id and the value for particular effects). The effect table stores the function name in string. The program will look for the effects the casted spell has (select bla from effect where spell_id=bla), then save it and the value for each effect. Then from that list of effects, I do a for loop and call the functions dynamically (about the function math) and insert the value as the argument.

Like spell with id = 1 has effect A with value a and effect C with value c. Then from that list with A and C in it, I do a for loop. For each loop I call the function using the string name, and use the value. In this case, the first loop will call A(a). Then in the next loop, C(c) will be called.

Am I doing it wrong? I love this kind of discussions. :)

@skywarden

Yes it is possible to have a server using python, I use it on mine!

But I use binds for physics/collision so the math is made with C++ and I profile my code and improve performance using cython (an optimizer).

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).



Yes it is possible to have a server using python, I use it on mine!

But I use binds for physics/collision so the math is made with C++ and I profile my code and improve performance using cython (an optimizer).

Thanks for clearing that up. By the way, the collision detection is done by server right? Or the client?

I execute the algorithm on both sides.

The client uses the information to be more responsive and results on better gameplay, still the server has the final decision (to avoid hacks).

Currently working on a scene editor for ORX (http://orx-project.org), using kivy (http://kivy.org).

@skywarden

That sounds like the buffs might work. You might want to have 3 tables.

-Spell table

-Effect Table

-SpellEffectJunction Table.

So you can customize your spells with different effects. I'm not sure if yoru effects are what the spell does (like damage, heal) or the graphic elements of the spell (what particle system to use). But I guess this would work for either way. If you have three tables, you can define your spells, define your effects, and then the junction table is a simple 2 column table with a spell_id and an effect_id (forgive me if this is what you had in mind). Then you can add as many effects to a spell by inserting them in this table. A query will return all effects related to the spell in the query.

Also, is this a client side database or on the server? Because the client will need to load all of this from the server before they start the game (i'm guessing). But you want the values to be controlled on the server so you can easily apply server side patches to balance the game.

You might want to have 3 tables.

Aye. That's how I do it. I have a table to store the effects, then magic table to store basic information about magics, and magic_effect to store the effects of magics and its value. That way, I can use the effect table for other tables like buff, items, etc and make a pivot table to relate them. For magic, I have these three :

-effects

-magics

-magic_effect

Magic elements, etc are stored in other tables. Like you said, if I want to add a new kind of effect I can easily insert it in the effects table and relate them in the magic_effect. I do it this way because I think not all magic has stun effect, and filling it will null doesn't feel just right. smile.png

The database is on the server. I think it's more secure. I mean, if it's a client-side database, the client can hack it right? To make sure that everything is secured, I make the client to act more like an input and display device, and the server do the game. I don't need to patch the client engine frequently that way, right?

What I put in the client are just the physic (I don't care about physic hack), sprites and models (who wants to hack them anyway?), and things to handle user input. My plan is to make the client engine detect input like 'move forward' then send the vector to the server. Then the server read that vector and see if it will make collision or not. The server later announce the result to the world.

I'm still rather confused with this actually. From what KnolanCross said, I assume that this kind of math is slower to do in Python, and the colission detection will be faster if it's done in the client. Do I get it wrong? Maybe you guys have an alternative? I really want to know the best way to do everything. biggrin.png

This topic is closed to new replies.

Advertisement