diff --git a/code/game/objects/items/crab17.dm b/code/game/objects/items/crab17.dm index 59973a8617a..2664cff95d4 100644 --- a/code/game/objects/items/crab17.dm +++ b/code/game/objects/items/crab17.dm @@ -6,6 +6,7 @@ w_class = WEIGHT_CLASS_SMALL attack_verb_continuous = list("dumps") attack_verb_simple = list("dump") + /// Has the phone been used already? var/dumped = FALSE /obj/item/suspiciousphone/attack_self(mob/living/user) @@ -32,11 +33,11 @@ new /obj/effect/dumpeet_target(targetturf, L) to_chat(user, span_notice("You have activated Protocol CRAB-17.")) - message_admins("[ADMIN_LOOKUPFLW(user)] has activated Protocol CRAB-17.") user.log_message("activated Protocol CRAB-17.", LOG_GAME) dumped = TRUE + /obj/structure/checkoutmachine name = "\improper Nanotrasen Space-Coin Market" desc = "This is good for spacecoin because" @@ -48,15 +49,23 @@ density = TRUE pixel_z = -8 max_integrity = 5000 + /// List of bank accounts to take money from, determines in start_dumping() var/list/accounts_to_rob + /// The original user of the suspicious phone var/mob/living/bogdanoff /// Are we able to start moving? var/canwalk = FALSE + /// Our own internal bank account, serves as a fallback to transfer money to if Bogdanoff doesn't have one + var/datum/bank_account/internal_account /obj/structure/checkoutmachine/examine(mob/living/user) . = ..() . += span_info("It has a flashing ID card reader for convenient cashing out.") +/** + * Check whether any accounts in the accounts_to_rob list are still being drained. + * Returns TRUE if no accounts are being drained, FALSE otherwise + */ /obj/structure/checkoutmachine/proc/check_if_finished() for(var/i in accounts_to_rob) var/datum/bank_account/B = i @@ -103,6 +112,7 @@ if(QDELETED(src)) return bogdanoff = user + internal_account = new /datum/bank_account/remote("CRAB-17", 0, player_account = FALSE) add_overlay("flaps") add_overlay("hatch") add_overlay("legs_retracted") @@ -110,7 +120,9 @@ QDEL_IN(src, 8 MINUTES) //Self-destruct after 8 min ADD_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING, REF(src)) - +/** + * Starts the dumping process and plays a start-up animation before the checkout starts walking. + */ /obj/structure/checkoutmachine/proc/startUp() //very VERY snowflake code that adds a neat animation when the pod lands. start_dumping() //The machine doesnt move during this time, giving people close by a small window to grab their funds before it starts running around sleep(1 SECONDS) @@ -171,17 +183,23 @@ add_overlay("screen_lines") cut_overlay("text") add_overlay("text") - START_PROCESSING(SSfastprocess, src) // we only start doing economy draining stuff once our machinery is initialized, thematically + START_PROCESSING(SSfastprocess, src) canwalk = TRUE /obj/structure/checkoutmachine/Destroy() stop_dumping() STOP_PROCESSING(SSfastprocess, src) priority_announce("The credit deposit machine at [get_area(src)] has been destroyed. Station funds have stopped draining!", sender_override = "CRAB-17 Protocol") + if(internal_account.account_balance) + expel_cash() + QDEL_NULL(internal_account) explosion(src, light_impact_range = 1, flame_range = 2) REMOVE_TRAIT(SSeconomy, TRAIT_MARKET_CRASHING, REF(src)) return ..() +/** + * Grabs the accounts to be robbed and puts them in accounts_to_rob, tells the accounts they're being drained and calls dump() to start draining. + */ /obj/structure/checkoutmachine/proc/start_dumping() accounts_to_rob = flatten_list(SSeconomy.bank_accounts_by_id) accounts_to_rob -= bogdanoff?.get_bank_account() @@ -190,6 +208,11 @@ B.dumpeet() dump() +/** + * For each account being drained, pulls a random percentage of cash out the account and sends it to Bogdanoff's account. + * If Bogdanoff did not have a bank account, stores the funds in the checkout's internal_account. + * Sets a timer to call itself again after an interval. + */ /obj/structure/checkoutmachine/proc/dump() var/percentage_lost = (rand(5, 15) / 100) for(var/i in accounts_to_rob) @@ -198,10 +221,9 @@ accounts_to_rob -= B continue var/amount = round(B.account_balance * percentage_lost) // We don't want fractions of a credit stolen. That's just agony for everyone. - var/datum/bank_account/account = bogdanoff?.get_bank_account() - if (account) // get_bank_account() may return FALSE - account.transfer_money(B, amount, "?VIVA¿: !LA CRABBE¡") - B.bank_card_talk("You have lost [percentage_lost * 100]% of your funds! A spacecoin credit deposit machine is located at: [get_area(src)].") + var/datum/bank_account/account = bogdanoff?.get_bank_account() || internal_account + account.transfer_money(B, amount, "?VIVA¿: !LA CRABBE¡") + B.bank_card_talk("You have lost [percentage_lost * 100]% of your funds! A spacecoin credit deposit machine is located at: [get_area(src)].") addtimer(CALLBACK(src, PROC_REF(dump)), 15 SECONDS) //Drain every 15 seconds /obj/structure/checkoutmachine/process() @@ -209,12 +231,31 @@ if(Process_Spacemove(anydir)) Move(get_step(src, anydir), anydir) +/** + * Goes through accounts_to_rob and tells every account that the drain has stopped. + */ /obj/structure/checkoutmachine/proc/stop_dumping() for(var/i in accounts_to_rob) var/datum/bank_account/B = i if(B) B.being_dumped = FALSE +/** + * Splits the balance of the internal_account into several smaller piles of cash and scatters them around the area. + */ +/obj/structure/checkoutmachine/proc/expel_cash() + var/funds_remaining = internal_account.account_balance + var/safety = funds_remaining + 1 // In the absolute worst case scenario the loop will complete in funds_remaining steps, if this is counter reaches 0 something went terribly wrong and we need to leave + while(floor(funds_remaining)) + var/amount_to_remove = min(funds_remaining, rand(1, round(internal_account.account_balance)/8)) + var/obj/item/holochip/holochip = new (get_turf(src), amount_to_remove) + funds_remaining -= amount_to_remove + holochip.throw_at(pick(oview(7,get_turf(src))),10,1) + safety -= 1 + if(safety <= 0) + CRASH("/obj/structure/checkoutmachine/proc/expel_cash() did not complete in the theoretical maximum number of steps. Starting value: [internal_account.account_balance]. Value at crash: [funds_remaining].") + + /obj/effect/dumpeet_fall //Falling pod name = "" icon = 'icons/obj/machines/money_machine_64.dmi' @@ -224,6 +265,7 @@ plane = ABOVE_GAME_PLANE icon_state = "missile_blur" + /obj/effect/dumpeet_target name = "Landing Zone Indicator" desc = "A holographic projection designating the landing zone of something. It's probably best to stand back." @@ -242,6 +284,9 @@ sound_to_playing_players('sound/items/dump_it.ogg', 20) deadchat_broadcast("Protocol CRAB-17 has been activated. A space-coin market has been launched at the station!", turf_target = get_turf(src), message_type=DEADCHAT_ANNOUNCEMENT) +/** + * Sets up the falling animation for the checkout machine. + */ /obj/effect/dumpeet_target/proc/startLaunch() DF = new /obj/effect/dumpeet_fall(drop_location()) dump = new /obj/structure/checkoutmachine(null, bogdanoff) @@ -250,8 +295,9 @@ playsound(src, 'sound/items/weapons/mortar_whistle.ogg', 70, TRUE, 6) addtimer(CALLBACK(src, PROC_REF(endLaunch)), 5, TIMER_CLIENT_TIME) //Go onto the last step after a very short falling animation - - +/** + * Cleans up after the falling animation. + */ /obj/effect/dumpeet_target/proc/endLaunch() QDEL_NULL(DF) //Delete the falling machine effect, because at this point its animation is over. We dont use temp_visual because we want to manually delete it as soon as the pod appears playsound(src, SFX_EXPLOSION, 80, TRUE)