ID:1393523
 
I've made this post to try and figure out what are the most common and uncommon bad habits new coders(and old) tend to developed when they are learning to code(one can never stop learning or else we won't advance) Could you list all the bad habits to stay away from here so i know wither i am starting to learn any and which tutorials i should stay away from because of the habits?

Thanks.
usr abuse:

mob
verb
attack()
usr.icon_state = "attack"
var/turf/t = get_step(usr,usr.dir)
var/mob/m = locate(/mob) in t
m.hp -= 100
m.deathcheck()


This is technically correct, but leads to another problem:

Overly generalized behavior

mob
var
hp = 100
verb
attack()
//etc
npc
proc
ailoop()
shopkeeper


This is how most BYOND games typically set up handling shopkeepers, enemies, and players, with the players being /mob, enemies being /mob/npc or /mob/enemy, and shopkeepers being /mob/npc/shopkeeper.

You wind up having to write in behavior that makes it so that you have to make shopkeepers unkillable.

Instead, it would be better to encapsulate behavior properly, like so:

mob
combatant
var
hp = 100
proc
takeDamage(var/damage,var/source)
src.hp -= damage
player
verb
attack()
var/turf/t = get_step(src,src.dir)
var/mob/combatant/c = locate(/mob/combatant) in t
if(c)
c.takeDamage(100,src)
enemy
npc


Notice we started using src, because usr defaults to /mob, and thus using the pathing operator "." will result in undefined variable errors.

Sometimes, people use the look-up path operator: ":", to circumvent this. It is incorrect to do so. Using src will avoid casting. However, should you have a verb defined under ANOTHER object, where src is not equal to usr, you should be casting usr:

var/mob/combatant/player/p = usr


Setting up your mob behaviors like this avoids a number of problems, such as having to define custom behavior just to disabled other behaviors, and cluttering your mob prototype with behavior that only applies to certain types.

You have a polymorphic language at your disposal. Use it.



Another common problem, handling user log-in and character creation:

mob
Login()
src.loc = locate("startpos") in world
src.invisibility = 101
//set up the title screen and handle logging in.
return 1


This is incorrect. What happens when you need to change mobs the player is in control of?

It's best to make a special type the default world mob, that way you can KNOW when the player is first logging in, and set up specialized Login() behavior for switching mobs with live clients using the Login()/Logout() procs:

world
mob = /mob/logging

mob
logging
Login()
if(fexists("saves\[src.ckey].sav"))
var/mob/player/p = new()
var/savefile/F = new("saves\[src.ckey].sav")
F >> p
p.key = src.key
del src
else
src.character_create()
return 1
proc
character_create()
//all character creation verbs and procs should be defined under mob/logging
player
Login()
world << "[src] has logged in!"
return 1


Encapsulation of behavior is important, and needs to be done right to keep your code clean and manageable.

Doing it right after doing it wrong can take ages, so it's best to just do it right the first time.


On a side note: Try to not design games that rely on verb panels and statpanels --You aren't going to be doing yourself any favors. Verbs should be triggered by interface elements, or, instead, you should be using macros/HUD elements. Heck, even using a browser Topic() link would be better than verb panels.
In response to Ter13
I don't understand a lot of that but i will try to follow those guide lines most of it is white noise atm since i don't understand...Do you know of any tutorials i should stay away from because they will teach me bad habits?

EDIT: I have another question that bothers me a lot, when making a project i never know how many different files i should use or if use more compact code/ect files would be better for example, how many files is too many? Like this, var, verb, general, ect, ect? What should and should not be together in one dm/other files.

Thanks again
Most of the tutorials don't teach you overly bad habits. It's mostly looking at the anime game codebases that lead to these.
In response to Ter13
I will stay away from those, could you answer the question above if you have time?
The number of files really only affects compilation time and .rsc seek time. Don't worry about it, so long as it makes sense to you.
In response to Ter13
Does having more/less or more in one file effect lag? in loading or executing protocols, ect?
No.

Every proc execution has a slight overhead. Avoid breaking up behaviors into a large number of procs if there is no reason to do so.

At the same time, the greater the number of instructions a proc has, generally, it will take longer than one with less instructions. This isn't a hard rule, simply because all instructions are not created equal. locate(), for instance, takes longer than a list access. But generally speaking, you just want to eliminate all excess instructions that you can, and find bottlenecks and eliminate them.


FYI: Lag only refers to network latency, not processing time, or rendering bottlenecks.
In response to Ter13
Ok, thanks, btw i really wanna play the game you are making for the Contest it looks fun.
BTW, what problems does abusing the usr lead to you never explained

EDIT: never mind i had to reread it i found where you explained why ..
Ah, abuse of usr leads into the next section of my post: incorrectly encapsulating behavior.

usr is typed /mob, so you can't use usr to access variables that are defined under /mob/player, etc.

Basically, verbs can only be triggered correctly by players, so usr should always refer to the last player that performed an input action. It's hard to create a situation in which usr equates to the wrong player, but it can theoretically happen.

Using usr instead of src (which is typed as the instance path where the currently running proc is defined), results in either having to cast usr into the correct type to receive the proper instance variables, or to define all variables and behavior under /mob.

This is why you typically see all behavior relating to players only defined under the base mob type in BYOND games, which results in having to override behavior that's player-specific in all subsequent mob types, such as monsters and NPCs.

It basically means that your combat and PVP behavior will be built into shopkeepers, and quest mobs, rather than having those act as noncombatants. It's counter-intuitive to build combat behavior or character creation behavior into a mob that will never use them.

It makes your code less readable, and makes your code much more brittle, allowing you to easily break things by simply misusing an object slightly in your code.
In response to Ter13
Ah, well what if i wanted shopkeepers and others to inherit this because they would be kill-able, like you go and murder and entire town(like skyrim ect)
Then you'd define shopkeepers under the combatant type.
In response to Ter13
Ah, well that does make more sense.
I have another question that comes to mind in your example, is that combatant an example for Mobs that are kill-able and for players?

Like how it has the hp var, is that just for the npc or would i need to add the other vars that the player/mobs might have along with hp ect?

EDIT: Also if it is for Mobs would i need to make more then one for each type or define the other types inside it with ifs or other things?
Sounds like you need to understand inheritance.

For example:
mob
var/hp = 100
test_mob
var/mana = 100


In this example, /mob/test_mob inherits the hp variable from its parent, /mob. However, a regular /mob will not have access to the mana variable, because parents don't inherit things from their children.

Understand now?
In response to Albro1
I understand it but what i was asking was if i would need to do what you did in the example for each mob type since the first one would inherit from the players value?
You can branch all kill-able mobs off of /mob/combatant, in that example. Even the player mob (by setting world.mob.
In response to Albro1
Would i have to use the world itself or use it inside combatant?

EDIT: i don't quiet understand what you mean my using world for it world.mob? setting a world mob type then using it?
world.mob sets the default mob players get much like world.turf sets the default turf type.
Page: 1 2