ID:36143
 
Keywords: beginner, tutorial, zbt

Z B T
For action/RPG fans

Welcome to Zilal's Beginner Tutorial for the BYOND system. I wrote this because even newbies who read the guide, and look at Your First World, are often confused and maybe a little overwhelmed and still don't know where to start. And when you're confused about a new thing, you frequently don't know even enough to think up the right questions to ask to get yourself help.

I'm going to walk you through the creation of a simple world, and I'm not going to assume you know anything about programming or BYOND already. And I'm going to show you one way to do what beginning programmers often want to know how to do: kill things and take their stuff.

Below, the titles of each section are meant to be approachable; what's in parentheses after the title is a more clinical indication of what you'll learn in that section.

I. Getting Set Up (Opening the program)

Go to your program menu and open the Dream Maker program. Under the File menu, choose "New Environment...", click on the right side of the input box, and type "Testworld". Click OK. When the next box comes up, you will see it wants to create a new Code File with the same name. Click OK.

Every world has to have an environment. For one world you may have many code files, or many sound files, and so on, but they're all part of the same environment. In our case, the Testworld environment. A code file (or .dm file) is where you do the actual programming. In the panel on the left, you can see little icons representing the environment and the Testworld code file.

A folder for this environment was created in your BYOND\bin\ folder, since we didn't specify otherwise. You can go look if you want. By default, BYOND is installed in C:\Program Files\BYOND (if you don't know where BYOND was installed on your computer, it's probably there). In the bin folder, you'll see a Testworld folder. In that, you'll see Testworld.dme (the environment) and Testworld.dm (the code file).

II. First Things First (Comments)

At the top of Testworld.dm, our code file, put this line:

//This is a test world created by <your name> on <today's date>.

...where you replace what's in the <>'s with the appropriate information.

That's a comment. It begins with the double-slash, which makes it turn grey. You can say anything you want in a comment and it won't affect your code. Comments are very important; a good programmer adds comments to her code explaining how it works. A comment should be made as if you're explaining the code to another programmer, even if you never intend anyone else to see it.

That may sound silly, but forgetting how your own code works is a lot easier than it sounds. It's far better to have good commenting and not need it than to need it and not have it.

III. Code that Does Stuff (Verbs)

Hit return a couple times to move down the page, and put in this code (indent lines by pressing the tab key):

mob
verb
say(msg as text)
world << "[usr]: [msg]"

