ID:147805
 
Okay, once again, I'm having a firearm related problem (No, I wasn't shot). I have set variables for each gun, two of which are the delay between being able to fire and the delay for reloading the gun.
                if(usr.wait == 1)
return
usr.projectile(new/obj/bullet(usr.loc),usr.dir,10,usr)
src.clip -= 1
if(src.clip == 0)
if(src.maxclip == 0)
usr << "The [src] is out of ammo!"
del(src)
return
usr.wait = 1
usr << "Reloading [src]..."
sleep(src.reloadelay)
if(src.maxclip <= src.fullclip - 1)
src.clip = src.maxclip
src.maxclip = 0
usr << "[src] reloaded."
usr.wait = 0
return
src.clip = src.fullclip
src.maxclip -= src.fullclip
usr << "[src] reloaded."
usr.wait = 0
return
usr.wait = 1
sleep(src.firedelay)
usr.wait = 0

The problem is, I can set the delay variables up to like thirty or forty seconds for test purposes, and I'm still able to fire while the gun is reloading.
Why are you using src and usr. Replace usr with src.
In response to Branks
Well, I left out some coding (and pasted the wrong bit to begin with, heh), but src is carried over from many other procs which is the firearm in question, and usr is the player associated to the gun.
In response to Enigmaster2002
Like Branks said, don't use usr in procs. Who knows what you'll end up with.
In response to Branks
Branks wrote:
Why are you using src and usr. Replace usr with src.

Enigmaster left out a crucial bit, which is whether this is a proc or a verb. Without knowing for sure I'd say this looks like a verb. And if it's a verb, usr is correct.

If it's not a verb, but a proc, then replacing usr with src would be wrong; it should instead be replaced with some argument to the proc.

Lummox JR
In response to Lummox JR
Why can't you use usr in procedures? Usr is the mob that called the procedure. Sure, in SOME procedures there is no usr because a huge Move() call stack or something called it. Procedures may also become verbs later.
proc/TakeDmg(D)
usr:DmgDelt += D
src.DmgTaken += D

In this case, the caller of the procedure gets it's variable (DmgDelt) boosted. Right??! I used : in case it was also called by something with null usr. I don't see why adding a mob/M param is always the way to do things.
In response to Yota
*cough*
THAT's why.

In a nutshell; it may work in some situations, but as soon as you change something, BLAM! You'll start getting weird errors and you won't know why. It will drive you INSANE. (Trust me, I know from experience, shortly before that article was written.) Use of usr in procs makes for extremely unstable programs.

Don't assume that usr is always the mob that called the procedure, because a lot of the time it isn't.

