ID:146474
 
Code:
mob/verb/drop_gold()
ammount_to_drop = input(usr,"How much gold do you wish to drop?","Gold to Drop?",usr.gold)
while(ammount_to_drop % 1.00 != 0)
usr << "You can not drop a value that is not a whole number."
return
if(ammount_to_drop >> usr.gold)
usr << "You don't even have that much gold to drop."
return
if(ammount_to_drop <= -1)
usr << "You can not drop negative gold."
return
else
new/obj/gold(usr.loc, ammount_to_drop)
usr.gold -= ammount_to_drop
usr << "You drop [ammount_to_drop] gold."



Problem description:Now, everything is fine, no errors, no warnings, but the modulus is not working. If the ammount_to_drop == 25.6, then it's remainder is not equal to 0, it equals 6. But it says even when I input the 25.6, that the remainder is still 0? Either the modulus is broken, or I'm doing something wrong.

I don't think that works with decimals. How about using round() instead, and rounding to the nearest 1? If the round()ed number is different from the given number, the given number had a decimal place.
Modulo is, by definition, an integer operation; i.e. one that only behaves as expected when given whole numbers. It won't work for what you're trying to do.

What I usually do is just round the input I'm given:

amount_to_drop = input(usr,"How much gold do you wish to drop?","Gold to Drop?",usr.gold)
amount_to_drop = round(amount_to_drop)


That way it will just ignore the fractional part of the number if someone types one in; so 25.6 becomes 25.

There are two other problems here that you need to fix:

1. The >> operator is not what you want. It's a binary "shift" operator, and its function is too obscure to go into right now. What you want is the "greater-than comparison" operator, which is the > operator. Note that there is only one >.

2. You don't want a while() loop here: while(ammount_to_drop % 1.00 != 0) You should use an if() there; while() isn't suited to the task, because if it wasn't for the return it would loop infinitely. And infinitely loops are very, very bad things. =) Although you should get rid of this bit anyway, and replace it with the round()ing I mentioned above.
In response to Crispy
Hey man you know what, thank you for answering. I really appreciate your help. I have another problem. Please help with this one too.
mob/verb/drop_gold()
ammount_to_drop = input(usr,"How much gold do you wish to drop?","Gold to Drop?",usr.gold)
ammount_to_drop = round(ammount_to_drop)
if(ammount_to_drop % 1 != 0)
usr << "You can not drop a value that is not a whole number."
return
if(ammount_to_drop >> usr.gold)
usr << "You don't even have that much gold to drop."
return
if(ammount_to_drop <= -1)
usr << "You can not drop negative gold."
return
else
new/obj/gold(usr.loc, ammount_to_drop)
usr.gold -= ammount_to_drop
usr << "You drop [ammount_to_drop] gold."

The problem here is that everytime I make a new bag of gold, the last one I made's value is now all the others values as well.
In response to DragonMasterGod
You haven't fixed the >/>> operator confusion. This line:

if(ammount_to_drop >> usr.gold)


Needs to look like this:

if(ammount_to_drop > usr.gold)


Notice the small but all-important difference.

Apart from that, that snippet of code looks fine. Can you show me your /obj/gold object's New() proc?

(By the way, you might want to also check for them entering 0 gold. But kudos for thinking about it enough to check for negative and fractional gold; not everyone remembers to do that.)
In response to Crispy
Ok Crispy here you go, I tried to check for 0 gold and negative gold.
var/obj/ammount_to_drop = 0
obj/gold
icon = 'gold-bag.dmi'
ammount_to_drop
mob/verb/drop_gold()
ammount_to_drop = input(usr,"How much gold do you wish to drop?","Gold to Drop?",usr.gold)
ammount_to_drop = round(ammount_to_drop)
if(ammount_to_drop % 1 != 0)
usr << "You can not drop a value that is not a whole number."
return
if(ammount_to_drop > usr.gold)
usr << "You don't even have that much gold to drop."
return
if(ammount_to_drop <= -1)
usr << "You can not drop negative gold."
return
else
new/obj/gold(usr.loc, ammount_to_drop)
usr.gold -= ammount_to_drop
usr << "You drop [ammount_to_drop] gold."

