For situations like this, I also find shoveling the logic into its own process can be helpful. That also means down the line, if you want different mobs to have different targeting rules (such as one that can't attack enemies that are "flying" or something), you can just overload it. There's a small performance cost, but for something like this I think it would be worth it.

Also, for your last example, I think adding parenthesis around the statements would make it even clearer:

for(var/mob/m in oview(10,src))
var/too_close = (get_dist(src, m) <= 4)
var/friendly = (m.team == team && m.team != NONE)


Anyway, nice article. We need more developers like you around :)
DarkCampainger wrote:
For situations like this, I also find shoveling the logic into its own process can be helpful. That also means down the line, if you want different mobs to have different targeting rules (such as one that can't attack enemies that are "flying" or something), you can just overload it. There's a small performance cost, but for something like this I think it would be worth it.

Yeah. In practice, I'd also use variables instead of the constants 4 and 10. Maybe some boolean variables too to enable or disable some of the checks (ex: a var you can set to make it ignore the team check). This way you can make minor customizations by changing some vars or you can override the proc to make larger changes.

Also, for your last example, I think adding parenthesis around the statements would make it even clearer:

> for(var/mob/m in oview(10,src))
> var/too_close = (get_dist(src, m) <= 4)
> var/friendly = (m.team == team && m.team != NONE)
>


Heh, if this was in a project of mine I'd have put the parenthesis there too, but I figured people would like it more without the parenthesis =)

Anyway, nice article. We need more developers like you around :)

Thanks!
GreatFisher wrote:
Hey F A could you give me a hand with implementing your visibility group library? If so I'll give you more info.

Actually after reading a bit I think I got it.

If you have any questions about using any of my libraries, just post on my forum: http://www.byond.com/members/Forumaccount/forum

Even if you think it's something simple or if you later figure it out yourself, I like to hear what questions people have. Also, having an answer to your question on the forum will help people who later have the same question =)
Forum_account wrote:
GreatFisher wrote:
Hey F A could you give me a hand with implementing your visibility group library? If so I'll give you more info.

Actually after reading a bit I think I got it.

If you have any questions about using any of my libraries, just post on my forum: http://www.byond.com/members/Forumaccount/forum

Even if you think it's something simple or if you later figure it out yourself, I like to hear what questions people have. Also, having an answer to your question on the forum will help people who later have the same question =)

Ha ha I figured it out the instant I started reading and it makes the certain feature of my game so cooool!!! thanks for your insane libraries they are making my game amazing.

GreatFisher wrote:
Ha ha I figured it out the instant I started reading and it makes the certain feature of my game so cooool!!! thanks for your insane libraries they are making my game amazing.

I'm glad to hear that!
Totally agree ;)
Nice tips ^^

There are tons of games where they are always using the same lines to check if the mob is frozen, stunned, etc... Then when they want to change the skills for add a new var which represents something simillar, they have to edit all the lines already coded.

Why not just a simple proc?

CheckStatus()
if(stunned==1||dead==1)
return

Same happens to the projectiles, instead of coding a proc which checks the damage and certain vars which would increase the damage, they continue adding lots and lots of lines next to Bump Proc. Which makes no sense at all. It's not so simple to make a game, but it's good to have certain procs which are nearly always called while using verbs or projectiles. If you want to change it's appareance, it's effects, and stuff, you can always check the proc and edit it.

I remember I once tried to make a Pokémon Game, I made a projectile proc, which increased / decreased the damage following the element you were hitting with and the mob's element you were dealing with. Not the best way, though, but it's better than checking if that person is a Squirtle, Wartortle, etc... Better to add a single var which checks if you're stronger against Water, Fire, etc.
Neat, thanks a bunch for the tips. I noticed you used the 4th Code Block Example inside the AI Tutorials lib (great lib) and it made coding seem so simple because I could easily see what was happening, not to mention it's way easier on the eyes. (Who looks forward to reading, "if(m.alive && (m.team != team || m.team == NONE) && get_dist(src, m) > 4)"?)

