ID:140791
 
Code:
mob
NPC
MartK
name = "Mart Keeper"
icon = 'Mart keeper.dmi'
icon_state = "1"
NPC = 2
verb
Buy()
set src in oview(2)
set category = "NPC"
switch(input("Welcome to my mart,what would you like to buy?") in list ("Pokeball : 75","Potion : 100","Super Potion : 200"))
if("Pokeball : 75")
var/buy = input("How many Pokeballs do you wish to buy?")as num
var/buying = buy*75
for(var/obj/Pokemoney/O in usr.contents)
if(buying <= 0)
usr<<"You can't buy that ammount"
return
if(buying > O.ammount)
usr<<"You don't have enough money for that"
return
else
usr<<"You have bought [buy] Pokeball(s)"
O.ammount -= buying
var/obj/Pokeball/B = new/obj/Pokeball
B.ammount = buy
for(var/obj/Pokeball/A in usr.contents)
counter+=1
if(counter<=0)
B.Move(usr)
B.name = "Pokeball"
B.name= "[B.name]: [B.ammount]"
else
for(var/obj/Pokeball/A in usr.contents)
A.ammount+=B.ammount
A.name = "Pokeball"
A.name= "[A.name]: [A.ammount]"
del(B)
O.name = "Pokemoney"
O.name= "[O.name]: [O.ammount]"
if("Potion : 100")
var/buy = input("How many Potions do you wish to buy?")as num
var/buying = buy*100
for(var/obj/Pokemoney/O in usr.contents)
if(buying <= 0)
usr<<"You can't buy that ammount"
return
if(buying > O.ammount)
usr<<"You don't have enough money for that"
return
else
usr<<"You have bought [buy] Potion(s)"
O.ammount -= buying
var/obj/Potion/B = new/obj/Potion
B.ammount = buy
for(var/obj/Potion/A in usr.contents)
counter+=1
if(counter<=0)
B.Move(usr)
B.name = "Potion"
B.name= "[B.name]: [B.ammount]"
else
for(var/obj/Potion/A in usr.contents)
A.ammount+=B.ammount
A.name = "Potion"
A.name= "[A.name]: [A.ammount]"
del(B)
O.name = "Pokemoney"
O.name= "[O.name]: [O.ammount]"
if("Super Potion : 200")
var/buy = input("How many Super Potions do you wish to buy?")as num
var/buying = buy*200
for(var/obj/Pokemoney/O in usr.contents)
if(buying <= 0)
usr<<"You can't buy that ammount"
return
if(buying > O.ammount)
usr<<"You don't have enough money for that"
return
else
usr<<"You have bought [buy] Super Potion(s)"
O.ammount -= buying
var/obj/SPotion/B = new/obj/SPotion
B.ammount = buy
for(var/obj/SPotion/A in usr.contents)
counter+=1
if(counter<=0)
B.Move(usr)
B.name = "Super Potion"
B.name= "[B.name]: [B.ammount]"
else
for(var/obj/SPotion/A in usr.contents)
A.ammount+=B.ammount
A.name = "Super Potion"
A.name= "[A.name]: [A.ammount]"
del(B)
O.name = "Pokemoney"
O.name= "[O.name]: [O.ammount]"


Problem description:Mostly when there are many people online the NPC won't sell them the item but he still takes money from them

I don't see any definition for your counter variable, which leads me to believe it's defined somewhere that makes no damn sense and is causing this to try to add to the amount of an item when there aren't any.

Also: that entire thing is a gigantic mess. You've mucked up the concept of item stacking and are obviously paying the price for it. You've also created a mess of buying items. This is what would make more sense:

//ITEM STACKING:

item
//setting parent_type lets us have /obj/item but only have to type out /item
parent_type = /obj
//the maximum number of items that can be stacked together, 0 for unlimited
var/stacksize = 1
//how many items are in this stack
var/amount = 1
//verbs for all items
verb
//all items can be picked up
get()
set src in oview(1)
//Move() must be called when moving items for stacking to work
if(Move(usr))
usr << "You pick up [src]"
//all items can be dropped
drop()
set src in usr
if(Move(usr.loc))
usr << "You drop [src]"