I'm kinda still in the process of learning DM, even though I've been learning it for almost 2 years now "5 months knowing what I'm doing."
In response to Jon88
Thank you man, Crispy helped me out with that, not there's a different problem.
In response to DragonMasterGod
Okay, I'm confused. Where is ammount_to_drop (you misspelt it by the way) defined so that it's accessible in the verb? Why have you defined it on /objs? Where does the gold actually get its amount set? What var does the gold use to hold its var?

Please post everything related to /obj/gold, and show all the bits where you've defined ammount_to_drop.
In response to Crispy
Ok, ammount_to_drop is under the obj variable, I set the variable so that it belongs to the object (the only way I could find to make the amount as in numbers inside of the object that falls) so that when the other person picks up the icon, they get the variable within that icon (as an object) which is in this case, the amount that was dropped. This is what I got so far.
//everything for dropping gold
var/obj/ammount_to_drop = 0
obj/gold
icon = 'gold-bag.dmi'
ammount_to_drop
mob/verb/drop_gold()
ammount_to_drop = input(usr,"How much gold do you wish to drop?","Gold to Drop?",usr.gold)
ammount_to_drop = round(ammount_to_drop)
if(ammount_to_drop % 1 != 0)
usr << "You can not drop a value that is not a whole number."
return
if(ammount_to_drop > usr.gold)
usr << "You don't even have that much gold to drop."
return
if(ammount_to_drop <= -1)
usr << "You can not drop negative gold."
return
else
new/obj/gold(usr.loc, ammount_to_drop)
usr.gold -= ammount_to_drop
usr << "You drop [ammount_to_drop] gold."
//for picking up the gold
obj
verb
get()
set src in usr.loc
if(ammount_to_drop) //if the object has an ammount_to_drop variable
usr.gold += ammount_to_drop
usr << "You get [ammount_to_drop] gold."
del(src)
if(!ammount_to_drop)
usr.contents += src
usr.has_items += 1
usr << "You get [src.name]."
drop()
if(src.usage == "Equip")
usr << "This item is equip right now, remove it first"
return
if(src.usage == "None")
if(src.equip_types == "Weapon")
set src in usr.contents
src.loc = usr.loc
usr << "You drop [src.name]."
usr.has_items -= 1
if(src.equip_types == "Armor")
set src in usr.contents
src.loc = usr.loc
usr << "You drop [src.name]."
usr.has_items -= 1

My brother wants to get on, post everything you can though right please Crispy, thank you for helping me.
In response to DragonMasterGod
One of your variable definitions goes like this:

var/obj/ammount_to_drop = 0


This variable would be an object -- an obj, specifically. Initializing an object to 0 makes no sense. Really, that whole variable makes no sense. =P

obj/gold
icon = 'gold-bag.dmi'
ammount_to_drop


Why define ammount_to_drop under /obj/gold? Instead, it should be defined within the drop verb since it is only to be used within the drop verb:

obj/gold/icon = 'gold-bag.dmi'

mob/verb/drop_gold()
var/ammount_to_drop = input(...) as num
//...


Notice the "as num" there. You want the player to give you a number -- not a string. =)

Well, the snippet should work at this point, but there are a few parts that can be improved:

ammount_to_drop = round(ammount_to_drop)
if(ammount_to_drop % 1 != 0)
usr << "You can not drop a value that is not a whole number."
return


If you round() ammount_to_drop, then that if(ammount_to_drop % 1 != 0) check isn't necessary -- round(ammount_to_drop) will round ammount_to_drop to the next integer anyway.

if(ammount_to_drop <= -1)
usr << "You can not drop negative gold."
return


