mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-27 02:23:47 +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:
@@ -7,4 +7,7 @@
|
|||||||
return mloc
|
return mloc
|
||||||
|
|
||||||
/proc/iswall(turf/T)
|
/proc/iswall(turf/T)
|
||||||
return (istype(T, /turf/simulated/wall) || istype(T, /turf/unsimulated/wall) || istype(T, /turf/simulated/shuttle/wall))
|
return (istype(T, /turf/simulated/wall) || istype(T, /turf/unsimulated/wall) || istype(T, /turf/simulated/shuttle/wall))
|
||||||
|
|
||||||
|
/proc/isfloor(turf/T)
|
||||||
|
return (istype(T, /turf/simulated/floor) || istype(T, /turf/unsimulated/floor) || istype(T, /turf/simulated/shuttle/floor))
|
||||||
|
|||||||
@@ -96,6 +96,43 @@
|
|||||||
onclose(user, "stack")
|
onclose(user, "stack")
|
||||||
return
|
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)
|
/obj/item/stack/Topic(href, href_list)
|
||||||
..()
|
..()
|
||||||
if ((usr.restrained() || usr.stat || usr.get_active_hand() != src))
|
if ((usr.restrained() || usr.stat || usr.get_active_hand() != src))
|
||||||
@@ -111,64 +148,37 @@
|
|||||||
if (href_list["sublist"])
|
if (href_list["sublist"])
|
||||||
var/datum/stack_recipe_list/srl = recipes_list[text2num(href_list["sublist"])]
|
var/datum/stack_recipe_list/srl = recipes_list[text2num(href_list["sublist"])]
|
||||||
recipes_list = srl.recipes
|
recipes_list = srl.recipes
|
||||||
|
|
||||||
var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])]
|
var/datum/stack_recipe/R = recipes_list[text2num(href_list["make"])]
|
||||||
var/multiplier = text2num(href_list["multiplier"])
|
var/multiplier = text2num(href_list["multiplier"])
|
||||||
if (!multiplier || (multiplier <= 0)) //href exploit protection
|
if (!multiplier || (multiplier <= 0)) //href exploit protection
|
||||||
return
|
return
|
||||||
if (src.amount < R.req_amount*multiplier)
|
|
||||||
if (R.req_amount*multiplier>1)
|
src.produce_recipe(R, multiplier, usr)
|
||||||
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
|
|
||||||
if (src && usr.machine==src) //do not reopen closed window
|
if (src && usr.machine==src) //do not reopen closed window
|
||||||
spawn( 0 )
|
spawn( 0 )
|
||||||
src.interact(usr)
|
src.interact(usr)
|
||||||
return
|
return
|
||||||
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)
|
if (amount < used)
|
||||||
return 0
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
/obj/item/stack/proc/use(var/used)
|
||||||
|
if (!can_use(used))
|
||||||
|
return 0
|
||||||
amount -= used
|
amount -= used
|
||||||
if (amount <= 0)
|
if (amount <= 0)
|
||||||
var/oldsrc = src
|
spawn(0) //delete the empty stack once the current context yields
|
||||||
src = null //dont kill proc after del()
|
if (amount <= 0) //check again in case someone transferred stuff to us
|
||||||
if(usr)
|
if(usr)
|
||||||
usr.before_take_item(oldsrc)
|
usr.before_take_item(src)
|
||||||
del(oldsrc)
|
del(src)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
/obj/item/stack/proc/add(var/extra)
|
/obj/item/stack/proc/add(var/extra)
|
||||||
@@ -178,71 +188,84 @@
|
|||||||
amount += extra
|
amount += extra
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
/obj/item/stack/proc/get_amount()
|
/*
|
||||||
return amount
|
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.
|
||||||
/obj/item/stack/proc/add_to_stacks(mob/usr as mob)
|
They also remove an equal amount from the source stack.
|
||||||
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
|
|
||||||
|
|
||||||
//attempts to transfer amount to S, and returns the amount actually transferred
|
//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)
|
/obj/item/stack/proc/transfer_to(obj/item/stack/S, var/tamount=null)
|
||||||
|
if (!amount)
|
||||||
|
return 0
|
||||||
if (stacktype != S.stacktype)
|
if (stacktype != S.stacktype)
|
||||||
return 0
|
return 0
|
||||||
if (isnull(tamount))
|
if (isnull(tamount))
|
||||||
tamount = src.amount
|
tamount = src.amount
|
||||||
|
|
||||||
var/transfer = min(tamount, src.amount, (S.max_amount - S.amount))
|
|
||||||
|
|
||||||
if (transfer)
|
var/transfer = max(min(tamount, src.amount, (S.max_amount - S.amount)), 0)
|
||||||
if (prob(transfer/src.amount *100))
|
|
||||||
S.copy_evidences(src) //have to do this before use() is called, unfortunately
|
var/orig_amount = src.amount
|
||||||
if (oldsrc.use(transfer))
|
if (transfer && src.use(transfer))
|
||||||
S.add(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)
|
/obj/item/stack/attack_hand(mob/user as mob)
|
||||||
if (user.get_inactive_hand() == src)
|
if (user.get_inactive_hand() == src)
|
||||||
var/obj/item/stack/F = new src.type(user, 1)
|
var/obj/item/stack/F = src.split(1)
|
||||||
F.copy_evidences(src)
|
if (F)
|
||||||
user.put_in_hands(F)
|
user.put_in_hands(F)
|
||||||
src.add_fingerprint(user)
|
src.add_fingerprint(user)
|
||||||
F.add_fingerprint(user)
|
F.add_fingerprint(user)
|
||||||
use(1)
|
spawn(0)
|
||||||
if (src && usr.machine==src)
|
if (src && usr.machine==src)
|
||||||
spawn(0) src.interact(usr)
|
src.interact(usr)
|
||||||
else
|
else
|
||||||
..()
|
..()
|
||||||
return
|
return
|
||||||
|
|
||||||
/obj/item/stack/attackby(obj/item/W as obj, mob/user as mob)
|
/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/S = W
|
||||||
|
|
||||||
var/obj/item/stack/oldsrc = src
|
if (user.get_inactive_hand()==src)
|
||||||
src = null
|
src.transfer_to(S, 1)
|
||||||
if (user.get_inactive_hand()==oldsrc)
|
|
||||||
oldsrc.transfer_to(S, 1)
|
|
||||||
else
|
else
|
||||||
oldsrc.transfer_to(S)
|
src.transfer_to(S)
|
||||||
|
|
||||||
if (S && usr.machine==S)
|
spawn(0) //give the stacks a chance to delete themselves if necessary
|
||||||
spawn(0) S.interact(usr)
|
if (S && usr.machine==S)
|
||||||
if (oldsrc && usr.machine==oldsrc)
|
S.interact(usr)
|
||||||
spawn(0) oldsrc.interact(usr)
|
if (src && usr.machine==src)
|
||||||
|
src.interact(usr)
|
||||||
else return ..()
|
else return ..()
|
||||||
|
|
||||||
/obj/item/stack/proc/copy_evidences(obj/item/stack/from as obj)
|
/obj/item/stack/proc/copy_evidences(obj/item/stack/from as obj)
|
||||||
@@ -258,8 +281,8 @@
|
|||||||
/datum/stack_recipe
|
/datum/stack_recipe
|
||||||
var/title = "ERROR"
|
var/title = "ERROR"
|
||||||
var/result_type
|
var/result_type
|
||||||
var/req_amount = 1
|
var/req_amount = 1 //amount of material needed for this recipe
|
||||||
var/res_amount = 1
|
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/max_res_amount = 1
|
||||||
var/time = 0
|
var/time = 0
|
||||||
var/one_per_turf = 0
|
var/one_per_turf = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user