proc
//here is our proc to stack
stack()
//loop through all items in the same location
for(var/item/I in loc)
//check that we can stack with I
if(I.canstack(src))
//find how many we can move from src to I
var/N
//only up to stacksize if it's nonzero
if(I.stacksize)
N = min(amount, I.stacksize-I.amount)
//as many as we have if stacksize is zero (and thus unlimited)
else
N = amount

amount -= N
I.amount += N
//update I's suffix
I.update()

//delete src if we're empty
if(amount == 0)
del(src)
//call update() to update our suffix
update()

//this lets us know if we can stack with another item
//I is new item being added, and src is the object it is trying to merge into
canstack(var/item/I)
//by default we just return 1 if we're the same type
//we can override this for different cases, though
//IE: return 0 if some variables don't match
//or return 1 even if types don't match (picking up ammo and stacking with a clip)
return (I.type == src.type)

//this is called whenever we update the amount in a stack
update()
//update our suffix to show how many are in this stack
suffix = "[amount]"
//oh, and let's use the gender variable too
if(amount > 1)
gender = "plural"
else
gender = "neuter"
//this is available to be overridden to display the amount differently

//here is a proc to delete N items from a stack
remove(var/N)
//if we don't have that many, return 0
if(amount < N)
return 0
//if we have precisely that many
else if(amount == N)
//we have to use the default return value variable . to return something here:
. = 1
//because we're deleting the object, and we can't do anything after that delete
del(src)
//we are, however, returning a true value (indicating success), so we'll put this here so we know that
return 1
//the line is never actually executed
//in most cases, N will be less than amount, so we just subtract N from amount and carry on
else
amount -= N
update()
return 1

//whenever we're moved somewhere
Move(loc, dir, var/nostack = 0)
//perform the default move action
.=..()
//if the move was successful and we aren't not stacking
if(. && !nostack)
//stack with anything in our new location
stack()

//also, try to stack when we're created
New(Loc, var/amount = 0, var/nostack = 0)
..()
//if we specified an amount, set our amount to that. Otherwise, just leave it as the default
if(amount)
src.amount = amount
//stack if we didn't specify not to
if(!nostack)
stack()
//if we don't call stack(), we'll need to call update() (stack() would have done it for us)
else
update()


//SHOPKEEPER:
item
var/price = 1
//for buying stuff:
money
stacksize = 0

mob/shopkeeper
New()
..()
//wait for the world to finish being created
sleep(0)
//pick up anything below us
for(var/item/I in loc)
I.Move(src)

verb/buy()
//generate a list of "item: $price"
var/selections = list()
for(var/item/I in src)
selections["[I.name]: $[I.price]"] = I
//select from that list, and grab the associated item
var/selection = input(usr,"Buy what?") as null|anything in selections
if(selection)
var/item/I = selections[selection]
var/amount = input(usr,"How many?") as num
amount = round(amount)
if(amount >= 1)
//calculate the total price
var/total = I.price * amount
//find their money and try to take enough of it
var/item/money/M = locate() in usr
if(M && M.remove(total))
//they have enough (and have had it taken) so give them the item
usr << "You have bought [amount] [I]\s."
new I.type(usr, amount)
else
//they do not have enough
usr << "You do not have enough money!"


(the indentation is mixed up because I wrote one in the IDE and one on the forum)

Anyway, that gives you items which will stack without you having to do anything at all besides call Move(), and a generic shopkeeper that can sell anything by simply dropping items at their feet in the map editor.
In response to Garthor
Well i tried changing stuff to fix it but nothing...

item
Pokemoney
name = "Pokemoney"
icon = 'Items.dmi'
icon_state = "Pokemoney"


I putted this but it won't stack when I use get,so do I need to define something specific? (I defined stacksize to unlimited and ammount of it to 1)(well i just placed 2 pokemoneys near the shop keeper for testing)
In response to Destrojer
Are your get() and drop() verbs using Move()?
In response to Garthor
Yes,just as you said they should