If you want to check for an amount of 0 gold, then you should change the above snippet to this:

if(ammount_to_drop < 1)
usr << "You cannot drop a non-positive amount of gold."
return
In response to Wizkidd0123
Thanks for the help wizkid, but I need to fix what the problem is. The problem is that everytime I drop gold bags, the last value of the gold bag that I dropped is now the value of all the gold bags. Look.
var/obj/ammount_to_drop

obj/gold
icon = 'gold-bag.dmi'
ammount_to_drop /* when picking up objects from the floor, I need this var so that it belongs to the object, so I can check if the object being picked up has this variable*/
mob/verb/drop_gold()
ammount_to_drop = input(usr,"How much gold do you wish to drop?","Gold to Drop?",usr.gold) as num
ammount_to_drop = round(ammount_to_drop)
if(ammount_to_drop > usr.gold)
usr << "You don't even have that much gold to drop."
return
if(ammount_to_drop < 1)
usr << "You can not drop less than 1 gold."
return
else
new/obj/gold(usr.loc, ammount_to_drop)
usr.gold -= ammount_to_drop
usr << "You drop [ammount_to_drop] gold."
//My picking up code
obj
verb
get()
set src in usr.loc
if(amount_to_drop)
usr.gold += amount_to_drop
usr << "You get [amount_to_drop] gold."
del(src)
if(!amount_to_drop)
usr.contents += src
usr.has_items += 1
usr << "You get [src.name]."
drop()
if(src.usage == "Equip")
usr << "This item is equip right now, remove it first"
return
if(src.usage == "None")
if(src.equip_types == "Weapon")
set src in usr.contents
src.loc = usr.loc
usr << "You drop [src.name]."
usr.has_items -= 1
if(src.equip_types == "Armor")
set src in usr.contents
src.loc = usr.loc
usr << "You drop [src.name]."
usr.has_items -= 1

It is still not working. I think there may be a problem with the picking up code. It's a logic error. It says there are no errors or warnings. It's just not workning the way it's supposed to.
In response to DragonMasterGod
You're using a GLOBAL /obj variable, set to a number.

Next, why do you have drop_gold() and drop()? drop()'s code apparently is only for gold, since it actually used the word "gold" in it's strings.

If you're going to use a 'set src = usr' verb, which is what /mob/verb/drop_gold is, you should use 'src' in stead of 'usr'. There are rare cases where 'usr' would be wanted, but not here!

Let's take a look at this:
obj/gold
icon = 'gold-bag.dmi'
ammount_to_drop

Don't you see what you're doing here? You're declaring a new prototype! /obj/gold/ammount_to_drop!

Back to that global variable. Why is it global, and why is it casted as /obj? Using a global variable is very dangerous, especially for multi-threaded programs! So sleep(), and spawn will be very dangerous. (Again, local variables are the way to go!)
In response to Crispy
Crispy wrote:
Modulo is, by definition, an integer operation; i.e. one that only behaves as expected when given whole numbers. It won't work for what you're trying to do.

What I usually do is just round the input I'm given:
amount_to_drop = input(usr,"How much gold do you wish to drop?","Gold to Drop?",usr.gold)
amount_to_drop = round(amount_to_drop)


Also, I don't know if you knew this already but, you can skip that second line.

Example:
amount_to_drop = min(max(round(input(usr,"How much gold do you wish to drop?","Gold to Drop?",usr.gold)),0),round(usr.gold))
In response to DragonMasterGod
DragonMasterGod wrote:
Thanks for the help wizkid, but I need to fix what the problem is. The problem is that everytime I drop gold bags, the last value of the gold bag that I dropped is now the value of all the gold bags. Look.

While Wizkidd's advice doesn't appear to directly relate to your problem, you should still consider it and follow it. Firstly because it will improve your code, which is always good; and secondly because once some errors are pointed out, the causes behind other errors become apparent.

