ID:46718
 
Modular: composed of standardized units or sections for easy construction or flexible arrangement - dictionary.com*


Many people seem to think the below code would be good:

mob/verb/Punch()
var/mob/M = locate(/mob) in get_step(src,dir) //find a mob in front of the player
flick("punch",src) //flick the punch icon state
if(M) //if it found said mob
view(src) << "[src.name] punches [M.name]"
M.HP -= 10
M.deathcheck(src)


However, if you have more than one attack that does almost the same thing, it wouldn't be so good. For example, what if you had a Kick() verb, too? And the only difference with the kick verb would be that it would deal more damage, say something else, and flick a different icon state. Would you copy and paste your punch code, then change the details? Probably! However, there is a much easier way to go about this, and it is with a modular proc:

mob/proc/Attack(name,damage,flickicon)
var/mob/M = locate(/mob) in get_step(src,dir) //find a mob in front of the player
flick(flickicon,src) //flick the punch icon state
if(M) //if it found said mob
view(src) << "[src.name] [name] [M.name]"
M.HP -= damage
M.deathcheck(src)

mob/verb
Punch()
Attack("punches",10,"punch")
Kick()
Attack("kicks",15,"kick")


Did you see what I did there? I defined a new proc, called Attack(), and gave it a few args. From there, I called the Attack proc from the verbs with these args, and Voila, you just saved a few lines of code. So right now you might be thinking, "So what's the big deal? I'm barely saving 3 or 4 lines!". Well, the big deal is that you can easily change the attack proc instead of changing the two verbs. Can you imagine having 200+ attacks that all do roughly the same thing, and then you figure out there's a bug in a bit of repetitive code? Well, then you have to spend 2+ hours fixing it. However, if use a proc to handle everything, you can change one little chunk of code and be over with it quickly! A huge time saver!

Now, what if I wanted to implement a status system, so that if a user is doing something, let's say taunting in this case, they can't attack. Well, you just tack on if(status != "taunting") on to every attack, right? Wrong. You simply use return (look it up in the DM reference if you don't know what it does) and a little if() statement:

var/status

mob/proc/Attack(name,damage,flickicon)
if(Status_Check()) //if they can't attack due to a status issue
return //cancel the attack
var/mob/M = locate(/mob) in get_step(src,dir) //find a mob in front of the player
flick(flickicon,src) //flick the punch icon state
if(M) //if it found said mob
view(src) << "[src.name] [name] [M.name]"
M.HP -= damage
M.deathcheck(src)

mob/proc/Status_Check()
if(status == "taunting")
src << "You can't attack while taunting!"
return 1//return one, which will mean don't attack
return //return null, which will mean attack

mob/verb
Punch()
Attack("punches",10,"punch")
Kick()
Attack("kicks",15,"kick")


As your code expands, designing it like this is a good thing to do. That way, if you ever decide, "Hey I need to change this! I just added a new status condition!" you only have a minute or so of work, versus 2 hours. In my one game, I have a few basic procs, such as melee attack, projectile attack etc. (there are a few more), some stat/status procs, a death check proc, and a damage proc. I strung these all together, and now my semi-complicated battle system is simple to add attacks to and change. Plus, most of the attacks take but 2 lines of code. Overall, it's best to program this way. Its efficient, saves time, and, most importantly, prevents you from hitting the resource limit as many games have before.

Please comment if I made any mistakes, typos, etc.

*Yes, I know there was a definition pertaining specifically to computers, I just felt this definition was easier to understand.
Not bad, I just wish I new more about this back when I started working with DM. It would have saved me from staying up all night programming the same thing”. After seeing this it reminded me of another “guide/tutorial” that explained modular programming, if you are interested the guide is here:

http://www.byond.com/members/DreamMakers/files/ iainperegrine.2007-1116/parent_type.html#part2_c
Calus CoRPS wrote:
Not bad, I just wish I new more about this back when I started working with DM. It would have saved me from staying up all night programming the same thing”. After seeing this it reminded me of another “guide/tutorial” that explained modular programming, if you are interested the guide is here:

http://www.byond.com/members/DreamMakers/files/ iainperegrine.2007-1116/parent_type.html#part2_c

Oh, I didn't know about that. It's not a post like the other articles, so I didn't see it.
I have the attack system in PMR coded like that. It's incredibly confusing when I need to add new attacks, though, which I why I usually have a commented example lying around at the end of my codefile.
Mechana2412 wrote:
I have the attack system in PMR coded like that. It's incredibly confusing when I need to add new attacks, though, which I why I usually have a commented example lying around at the end of my codefile.

As do I =]

I think I have roughly 10-20 args for each proc, minus a select few like healing attacks.
I have 6 to 10 args per-proc. I can't recall them all at this moment, but I think the Attack() proc goes something like

attack(user,target,attack power,attack name,energy usage,cooldown,status effect,effect duration,other)

The only current use of Other being for the game's sole animated attack, Maxima Solaris.
I have 7 different types of attack, but I'll put melee and damage here:

M_attack(damage,type,afflict,a_per,spec=0,name,OV,delay=10, rec,stat,s_per,s_int=1,s_pol=1,s_usr,crit_p=10)
damage(mob/Pokemon/ ct,a_per,spec=0,name,OV,rec,stat,s_per,s_int=3,s_pol=1,list/ s_usr[0],crit_p=10)

I tried to cover all major aspects of the combat system >_>
Really, by that point, you should be using datums and overriding their execution proc for the more complicated attacks only, IMHO.
DarkCampainger wrote:
Really, by that point, you should be using datums and overriding their execution proc for the more complicated attacks only, IMHO.

What would be the benefits of this? I would rather not define hundreds of many-lined datums (most of my attacks are that complicated).
Well, your attacks would be more than verbs, for starters. You could add attack-specific experience and the like.

Really, the idea would be similar to what you are doing now, but even more customizable (you don't have to tack on more args for the global Attack() process, you can just alter one datum)

If you can set up all of your Attacks using that one process, you can just as easily with datums. But this time, you could make a basic datum for the general attacks, and then make sub-types of that datum for the more advanced ones.

Here's an article that somewhat touches on the subject (took a while to remember where I had seen it)
All Rectangles Are Squares - By IainPeregrine
It's not global :P. Either way, I'll take a look into that article. However, it might be too late >_>. I defined a good number of attacks already (and even though it didn't take long to add each attack, it's just plain boring!).
Honestly, I would just stay away from verbs in general unless it was an action that wasn't timing-sensitive.