mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 18:22:39 +00:00
Stack reorganization, use() now dels after yield
stack/use() now only deletes an empty stack after the current context yields, removing the need for some awkward patterns when dealing with stacks. Also adds procs for transferring and splitting stacks.
This commit is contained in:
@@ -96,6 +96,43 @@
|
||||
onclose(user, "stack")
|
||||
return
|
||||
|
||||
/obj/item/stack/proc/produce_recipe(datum/stack_recipe/recipe, var/quantity, mob/user)
|
||||
var/required = quantity*recipe.req_amount
|
||||
var/produced = min(quantity*recipe.res_amount, recipe.max_res_amount)
|
||||
|
||||
if (!can_use(required))
|
||||
if (produced>1)
|
||||
user << "\red You haven't got enough [src] to build \the [produced] [recipe.title]\s!"
|
||||
else
|
||||
user << "\red You haven't got enough [src] to build \the [recipe.title]!"
|
||||
return
|
||||
|
||||
if (recipe.one_per_turf && (locate(recipe.result_type) in user.loc))
|
||||
user << "\red There is another [recipe.title] here!"
|
||||
return
|
||||
|
||||
if (recipe.on_floor && !isfloor(user.loc))
|
||||
user << "\red \The [recipe.title] must be constructed on the floor!"
|
||||
return
|
||||
|
||||
if (recipe.time)
|
||||
user << "\blue Building [recipe.title] ..."
|
||||
if (!do_after(user, recipe.time))
|
||||
return
|
||||
|
||||
if (use(required))
|
||||
var/atom/O = new recipe.result_type(user.loc)
|
||||
O.set_dir(user.dir)
|
||||
O.add_fingerprint(user)
|
||||
|
||||
if (istype(O, /obj/item/stack))
|
||||
var/obj/item/stack/S = O
|
||||
S.amount = produced
|
||||
|
||||
if (istype(O, /obj/item/weapon/storage)) //BubbleWrap - so newly formed boxes are empty
|
||||
for (var/obj/item/I in O)
|
||||
del(I)
|
||||
|
||||
/obj/item/stack/Topic(href, href_list)
|
||||
..()
|
||||
if ((usr.restrained() || usr.stat || usr.get_active_hand() != src))
|
||||
@@ -111,64 +148,37 @@
|
||||
if (href_list["sublist"])
|
||||
var/datum/stack_recipe_list/srl = recipes_list[text2num(href_list["sublist"])]
|
||||
recipes_list = srl.recipes
|
||||
|
||||
var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])]
|
||||
var/multiplier = text2num(href_list["multiplier"])
|
||||
if (!multiplier || (multiplier <= 0)) //href exploit protection
|
||||
return
|
||||
if (src.amount < R.req_amount*multiplier)
|
||||
if (R.req_amount*multiplier>1)
|
||||
usr << "\red You haven't got enough [src] to build \the [R.req_amount*multiplier] [R.title]\s!"
|
||||
else
|
||||
usr << "\red You haven't got enough [src] to build \the [R.title]!"
|
||||
return
|
||||
if (R.one_per_turf && (locate(R.result_type) in usr.loc))
|
||||
usr << "\red There is another [R.title] here!"
|
||||
return
|
||||
if (R.on_floor && !istype(usr.loc, /turf/simulated/floor))
|
||||
usr << "\red \The [R.title] must be constructed on the floor!"
|
||||
return
|
||||
if (R.time)
|
||||
usr << "\blue Building [R.title] ..."
|
||||
if (!do_after(usr, R.time))
|
||||
return
|
||||
if (src.amount < R.req_amount*multiplier)
|
||||
return
|
||||
var/atom/O = new R.result_type( usr.loc )
|
||||
O.set_dir(usr.dir)
|
||||
if (R.max_res_amount>1)
|
||||
var/obj/item/stack/new_item = O
|
||||
new_item.amount = R.res_amount*multiplier
|
||||
//new_item.add_to_stacks(usr)
|
||||
src.amount-=R.req_amount*multiplier
|
||||
if (src.amount<=0)
|
||||
var/oldsrc = src
|
||||
src = null //dont kill proc after del()
|
||||
usr.before_take_item(oldsrc)
|
||||
del(oldsrc)
|
||||
if (istype(O,/obj/item) && istype(usr,/mob/living/carbon))
|
||||
usr.put_in_hands(O)
|
||||
O.add_fingerprint(usr)
|
||||
//BubbleWrap - so newly formed boxes are empty
|
||||
if ( istype(O, /obj/item/weapon/storage) )
|
||||
for (var/obj/item/I in O)
|
||||
del(I)
|
||||
//BubbleWrap END
|
||||
|
||||
src.produce_recipe(R, multiplier, usr)
|
||||
|
||||
if (src && usr.machine==src) //do not reopen closed window
|
||||
spawn( 0 )
|
||||
src.interact(usr)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/item/stack/proc/use(var/used)
|
||||
//Return 1 if an immediate subsequent call to use() would succeed.
|
||||
//Ensures that code dealing with stacks uses the same logic
|
||||
/obj/item/stack/proc/can_use(var/used)
|
||||
if (amount < used)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/stack/proc/use(var/used)
|
||||
if (!can_use(used))
|
||||
return 0
|
||||
amount -= used
|
||||
if (amount <= 0)
|
||||
var/oldsrc = src
|
||||
src = null //dont kill proc after del()
|
||||
if(usr)
|
||||
usr.before_take_item(oldsrc)
|
||||
del(oldsrc)
|
||||
spawn(0) //delete the empty stack once the current context yields
|
||||
if (amount <= 0) //check again in case someone transferred stuff to us
|
||||
if(usr)
|
||||
usr.before_take_item(src)
|
||||
del(src)
|
||||
return 1
|
||||
|
||||
/obj/item/stack/proc/add(var/extra)
|
||||
@@ -178,71 +188,84 @@
|
||||
amount += extra
|
||||
return 1
|
||||
|
||||
/obj/item/stack/proc/get_amount()
|
||||
return amount
|
||||
|
||||
/obj/item/stack/proc/add_to_stacks(mob/usr as mob)
|
||||
var/obj/item/stack/oldsrc = src
|
||||
src = null
|
||||
for (var/obj/item/stack/item in usr.loc)
|
||||
if (item==oldsrc)
|
||||
continue
|
||||
if (item.stacktype != oldsrc.stacktype)
|
||||
continue
|
||||
if (item.amount>=item.max_amount)
|
||||
continue
|
||||
oldsrc.attackby(item, usr)
|
||||
usr << "You add new [item.singular_name] to the stack. It now contains [item.amount] [item.singular_name]\s."
|
||||
if(!oldsrc)
|
||||
break
|
||||
/*
|
||||
The transfer and split procs work differently than use() and add().
|
||||
Whereas those procs take no action if the desired amount cannot be added or removed these procs will try to transfer whatever they can.
|
||||
They also remove an equal amount from the source stack.
|
||||
*/
|
||||
|
||||
//attempts to transfer amount to S, and returns the amount actually transferred
|
||||
/obj/item/stack/proc/transfer_to(obj/item/stack/S, var/tamount=null)
|
||||
if (!amount)
|
||||
return 0
|
||||
if (stacktype != S.stacktype)
|
||||
return 0
|
||||
if (isnull(tamount))
|
||||
tamount = src.amount
|
||||
|
||||
var/transfer = min(tamount, src.amount, (S.max_amount - S.amount))
|
||||
|
||||
if (transfer)
|
||||
if (prob(transfer/src.amount *100))
|
||||
S.copy_evidences(src) //have to do this before use() is called, unfortunately
|
||||
if (oldsrc.use(transfer))
|
||||
S.add(transfer)
|
||||
var/transfer = max(min(tamount, src.amount, (S.max_amount - S.amount)), 0)
|
||||
|
||||
var/orig_amount = src.amount
|
||||
if (transfer && src.use(transfer))
|
||||
S.add(transfer)
|
||||
if (prob(transfer/orig_amount * 100))
|
||||
S.copy_evidences(src)
|
||||
return transfer
|
||||
return 0
|
||||
|
||||
//creates a new stack with the specified amount
|
||||
/obj/item/stack/proc/split(var/tamount)
|
||||
if (!amount)
|
||||
return null
|
||||
|
||||
return transfer
|
||||
var/transfer = max(min(tamount, src.amount, initial(max_amount)), 0)
|
||||
|
||||
if (transfer && src.use(transfer))
|
||||
return new src.type(loc, transfer)
|
||||
return null
|
||||
|
||||
/obj/item/stack/proc/get_amount()
|
||||
return amount
|
||||
|
||||
/obj/item/stack/proc/add_to_stacks(mob/usr as mob)
|
||||
for (var/obj/item/stack/item in usr.loc)
|
||||
if (item==src)
|
||||
continue
|
||||
var/transfer = src.transfer_to(item)
|
||||
if (transfer)
|
||||
usr << "You add a new [item.singular_name] to the stack. It now contains [item.amount] [item.singular_name]\s."
|
||||
if(!amount)
|
||||
break
|
||||
|
||||
/obj/item/stack/attack_hand(mob/user as mob)
|
||||
if (user.get_inactive_hand() == src)
|
||||
var/obj/item/stack/F = new src.type(user, 1)
|
||||
F.copy_evidences(src)
|
||||
user.put_in_hands(F)
|
||||
src.add_fingerprint(user)
|
||||
F.add_fingerprint(user)
|
||||
use(1)
|
||||
if (src && usr.machine==src)
|
||||
spawn(0) src.interact(usr)
|
||||
var/obj/item/stack/F = src.split(1)
|
||||
if (F)
|
||||
user.put_in_hands(F)
|
||||
src.add_fingerprint(user)
|
||||
F.add_fingerprint(user)
|
||||
spawn(0)
|
||||
if (src && usr.machine==src)
|
||||
src.interact(usr)
|
||||
else
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/stack/attackby(obj/item/W as obj, mob/user as mob)
|
||||
..()
|
||||
if (istype(W, /var/obj/item/stack))
|
||||
if (istype(W, /obj/item/stack))
|
||||
var/obj/item/stack/S = W
|
||||
|
||||
var/obj/item/stack/oldsrc = src
|
||||
src = null
|
||||
if (user.get_inactive_hand()==oldsrc)
|
||||
oldsrc.transfer_to(S, 1)
|
||||
|
||||
if (user.get_inactive_hand()==src)
|
||||
src.transfer_to(S, 1)
|
||||
else
|
||||
oldsrc.transfer_to(S)
|
||||
|
||||
if (S && usr.machine==S)
|
||||
spawn(0) S.interact(usr)
|
||||
if (oldsrc && usr.machine==oldsrc)
|
||||
spawn(0) oldsrc.interact(usr)
|
||||
src.transfer_to(S)
|
||||
|
||||
spawn(0) //give the stacks a chance to delete themselves if necessary
|
||||
if (S && usr.machine==S)
|
||||
S.interact(usr)
|
||||
if (src && usr.machine==src)
|
||||
src.interact(usr)
|
||||
else return ..()
|
||||
|
||||
/obj/item/stack/proc/copy_evidences(obj/item/stack/from as obj)
|
||||
@@ -258,8 +281,8 @@
|
||||
/datum/stack_recipe
|
||||
var/title = "ERROR"
|
||||
var/result_type
|
||||
var/req_amount = 1
|
||||
var/res_amount = 1
|
||||
var/req_amount = 1 //amount of material needed for this recipe
|
||||
var/res_amount = 1 //amount of stuff that is produced in one batch (e.g. 4 for floor tiles)
|
||||
var/max_res_amount = 1
|
||||
var/time = 0
|
||||
var/one_per_turf = 0
|
||||
|
||||
Reference in New Issue
Block a user