when picking up objects from the floor, I need this var so that it belongs to the object, so I can check if the object being picked up has this variable

Firstly, you haven't defined that as a var; it needs a "var/" before it. Secondly, you're getting rather confused about what you're doing. Let me explain:

What you're doing is defining a global var called ammount_to_drop (it's still misspelt =)). This is bad! Why? Because there's only one "ammount_to_drop" var. Ever. This means that when you're setting that var for one bag of gold, you're setting it for ALL of them!

See the problem now? You're using the same var for multiple gold bags. Each var can only have one value, so every single gold bag has the same value of ammount_to_drop! In other words, every gold bag has the same amount of gold in it. =)

You're also using the same var for asking the player how much gold they want to deposit, and for holding how much gold exists. This is a bit messy; and once we apply the fix to the above problem, it will stop compiling because the global "ammount_to_drop" var will not exist. So we need to change this as well.

So this is what we need to do:

1. Give each gold bag its own var to hold how much gold is in it.

2. Use a different var to store the player's desired drop amount.

Firstly, a little revision on type paths. There is a big difference between these two lines:

mob/var/bestfriend
var/mob/bestfriend


The bit before the "var" is the type of object the variable belongs to. The bit after the "var" is the type of object the variable refers to.

In the example above, the first line defines a var called bestfriend that belongs to all mobs. In other words, all mobs have a best friend. (Hooray!) The second line, though, defines only one best friend, and declares it to be a mob. According to the second line, there is only one best friend in the whole entire universe! Just one! A single one! Isn't that sad? =(

So basically what we need to do is swap the "var" and "obj" around, so that the var belongs to all objs.

"But wait!" you cry. "Not all objs need an amount! Only gold does!"

And you are correct in saying that - even if you didn't say it. ;-D So in fact, what we need to do is give it to all /obj/golds.

I'm also going to rename the var, so its name better matches what it's for; and I'm going to give it an initial value of zero. Replace "var/obj/ammount_to_drop" with this line:

obj/gold/var/amount = 0


See what that's doing? This var belongs to each /obj/gold object, and refers to a number.

Now on to problem #2. This is easy; instead of using the global var, we now use a local var instead. What's a local var? One that's defined in the proc where it's used, that's what:

mob/verb/drop_gold()
var/amount_to_drop = input(usr,"How much gold do you wish to drop?","Gold to Drop?",usr.gold) as num


Notice the "var/" bit; that defines the variable.

   amount_to_drop = round(amount_to_drop)
if(amount_to_drop > usr.gold)
usr << "You don't even have that much gold to drop."
return
if(amount_to_drop < 1)
usr << "You can not drop less than 1 gold."
return
else


This bit (above) is nearly the same, except for the replacement of "ammount_to_drop" (the misspelled global variable) with "amount_to_drop" (the new local variable).

Now, let's look at this line:

      new/obj/gold(usr.loc, ammount_to_drop)


Danger, Will Robinson! The second argument there does nothing, because /obj/gold does not take a second argument to New(). In other words; it's useless.

We have two options:
1. Override /obj/gold/New() so that it accepts a second argument and sets its amount var to it, OR
2. Set the amount var in this proc.

#1 is slightly advanced, so I'm sticking with #2 for now.

Firstly, because we're referring to the bag of gold after its creation, we need a var that refers to it. To do so, we just save the return value of new(), like so:

var/obj/gold/bagofgold = new/obj/gold(usr.loc)


Actually, we can shorten this a bit. Since we've been nice and well-behaved and defined the bagofgold var with its correct type, we can avoid repeating "/obj/gold" after the "new":

var/obj/gold/bagofgold = new(usr.loc)


...and this will still work, exactly the same.

Now we just need to set the bag of gold's amount var. You know how to set vars, right? =)

bagofgold.amount = amount_to_drop