+yea

ps. "There are certain conditions we need to take into account." <-- i c what u did thar. xD
Eternal_Memories wrote:
Nice tips ^^

There are tons of games where they are always using the same lines to check if the mob is frozen, stunned, etc... Then when they want to change the skills for add a new var which represents something simillar, they have to edit all the lines already coded.

Why not just a simple proc?

CheckStatus()
if(stunned==1||dead==1)
return

That's a good idea. You might need to use this function in many places so you can make a proc to handle it, but the same ideas will apply to that proc:

mob
proc
// messy way:
valid_target(mob/m)
if(m.alive && m.team != team && get_dist(src, m) > 4)
return 1
return 0

// clean way:
valid_target(mob/m)
if(!m.alive) return 0
if(m.team == team) return 0
if(get_dist(src, m) < 4) return 0
return 1

for(var/mob/m in oview(10,src))
var/too_close = get_dist(src, m) <= 4
var/friendly = m.team == team && m.team != NONE

if(m.alive && !too_close && !friendly)
target = m
break
I don't know where I picked this up from, but I've had this habit of making code as-seemingly-efficient-as-possible. This means not declaring too many variables and not calling too many procs, "because BYOND is slow."

I think I should just try making something without that habit. I might get somewhere, even if it ends up being slow overall.
I don't trust that the DM compiler and interpreter has many optimizations, but concern over using local variables seems silly. For an if statement, BYOND has to evaluate the expression, store the result in some location in memory, then determine whether that value equates to true or false. Whether you're storing it to a local variable or it's being stored in an internal location that's not accessible to the DM program, the performance difference will certainly be negligible.

The only difference it does make would be in a case like this:

var/too_close = get_dist(src, m) <= 4
var/friendly = m.team == team && m.team != NONE

if(m.alive && !too_close && !friendly)


If m.alive is zero, you evaluate almost the entire expression in the first two lines. If you had written it out in a single if statement, as soon as the interpreter sees that m.alive is zero it can skip the rest of the expression because it knows the whole thing will be false. Even then, none of these conditions are particularly costly to evaluate.
for(var/mob/m in oview(10,src))
if(!m.alive) continue
if(m.team == team) continue
if(get_dist(src, m) <= 4) continue

target = m
break



I have a question about this piece of code. When you have multiple if() under each other. why do you need continue here? It works without it.

Or does this stop the if() procs calling more than once?

Just wondering what your opinion is on these two pieces. The first you wrote and the second was how I would write it.

for(var/mob/m in oview(10,src))
if(!m.alive) continue
if(m.team == team) continue
if(get_dist(src, m) <= 4) continue

target = m
break


for(var/mob/m in oview(10,src))
if(!m.alive)
if(m.team == team)
if(get_dist(src, m) <= 4)
target = m
break


I'm not at all saying that what you wrote is wrong, I'm just wondering what makes you want to use continue in that situation.
In response to Zecronious
continue is a loop word that makes a loop skip directly to the next iteration. It's like, if you have a for() loop with just a proc in it, inside that proc would be a "return" instead of "continue", but they do pretty much the same thing.

To write the ifs embedded in each other like that, Zecronius, you would need the opposite conditions.

Using a series of ifs with a return or continue after them is like short-circuiting. After the first if that passes, no further code is processed. This also happens when you have the conditions in a single if() and you use && or ||.
@Slic3y and Zecronious, these two things are the same:

for(something in list)
if(!condition) continue
// do something

for(something in list)
if(condition)
// do something


The difference is readability. Using continue is a way to split the conditional into multiple if statements without having excessive indentation. Instead of checking for the desired condition being true and only doing something when that occurs, we check for when the condition is not met and we skip to the loop's next iteration.
ahh, so it just beats the indentation. that's cool.
Page: 1 2