We made our first verb. Verbs are the commands the player has access to in a game. We started off with "mob", which means that for the verb to work, a mob must exist in the world. Which could be you. (If we had started off with "turf", then the verb would require a turf to exist. And a mob too, in fact, since without at least one mob in the world there'd be no one to use the verb.) Mob is short for mobile and is usually used to represent players and monsters.

Under mob we put "verb". We used a tab before verb, which means it belongs to mob; mob is the parent. If we'd put "verb" all the way on the left, it wouldn't belong to anything.

Next is "say" and some stuff. By tabbing and putting it under verb, we're indicating that say is a verb. What goes on with that line is slightly more complex. Before we get to that we have to comment our code like good little programmers.

mob
verb
say(msg as text) //what the usr says is passed into "msg" as text
world << "[usr]: [msg]" //the world sees chatroom-like output

Any of the comments in this tutorial may wrap around the screen in your text editor, but there's no carriage returns in each individual one. Now I'll explain what the comments above mean.

(When you're still learning the language, comments also help to better remember what you just learned... like summarizing in your own words the chapter you're reading for History class. You'll be grateful later when I call you up to test you.)

IIIa. Arguments Are Healthy (Verb arguments)

        say(msg as text)            //what the usr says is passed into "msg" as text

As programmers put it, verbs take arguments. But that's not very helpful if you don't know what an argument is or how it can be taken. We can all see the word doesn't make much sense. What exactly are we arguing about? (I prefer to argue about the Yankees and the Red Sox, but if you were interested in that you'd read my tutorial on how to acknowledge that the Red Sox are superior.)

Think of an argument as input. With a verb, this input comes from the player. You decide what name to call the incoming information. In this case, it's "msg", short for "message." We could call it anything we want, but it's good to pick a name that's both descriptive and easy to type.

So, we don't know what input is going to come in here, but whatever it is, we know what we're going to call it. And we know what type of input it's going to be. Text. Not a number, not a mob, but text. Which is words, mostly. Text might contain digits in it: "I am 23 years old"--but that doesn't make it a number. Msg as text.

A player who types "say" in the game will then be able to type in any text he wants. The text gets passed in to the say verb. Picture a player using your verb to say something like "Hello!", and imagine those words dropping right into "msg".

IIIb. Output! (The << operator)

            world << "[usr]: [msg]"     //the world sees chatroom-like output

We put this line under the verb, indented, since it's the action the verb does. Those two lesser-than signs are called an operator. "The << operator," in fact. Don't ask me how to pronounce that. Operators are symbols, usually placed between things, that cause something specific to happen. In this case, what's happening is that the right side is being output to the left side. Which is the whole world, in our case. Picture the stuff on the right being funneled >> into the world. Uh, in the opposite direction as we did above. Here it is in the same direction.

.dlrow eht otni << delennuf gnieb thgir eht no ffuts eht erutciP

Makes much more sense, doesn't it?

IIIc. What the Heck Is That? (Embedded expressions)

What exactly "[usr]: [msg]" means might have you stymied at this point. It has quotes around it, which means the whole thing is a text string. What the player typed in, our msg, is a text string... I called it "text" before since, hey, that's what our verb said. Msg as text. Not msg as text string. The verb does not lie. But they do mean the same thing.

When something in a text string has [] brackets around it, that's what they call an imbedded (or embedded) expression. I don't know where programmers come up with this stuff. I believe they sit around drunk throwing darts at a page of the Oxford English Dictionary. However, the imbedded part of "imbedded expression" makes some sense. An imbedded expression is like a nugget buried in our text string.

When your code gets executed... which means run, rather than guillotined, not that that wouldn't be fun... that text string doesn't get funneled into the world exactly as you see it above. Rather, anything that's an imbedded expression gets replaced. You'll see instead whatever the word in brackets refers to. The [usr] is replaced by the usr's name. Usr, also a pronunciation challenge, is whichever player just used the verb. When a text string containing [usr] gets displayed in your world, the [usr] part gets replaced by the verb-user's name.

If I know you, you've already figured out what [msg] gets replaced by. I don't know you; however, this should not stop you from sending me money. Think fast! If a player named Ichabod uses the say verb to say "I'm going to whack everybody with a 30-pound petrified hunk of mutton!", what will the world see?

Yes, that's right. Stars. No, no, I jest. The world will see...

Ichabod: I'm going to whack everybody with a 30-pound petrified hunk of mutton!

Voila. Chatroom. (You know it's a chatroom because the person speaking already shows a baseless hostility toward everybody else.)

By the way... never let an expression im bed with you. They steal the covers.

IIId. Action! (Compiling and running)

Go under the Build menu and choose "Compile." In the bottom panel you should see:

loading Testworld.dme
saving Testworld.dmb

Testworld.dmb - 0 errors, 0 warnings

If you don't, check your code to make sure it looks like what's above.

When your code is compiled, it's translated into a format the computer (and/or whichever program is running your program) can read. If there are no errors during this process, your .dm code file will also be saved. Now go under the Build menu again and choose "Run." The Dream Seeker (a client, or interface to other programs) will open.

If you're prompted by the Dream Seeker to choose a key, go ahead and do that.

Once your world opens you should see the verb "say" in a panel named "Commands." Click on that or type "say" on the command line (the pink type-in window), then your message. If you're using the command line be sure to put a space in between. And press enter. Now get back here!

IV. This World is Pretty Friggin' Boring (Icons)

Picky, picky! We'll make it a little more interesting. Under the File menu in the Dream Maker, choose "New..." and when the box pops up, choose "Icon File (.dmi)". Name it "grass".

Now you're in the icon editor; you can see a new screen with two buttons, a palette and a camera. Click the palette. What you see next is probably self-explanatory; make some pretty grass if you want, or just flood the whole thing with green.

IVa. Fancy Fancy (Icon states)

Next, make a new Icon File (.dmi) and name it "person". Click the palette and draw a stick figure in pink. Yeah, you heard me. If you mess up, the color in the very upper-left of the palette can be effectively used as an eraser. It's called the mask, and parts in that color will be transparent in your game.

Once you're done hit the "Back" button in the lower right. You'll see your little pink figure in the space that was blank before. Click the palette again. This time, draw a stick figure in blue, and go back again. Click the palette a third time and make a black stick figure, then go back once more.

We just created an icon with multiple states. It's still one .dmi file, one icon, but it can look three different ways. Instead of thinking of it as a painting, think of it as a picture book, and you can flip to whichever picture you want and then show it to people. The whole "book" together is named "person.dmi". This one was NOT on the New York Times bestseller list.

Click a millimeter or two beneath Pinky. There may be a split second delay and then a little box should appear. In the box, type "female", all lowercase, spelled correctly of course. Now do the same with the blue guy, but type in "male". And do the same with the black figure, but type in "neuter". We've named our icon states. Now when we want to display a particular one we can call it by name.

That's "neuter" the adjective/noun, not "neuter" the verb. Don't get so upset.

This may be the only beginner's tutorial to talk about icon states. Icon states are considered a difficult concept. Many people who've been coding for months still don't understand them. If I've done my job, you're sitting there wondering what's not to understand.

If I haven't, look for my "Conquer Icon States in Just 60 Days" tutorial in the near future.

IVb. Implementing Graphics (Prototypes)

We made some (sort of) nice graphics, but they're not going to jump into the game all by themselves. Double-click on Testworld.dm, our code file. Under "mob", tabbed so that it sits right above "verb", stick this in:

    icon = 'person.dmi'     //make it so all mobs will be created with the person icon

After all the mob code put:

turf
grass //defines a "grass" prototype, which is a kind of turf...
icon = 'grass.dmi' //and has an icon named 'grass.dmi'. In single quotes!

A prototype is like a blueprint. A blueprint of a house isn't the house itself... and I don't recommend using it to keep the cold out... but you do use it to build a house. Our code here doesn't create grass in the game. It's just the blueprint. We can make as much grass from that one blueprint as we want. Finally:

world                   //we set one of our world's characteristics:
turf = /turf/grass //its default turf is the grass turf.

We'll take a look at what that did in a moment. Right now, go under the Build menu and compile again, which besides translating the new code will save our files. Always remember to save regularly, and make backups (with real projects, anyway). If you ever forget, there's a 99.9% chance that'll be the day lightning sizzles out of a clear sky to strike your computer.

I had to rewrite half this tutorial because I forgot to save, and my computer sensed this and obediently crashed. Do as I say, not as I do.

IVc. Cartography (Making a map)

Time to make a map for our world. Under the File menu, choose "New..." again and make a new "Map File (.dmm)" named "Testworld". Same name as our environment. Remember the environment?

Yeah?

So why aren't you recycling, hot shot?

You'll be asked to set the map size; just click OK. When the map editor comes up, you'll see it's all green. I hope. That's because we set the world's default turf to grass, and we set grass's icon, and the map automatically filled in everything with it. That saves us the work of putting in all that grass ourselves. How devious of us.

You now have a world of 100 tiles. Compile again, and run. You'll see the grass... but you won't see any stick figures.

You DID log in. And you would be a pretty little stick figure in the grass... except that we gave the stick figure different icon states, and the program doesn't know which one to display, so it gives up and you don't get to be a stick figure. Sorry.

V. More Creepy Abbreviations (Procs)

Proc is short for procedure. These are little bits of code that make all the action happen in the game; you can recognize a proc because parentheses come after its name. Verbs are a type of proc, so you made one earlier without even knowing it. The DM language comes with some built-in procs to make coding easier. Since DM is also about power, we're allowed to override the built-in ones and make them do exactly what we want.

Va. Login() and Logout() (Built-in procs)

When your program is ordered to go do a procedure, the relevant proc is "called," as they say. Login() gets called automatically when a player logs in, and Logout() when she logs out. When you want to override these two, you put the code in the prototype for mobs. Here's our code for mobs now:

mob
icon = 'person.dmi' //makes it so all mobs will be created with the person icon
Login()
icon_state = gender //when a player logs in, make their icon's state
..() //the gender of their key. Then call the parent!

verb
say(msg as text) //What the usr says is passed into "msg" as text
world << "[usr]: [msg]" //The world sees chatroom-like output

You've been a very fidgety student and I have considered calling your parent, but that's not what the comment is about. The ..() command says to go call the actual built-in Login() proc. This is very, very important. The built-in Login() proc is what actually puts you onto the map. It's called the parent proc because it's the version ours was derived from. (Didn't you ever ask, "Mom, how was I derived?")

The Login() WE coded is a child, and it doesn't know everything the parent does. So we tell it to go ask its parent what to do with that ..() line.

Now, compile and run! You will be a stick figure who can say things AND move around with the arrow keys. You now have a graphical chatroom. Ain't life grand? You should Save All or Compile again now, by the way.

VI. But I Don't Want a Chatroom!! (Declaring variables)

The characteristics of mobs and turfs we've been fooling around with (such as "icon" and "gender") are called built-in variables. A variable is a place where a tidbit of data is stored. It's called a variable because we can change it at will, so the info it holds can vary. The DM Reference lists which variables are built-in and already there for you to use.

But today we want to make a variable to hold data about a player's hit points, or HP, and the Reference shows us that there's no built-in variable for that. So we have to make our own. Put the lines:

    var
HP = 30 //declares a new variable called HP, with a value of 30

...under mob, beneath the "icon" line. We break alphabetical order here, sticking "var" near the top, because it's helpful to group variables together. HP is close to the built-in variables we already typed in.

We've declared a variable and assigned a value to it. When we declare a variable, we let the program know we just made up a new one that isn't built-in. We do this by putting it under "var". When we assign a value, we say what data we want our variable to hold. In this case that's the number 30.

VIa. Killing Things... (More built-in procs)

If we're going to go around attacking things, we really ought to give ourselves an attack verb. I mean, honestly. Add this under "verb" but before "say":

        attack(mob/M as mob in oview(1)) //attack a mob within 1 tile of you
usr << "You attack [M]!" //send this message to the usr
oview() << "[usr] attacks [M]!" //send this message to everybody else
var/damage = rand(1,10) //assign a random # to a new variable
world << "[damage] damage!" //tell the damage to the world
M.HP -= damage //take away the damage from M

That's quite a chunk, and I was much briefer with the comments here. Take a look at things and see if you can figure out some of it yourself. Don't fret though, I'll explain everything in greater detail.

        attack(mob/M as mob in oview(1)) //attack a mob within 1 tile of you

This is pretty similar to the say verb. The player who's doing the attacking gets to pick a mob near him, which will be passed into M. Again, just picture the mob he's attacking dropping right into M.

Next, oview(1) is the range he can attack things in. The "view" part of it is pretty self-explanatory; the "o" means outside or other, or possibly Okefenonkee, and it keeps the usr from being a possible target. The usr will only be able to use the attack verb on other mobs within 1 tile of him.

            usr << "You attack [M]!"    //send this message to the usr

In the line above we funnel an attack message to just the usr.

            oview() << "[usr] attacks [M]!" //send this message to everybody else

We didn't put any number in the parentheses of this oview(), so it will apply to everyone the usr can see... except, of course, the usr himself.

            var/damage = rand(1,10)    //assign a random # to a new variable

We declare a new variable above, called damage. Damage isn't indented under "var" this time like HP was, but there is a slash between them. A slash is the same as going down a line and indenting. It shows that the thing on the right is a type of thing-on-the-left. Damage is a type of variable. Since that sounds silly we say damage IS a variable.

We assign a value to our variable here, but not like we did with HP. Instead of assigning a number, we call a built-in proc, rand(). The arguments we pass into rand() determine the range of the random number we're going to get. In this case, an integer between 1 and 10 inclusive.

Every time this line is reached in your program, rand() will be called, and will call back with the number it picked. That's called returning. It returns the number we requested and it returns execution of the program to its caller. Good word for it, eh? The number it returns is what we assign to damage.

            world << "[damage] damage!" //display the damage to the world

Here we imbed damage just like we imbedded usr, msg and M.

            M.HP -= damage      //take away the damage from M

This is where we actually do the damage. M.HP means "the HP of M." The -= operator (that's a minus and an equals sign) means that the thing on the left of the operator now equals itself minus the thing on the right. So, M's HP now equals what it was before, minus the damage.

VIb. Five Notes (Clarification, advice, info, warning)

1. I've put comments on almost every line in our Testworld program, but that's neither expected nor desirable in normal practice. Just put in enough commenting that another coder reading your stuff would be able to figure out basically what it does. Or exactly what it does, perhaps, with very complex code.

2. Note how we give our variables names that relate to their purpose. I strongly recommend this. Make a variable's name as descriptive as you can without making it a pain to type repeatedly.

3. When we declare a variable from within a proc, it exists only in that proc. Once the proc returns the variable goes poof. If you want another proc to use that variable you must pass it in. You'll learn more about that as you progress in your study of BYOND.

4. If you recall, we have a line saying "var/HP = 30" and a line saying "var/damage = rand(1,10)". If you were to go back and make HP = rand(1,10), instead of 30, you'd get an error.

Testworld.dm:6:error:= :expected a constant expression

That's because if something is unknown when you compile... such as what the random number will turn out to be... you have to put it inside a proc.

5. You might have noticed a difference between Login(), a built-in proc, and rand(), also a built-in proc. One is capitalized and one isn't. That's to indicate Login() is a mob proc, while rand is just a regular old proc. It's all on its own.

VIc. Procadile Dundee (Proc declaration; if statements; src)

So now we can attack mobs. But if we want to actually kill them, we have to check and see if their HP drops to 0 or below. The best time to do this is after the mob takes damage. Add another line at the end of the attack verb:

            M.DeathCheck()      //check for death with a proc

You could probably tell that DeathCheck() was a proc. The M. in front of it tells us to call not just any DeathCheck(), but the DeathCheck() belonging to whoever M is. So we better write a DeathCheck() proc! Under mob, between Login() and var, put this:

    proc
DeathCheck() //checks to see if an attack is deadly
if (HP <= 0) //if the defender's HP is low enough...
world << "[src] dies!" //do the death messaging

Since DeathCheck() isn't a built-in proc like Login() is, we have to declare it by typing "proc" first, just like we had to put in "var" above HP.

On the next line we have an if statement. This isn't quite like a proc; you can separate the "if" from the parentheses, and what's more it shows up blue in your code editor. In this case we're checking to see if M's HP is less than or equal to 0. If it is, the program will go do whatever code is underneath the if statement. In this case it's an instruction to send a message to the world.

The [src] part is new; src stands for "source," and it's whichever thing the proc belongs to. In our case, DeathCheck() will always belong to whoever M was in the attack verb. But DeathCheck() doesn't know we were calling him M, so we use src, which always refers to the owner of the proc.

By now, all our code together should look like:

//This is a test world created by Zilal on 2/20/01.

mob
icon = 'person.dmi' //make it so all mobs will be created with the person icon
var
HP = 30 //define a new variable called HP, with a value of 30

Login()
icon_state = gender //when a player logs in, get them the right icon state for
..() //the gender of their key. Then call the parent!

proc
DeathCheck() //check to see if an attack is deadly
if (HP <= 0) //if the defender's HP is low enough...
world << "[src] dies!" //give the death messaging

verb
attack(mob/M as mob in oview(1)) //attack a mob within 1 tile of you
usr << "You attack [M]!" //send this message to the usr
oview() << "[usr] attacks [M]!" //send this message to everybody else
var/damage = rand(1,10) //assign a random # to a new variable
world << "[damage] damage!" //tell the damage to the world
M.HP -= damage //take away the damage from M
M.DeathCheck() //check for death with a proc

say(msg as text) //what the usr says is passed into "msg" as text
world << "[usr]: [msg]" //the world sees chatroom-like output

turf
grass //define a "grass" prototype, which is a kind of turf...
icon = 'grass.dmi' //that has an icon named 'grass.dmi'. In single quotes!

world //set one of our world's characteristics:
turf = /turf/grass //its default turf is the grass turf.

At this point, Save All or Compile again.

VId. I'm a Programmer! (Anticipating problems)

Not so fast, Jack. A programmer... a good one, anyway... has to think ahead. This means anticipating what your players are going to do. Players are nasty crafty things, and if there's a problem with your game they will find it eventually. Can you spot the problem in the code we just wrote?

Yes? No? Remember that players don't see the game the way you do. You know how things are supposed to work; they don't. You are on the straight and narrow path of "supposed to," but they don't see the path that's clear to you. They wander around and run into loopholes and bugs. Or they deliberately set out to find them. You didn't realize that stuff was out there. You were on the path.

I think we should see our bug in action. First we need something for you to attack. Make a new icon file and name it "bug" (this is symbolic, of course). Click on the palette and draw some type of bug as best you can. You are not being graded on your drawing skill. Now, under mob and between the icon and Login() lines, put this:

    bug             //new prototype
icon = 'bug.dmi' //override the parent's icon, which was 'person.dmi'

We break our alphabetical order again here. This way we have the prototypes, mob and mob/bug, close to each other. Now compile.

To place our bug on the map, we must open up the Testworld.dmp map file. In the left panel you'll see what they call a "tree", which is a branching arrangement. Click on the little arrow beside "mob" and the tree will open up to display your bug. Click on the bug and then put one or two or ten anywhere you want on your map.

Compile again and run. Wander around experimenting with the attack verb. Kill a bug... then keep attacking it. Pretty messed up, huh? Games have been produced and even sold on store shelves with silly bugs like this one. We're better than that.

Seeing your world as someone without your knowledge would see it is a game design strategy, something also rarely seen in beginner tutorials. But game design is very important to me. And it should be very important to you. What if killing a mob earned a player 100 gold pieces? You'd have people with a bazillion gold faster than you could say "Z is to BYOND newbies what a restroom is to a tourist in a Mountain Dew factory."

VIe. Buntime Rugs (Runtime bugs)

What we have is a runtime bug. Our code all checks out, looks great... but it doesn't do what we want it to. This can be very frustrating, and you'll no doubt bang your head on the keyboard countless times over this during your programming career. This is why I have POIUYTREWQ imprinted across my forehead. In case you've ever wondered.

When faced with a problem, we (1) think of all the solutions and (2) choose the most efficient. That "think of all the solutions" part is probably a little daunting for the beginner to DM. So I want you to forget about code and just think real-world logic. This is probably a question you ask all the time in everyday life: How do I keep people from killing things that are already dead?

The way I see it, our solutions fall into two basic categories: blocking the killer from killing the corpse, and simply removing the corpse so we don't have to block. I'm going to show you how to do both.

VIf. Keeping the Killer from Striking Again (The else statement)

Here's our way to block the killer; old comments have been removed for the time being.

        attack(mob/M as mob in oview(1))
if (M.HP <= 0) //if M's HP are at or below 0...
usr << "[M] is already dead!"
else //otherwise...
usr << "You attack [M]!"
oview() << "[usr] attacks [M]!"
var/damage = rand(1,10)
world << "[damage] damage!"
M.HP -= damage
M.DeathCheck()

If and else work together. You can have an if without an else, but you can't have an else without an if. They do pretty much what it sounds like they do. For our purposes, "else" is a more typable synonym for "otherwise."

VIg. RAID?!?!?! (The del() proc)

Here's our way to simply get rid of the corpse; old comments have again been removed.

        DeathCheck()
if (HP <= 0)
world << "[src] dies!"
del(src) //delete whatever just died

This also does pretty much what it sounds like. Whatever's in the parentheses of the del() proc... whatever's passed in... will be deleted from the game.

You get to decide which of these solutions is better for you. Imagine this as a real game you're making, and think ahead. Is there a reason to keep corpses around? Which method does your job the best in the fewest lines? What would happen if a player killed another player, rather than a monster? Which solution is easiest to make changes to in the future?

I myself am going to go with del(), because of what's coming up next...

VII. ...And Taking Their Stuff (Review)

Go on and add this to our program, under the mob code and before the turf code:

obj
gold //define a "gold" prototype, which is a kind of obj
icon = 'gold.dmi' //set the default icon
var
amount //declare a new variable called "amount"

It's all in the comments. That "obj" is like mob and turf; it's a type of thing you can make prototypes of. And it's best used for what we think of as things in the real world. Which is to say, things that are not places or people.

Now compile.

VIIa. AHA! (Compile-time errors)

If you did only what I told you, chances are you now have something like this in your bottom panel:

loading Testworld.dme
Testworld.dm:34:error:'gold.dmi':cannot find file

Testworld.dmb - 1 error, 0 warnings

This is a compile-time error. These are usually the easiest to fix because our friend the compiler tells us where it thinks the error is. In this case, obj/gold/icon refers to a file that doesn't exist. Because we haven't made it yet. Go make a new .dmi for gold, and name it "gold". Creative, aren't we?

NOW compile.

VIIb. Show Me the Money! (The Del() and new() procs, the loc variable)

When the del() proc is called, it calls the Del() proc... convenient, yes?... of the area or turf or obj or mob being deleted. Recall how I said capitalized built-in procs belonged to something, while non-capitalized ones were on their own? Both of these are built-in procs and what I said applies. We're going to override the dead mob's Del() proc just like we overrode mob/Login(). Above Login()...

    Del()
var/obj/gold/G = new(loc) //create a new obj from the gold blueprint
G.amount = rand(1,100) //set its amount variable randomly
..() //call the parent

I'll go into greater detail now. G is a variable we create meant to hold a reference to an obj. That's why it's var/obj/gold/G instead of var/G. What we assign to it is a reference to an obj created on the spot; this obj is going to be of type var/obj/gold. The built-in new() proc is what creates the new obj. What's in its parentheses is the location we want the gold to turn up.

In this case that's src.loc. That's the location of the src, or the source of the Del() proc, which is the mob that just got killed. Loc is a built-in variable that contains a reference to the turf something's on. I didn't put src. in front of loc above. You can leave that out and the program will assume you're talking about src. Saves a tiny bit of typing.

Next we access a variable of our new obj. We do this by fiddling with G. We're telling the program to find the obj that G refers to and make its amount variable a number between 1 and 100 inclusive.

After that we call the parent Del() proc, which will do the actual deleting of src. Save All or Compile.

VIIc. Are We Having Fun Yet? (I hope so!)

So. When we kill a bug, a random amount of gold will appear on that spot. That's not very helpful to us unless we can get it. Here's our revised code for the gold obj, past comments excluded:

obj
gold
icon = 'gold.dmi'
var
amount
verb
get() //obj/gold/verb/get()
set src in view(1) //src must be close
usr << "You pick up [amount] gold."
usr.wealth += amount //add to usr.wealth
del(src) //delete the gold

You might have noticed that we accessed a mob variable--wealth--that's not in our code. It's not built-in, either, so we have to make it ourselves. So put "wealth" right under "HP" in the mob section.

This time we made an obj/gold/verb instead of a mob/verb. That means an obj/gold must be present before you can use the verb. The next line makes it so that obj must be within one tile of the usr. Next is our messaging, complete with imbedded expression. Next line means that usr.wealth now equals itself plus src.amount, (the amount of gold). And after that we delete the source of the verb (the gold obj).

Compile and test. And we're done.

VIII. Exercises

Here are a few things to try on your own. Can you...

1. Send a message to the world that a player has logged in?

2. Make a new "tree" obj, with icon, and place some on the map?

3. Alter the DeathCheck() messaging to say who the bug was killed by?

4. Write a verb allowing the usr to check her wealth?

5. Make "damaged" icon states for the bug, and show them as the bug is injured?

IX. Final Words

Start small. Get comfortable with the language before you embark on that 10,000 room RPG you've always dreamed about making. Download and fiddle with the "Your First World" demo from the Tutorials section of the website.

The DM Reference I've mentioned a few times in this tutorial can be found in C:/Program Files/BYOND/help/ref, or on the BYOND website. When you have a question about how to do something, I advise scanning through the procs there to see if anything does what you want. There are a lot of them but chances are even if you don't find what you want, something else you'll find useful will catch your eye.

If you're still lost after you've thought your problem through, experimented, and scanned the Reference, check out the BYOND Forum. Browse or do searches for your issue. If you're still not getting anywhere, post to the Newbie Central board and ask your question. Be specific or it's very difficult for others to help you, and don't ask others to do your work for you.

Wrong: "How do I make a combat system?"
Right: "What's a sample equation to see if a mob with 50 strength and 40 accuracy will hit a monster with 45 defense?"

Wrong: "Why'd I get this error?"
Right: "Here's my code for mob variables and the attack verb. How come I got this error for the third line from the bottom?"

Wrong: "Can somebody give me code for character generation?"
Right: "Which procs would be useful for letting a player choose his race or class?"

Wrong: "How do I use BYOND?"
Right: "I read the tutorials, scanned the Reference, bought the book, now all I want to know is: where can I donate money to Dantom International?"

X. There is no X. Don't ask me Y.

Z

Wow that was kinda painful to scroll through, it's almost as unbearable to read as the original.

Might I suggest some bolds and at least something attention grabbing? Being completely plain is rough on the brain.
Also, please tweak this article by changing the colon to a period, so it is typecasted, in the snippet (the lines are M:HP and M:DeathCheck())
There are a couple of things that really need to be fixed in this tutorial. GhostAnime pointed out one of them, the other is unnecessary use of usr - which will just inspire new users to use 'usr' where they should be using 'src'.
I added some bolding throughout the article and changed the instance of colon-abuse I found. As far as I can see 'usr' is only being used in verbs, which is perfectly valid and usually the desired course of action.
I love your tutorial, this is the tut i first learned DM from.
Uh, a lot of the indentations looks wrong, like where hp is initially declared var and hp are at the same level indentation-wise.
for(var/mob/M in get_step(usr,usr.dir))

mob/proc/DeathCheck(mob/M)
if(src.HP<=0)
world<<"[M] killed [src]."
spawn(30) src.HP = 30

Meow. D:
Oldskool rox.
Thanks Nadrew, and thanks everyone else for the feedback! The indentation problems look like they were caused by spaces after the DM tags. Hopefully I've got 'em fixed now.
Now it looks much better!

Well Thanks Nadrew (I though Zilal wrote this) Although I could easily say that i program, it does not neccasserily state that i am capable to do the basics. I hav learnt the Dm Language through simple Logic and studying other sources and now i regret this(although Using Logic and stdying sources maybe good for you later on in your Programming Career). I would like to advise all fellow Newbie developers to read the guide, however irratating it, maybe you should study this aticle to your will. Also I would like to Thank this Articles Write, The article has made me a better programmer :D


Quote:'Ripping will affect you more than it will effect anything else'


Twista.
i dont get this part We made some (sort of) nice graphics, but they're not going to jump into the game all by themselves. Double-click on Testworld.dm, our code file. Under "mob", tabbed so that it sits right above "verb", stick this in:

icon = 'person.dmi' //make it so all mobs will be created with the person icon
when i have this down: mob icon = 'person.dmi'
verb
say(msg as text)
world <<"[usr]: [msg]"// the world sees what you say
it says 1 error and then it higlights verb
mob
icon = 'person.dmi'
verb
ExampleVerb()
usr << "blah blah blah"

The > represent one tab, the tab on your keyboard to indent 5 or so spaces.
ok so i keep getting inconsistent indent errors with these codes

icon = 'bug.dmi' //override the parent's icon, which was 'person.dmi'

icon_state = gender //when a player logs in, get them the right icon state for

..() //the gender of their key. Then call the parent!

DeathCheck() //check to see if an attack is deadly

if (HP <= 0) //if the defender's HP is low enough...


world << "[src] dies!" //give the death messaging

and a few otheres
itonly happens after i add the bug
This tutorial is all out of whack! Several errors found that cause problems, etc!
People, this is really old. There's going to be errors.
I think they might of noticed that eight months ago. :P
Yep probably xD
Page: 1 2

Login to reply.