Oh, and using the colon won't have any advantage over using the period if the variable is null. It simply relaxes the compiler's type-checking (which just means that you'll get the error at runtime instead of at compile-time, which is bad). Colon use is yet another no-no, unless you've made sure (using istype() that the variable is the type that you think it is. And even then, that's lazy programming.
In response to Jon88
I found out what the problem was, heh. There's a sleep statement inside the projectile procs, and it wasn't assigning the "wait" variable until after the projectile was deleted.
In response to Yota
Yota wrote:
Why can't you use usr in procedures? Usr is the mob that called the procedure.

NO. Very very very wrong.

usr is the mob which, connected to a client, initiated a verb or some internal call like client/New().

usr is NOT (necessarily) the mob that called a proc. There is no var that keeps track of what called a proc.

An example:
mob
verb/A(mob/M as mob in world)
world << "src in A() is [src]"
world << "usr in A() is [usr]"
M.B(usr)
proc/B(mob/M)
world << "src in B() is [src]"
world << "usr in B() is [usr]"
M.C()
proc/C()
world << "src in C() is [src]"
world << "usr in C() is [usr]"
By what you said, usr in C() would be what src was in B(). But that's not the case. usr is a local var passed implicitly from the initial verb where it's set, down through all the procs called thereafter. Therefore, usr will be the same in A(), B(), and C(): it's the mob who used the A verb.

Sure, in SOME procedures there is no usr because a huge Move() call stack or something called it. Procedures may also become verbs later.

usr remains intact throughout a call stack unless it's explicitly altered, or the mob is deleted. (This may not apply to built-in procs, which might have reasons for resetting usr to null.) You can manually change the value of usr.

proc/TakeDmg(D)
usr:DmgDelt += D
src.DmgTaken += D
In this case, the caller of the procedure gets it's variable (DmgDelt) boosted. Right??!

Wrong!!!

The caller of the proc is not necessarily usr, although it may well be just by coincidence. If this is called by a verb in which src and usr are the same, then your assumption would hold.

Again, there is no var that keeps track of the caller. usr is the mob whose client initiated an action, which usually means a verb. Because procs are meant to be general-purpose routines, it's generally not safe in them to make assumptions about usr.

I used : in case it was also called by something with null usr.

Now that's just pointless. You'll get the same runtime error with : as you would with . if the value is null. This is not a valid use of the : operator.

I don't see why adding a mob/M param is always the way to do things.

Clearly. But hopefully now you do.

Lummox JR
In response to Lummox JR
Lummox JR wrote:
...

I copy that and get banned. XD How many times did your computer freeze white typing that?

Anyway, ...

If this is called by a verb in which src and usr are the same, ...

Not aways same. ^_^

(Now I'm nit-picking.)

You made your point, and am getting an idea of what you mean. USR isn't inherited from the top procedure in the stack. I thought that when using the : operator, it just skips the line or returns 0. If someone uses a like like that, they would need to use "if(M) M:DmgDelt += D" with a param named M so a "can not set null" error doesn't arrise.

*waits for post starting with "WRONG!!!"*

...

Is the coast clear? ^_^
In response to Yota
Yota wrote:
You made your point, and am getting an idea of what you mean. USR isn't inherited from the top procedure in the stack.

Well since USR is not usr, it'd have to be defined in the proc or elsewhere.

But usr in fact is inherited from the top procedure in the stack (more accurately, it's the same that usr was in the proc that called it, when it called it)--but it is not the same as src from the previous procedure. The latter is what you basically said in your post.

I thought that when using the : operator, it just skips the line or returns 0.

No. The difference between : and . is mostly in the compiler. If the datum is null, you get the same runtime error with either.

If someone uses a like like that, they would need to use "if(M) M:DmgDelt += D" with a param named M so a "can not set null" error doesn't arrise.

Well, there'd be no point using : here, since . is more appropriate.

Lummox JR
In response to Lummox JR
Yota:
You made your point, and am getting an idea of what you mean. USR isn't inherited from the top procedure in the stack.

Lummox:
Well since USR is not usr, it'd have to be defined in the proc or elsewhere.

USR isn't usr?!?!?! I used caps because I didn't want to start a sentence with lowercase letters... so I used ALL caps, much better huh?

Yota:
I thought that when using the : operator, it just skips the line or returns 0.

Lummox:
No. The difference between : and . is mostly in the compiler. If the datum is null, you get the same runtime error with either.

Ok... that's what the following line is for...

Yota:
If someone uses a like like that, they would need to use "if(M) M:DmgDelt += D" with a param named M so a "can not set null" error doesn't arrise.

Lummox:
Well, there'd be no point using : here, since . is more appropriate.

Ugh, why would I use . when the variable does not nessecarally exist for that datum?
In response to Yota
Err, i think lummox knows his :'s and .'s.
In response to Yota
Yota wrote:
USR isn't usr?!?!?! I used caps because I didn't want to start a sentence with lowercase letters... so I used ALL caps, much better huh?

Nope. For one thing, capitalizing the first letter would have been closer to correct. For another, it's grammatically okay to begin a sentence in lowercase if you're starting it off with a technical term like a var name.

All that aside, DM is a case-sensitive language.

No. The difference between : and . is mostly in the compiler. If the datum is null, you get the same runtime error with either.

Ok... that's what the following line is for...

But you still have the : operator in there where it should be . instead.

Yota:
Well, there'd be no point using : here, since . is more appropriate.

Ugh, why would I use . when the variable does not nessecarally exist for that datum?

If M is properly defined as a mob and you ensure the proc has been passed a mob, as you should, then . is correct. It's safer all around to stick with . and avoid the compiler error.

And again, the : operator will not help you if the var doesn't exist in M; all this does is avoid the compiler error, not a runtime error.

Lummox JR
In response to Lummox JR
Lummox JR wrote:
Yota:
Well, there'd be no point using : here, since . is more appropriate.

Ugh, why would I use . when the variable does not nessecarally exist for that datum?

If M is properly defined as a mob and you ensure the proc has been passed a mob, as you should, then . is correct. It's safer all around to stick with . and avoid the compiler error.

Are you forgetting?
mob
mob2
var/DmgDelt=0

M may be defined as /mob, and /mob does not have the var, whereas M may be /mob/mob2, and that DOES have the var. If "M:DmgDelt+=D" is executed, it will only take effect if the datum has that variable. If you would have used . then, you would get the "variable not defined" error, would you not?

To Karasu Kami:
He didn't know what I was talking about, now he does.
In response to Yota
Yota wrote:

Are you forgetting?
> mob
> mob2
> var/DmgDelt=0
>

M may be defined as /mob, and /mob does not have the var, whereas M may be /mob/mob2, and that DOES have the var. If "M:DmgDelt+=D" is executed, it will only take effect if the datum has that variable. If you would have used . then, you would get the "variable not defined" error, would you not?

You're right. But if you're using DmgDelt in a procedure, you're doing it while knowing that it is a mob2 variable, and not a global mob variable. In that case (I would hope, at least.), you would define the variable in said case as a mob/mob2. If you used ':' you'd just get a nice 'undefined variable' runtime error.

~>Volte
In response to Volte
Yes, but in this case, the procedure accepts ANY mob. Only mobs with that variable gets credit. So no, the procedure does not know that it's /mob/mob2. Also, I'm not using istype(M,/mob/mob2) because that datum may not be the only one with the var.

Don't forget, this isn't real code that we are using, these are examples for this topic.
In response to Yota
Yota wrote:
Yes, but in this case, the procedure accepts ANY mob. Only mobs with that variable gets credit. So no, the procedure does not know that it's /mob/mob2. Also, I'm not using istype(M,/mob/mob2) because that datum may not be the only one with the var.

Don't forget, this isn't real code that we are using, these are examples for this topic.

I'm wondering where you're trying to get in this case, though. In this 'example', you obviously want the mob specified in the arguments to be a mob/mob2. So I'm wondering why you're entering pointless lines of source code to determine if it's a mob2 type, rather than just type-cast the variable as a mob2.

I do get what you're saying, however, it is not the best to apply it to the example at hand.

~>Volte
In response to Yota
Yota wrote:
Are you forgetting?
mob
mob2
var/DmgDelt=0

M may be defined as /mob, and /mob does not have the var, whereas M may be /mob/mob2, and that DOES have the var. If "M:DmgDelt+=D" is executed, it will only take effect if the datum has that variable. If you would have used . then, you would get the "variable not defined" error, would you not?

WRONG!

You would get a "variable not defined" error in the compiler if you used . and M was the wrong type, but all the more reason to use it; then you get the error in the compiler instead of at runtime.

The statement will still be executed at runtime, regardless of whether M is the right type. If the var does not exist for M's actual type (not defined type), you'll get a runtime error.

To Karasu Kami:
He didn't know what I was talking about, now he does.

I did know, and tried to explain to you why you were way off base. You think the : operator offers some magical resistance to bugs at runtime; it does not. It only defers compiler errors to runtime.

Lummox JR
In response to Volte
Volte wrote:
M may be defined as /mob, and /mob does not have the var, whereas M may be /mob/mob2, and that DOES have the var. If "M:DmgDelt+=D" is executed, it will only take effect if the datum has that variable. If you would have used . then, you would get the "variable not defined" error, would you not?

You're right.

No he isn't; the statement will run whether M has the var or not. If it doesn't have the var, there will be a runtime error.

The difference between . and : here is only in whether you catch such a potential error at compile-time.

Lummox JR
Page: 1 2