Yay! Our bag of gold now contains the correct amount.

      usr.gold -= amount_to_drop
usr << "You drop [amount_to_drop] gold."


The above two lines are the same except for the changing of the var "ammount_to_drop" to "amount_to_drop".

Whew! That was a lot of typing! But we're not quite done yet. Now we need be able to pick the thing up again.

Now that I've gone and defined your amount var under /obj/gold instead of /obj, this snippet won't work, because not all /objs have amount_to_drop:

obj
verb
get()
set src in usr.loc
if(amount_to_drop)
usr.gold += amount_to_drop
usr << "You get [amount_to_drop] gold."
del(src)
if(!amount_to_drop)
usr.contents += src
usr.has_items += 1
usr << "You get [src.name]."


Slow down cowboy! Don't go reaching for that there amount_to_drop definition. There's a "better" way to do this. =)

A "get" operation is quite different for a bag of gold than it is for a normal obj. Ideally we'd want to specify each operation in a different place. (It may not be clear to you why this is better; that's okay, just go along with it for now.)

Firstly, let's define picking up for normal objs:

obj
verb
get()
set src in usr.loc
if(!amount_to_drop)
usr.Move(src)
usr.has_items += 1
usr << "You get [src.name]."


I'll leave you to spot the differences from your existing snippet. =) (Hint: There are two.)

And now, through the magic of object-oriented programming, let us define picking up using the same verb in a different place! Drum roll, please...

obj
gold
get()
set src in usr.loc
usr.gold += src.amount_to_drop
usr << "You get [src.amount_to_drop] gold."
del(src)


As well as defining it under /obj, we've defined it under /obj/gold. "Defining it twice? How can we do that?" Actually we can't; I've defined it once, and overridden it once.

Note that I haven't said "obj/gold/verb/get()"; just "obj/gold/get()". Why? Well, trying putting the "verb" bit back in and see what happens when you try to compile. =) They're still the same verb, which means you can't define it twice. What the above snippet does it override an already defined verb.

Confused yet? You should be. ;-) Read it over a few more times and see if it starts to make sense after a while.

So what's left to do? Actually, nothing. We're done (at last)! Yay!

... Well, I really hope that helped, because I spent about an hour typing it up. My apologies for making you read an essay, but hopefully you'll be a better programmer at the end of it all. =D
In response to Crispy
Thanks for the help man, I really appreciate your time and I did learn a lot from what you just wrote. But now there is another problem.
obj   
gold
get()
set src in usr.loc
usr.gold += src.amount_to_drop
usr << "You get [src.amount_to_drop] gold."
del(src)

Now it's saying that src.amount_to_drop is an undefined variable -.-'. I think I know why, it's because the amount_to_drop variable is where the drop_gold() verb is and not where the obj/verb/get() verb is. It's a local verb, so it is only used when that verb is used. Not when the obj/verb/get() verb is used. How can I fix this? Yea, I know, by moving it, but then a course of other problems come into play.
In response to DragonMasterGod
Thanks for the help man, I really appreciate your time and I did learn a lot from what you just wrote. But now there is another problem.
obj   
gold
get()
set src in usr.loc
usr.gold += src.amount_to_drop
usr << "You get [src.amount_to_drop] gold."
del(src)

Now it's saying that src.amount_to_drop is an undefined variable -.-'. I think I know why, it's because the amount_to_drop variable is where the drop_gold() verb is and not where the obj/verb/get() verb is. It's a local verb, so it is only used when that verb is used. Not when the obj/verb/get() verb is used. How can I fix this? Yea, I know, by moving it, but then a course of other problems come into pl
In response to DragonMasterGod
obj   
var/amoount_to_drop
gold
get()
set src in usr.loc
usr.gold += src.amount_to_drop
usr << "You get [src.amount_to_drop] gold."
del(src)
In response to DragonMasterGod
Whoops! My bad. I should have typed "amount", not "amount_to_drop".