From 6fc9950e4555b81c24c46a3639d3b12ad7a3975c Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Wed, 28 Oct 2015 18:49:14 -0400 Subject: [PATCH] Gave space cash a proc get_total() to return value of stack, and fixed richest escapee scoreboard line to actually get bank account (was ref'ing phantom var) and get cash amount correctly. --- code/game/gamemodes/newobjective.dm | 2880 +++++++++++------------ code/game/gamemodes/scoreboard.dm | 484 ++-- code/game/machinery/vending.dm | 4 +- code/game/objects/items/weapons/cash.dm | 219 +- code/modules/economy/ATM.dm | 805 ++++--- code/modules/economy/POS.dm | 1076 ++++----- code/modules/economy/cash.dm | 116 +- 7 files changed, 2789 insertions(+), 2795 deletions(-) diff --git a/code/game/gamemodes/newobjective.dm b/code/game/gamemodes/newobjective.dm index 9f183206633..000bb60f2b7 100644 --- a/code/game/gamemodes/newobjective.dm +++ b/code/game/gamemodes/newobjective.dm @@ -1,1441 +1,1441 @@ -#define FRAME_PROBABILITY 3 -#define THEFT_PROBABILITY 55 -#define KILL_PROBABILITY 37 -#define PROTECT_PROBABILITY 5 - -#define LENIENT 0 -#define NORMAL 1 -#define HARD 2 -#define IMPOSSIBLE 3 - - -/proc/GenerateTheft(var/job,var/datum/mind/traitor) - var/list/datum/objective/objectives = list() - - for(var/o in subtypesof(/datum/objective/steal)) - var/datum/objective/target = new o(null,job) - objectives += target - objectives[target] = target.weight - return objectives - -/proc/GenerateAssassinate(var/job,var/datum/mind/traitor) - var/list/datum/objective/assassinate/missions = list() - - for(var/datum/mind/target in ticker.minds) - if((target != traitor) && istype(target.current, /mob/living/carbon/human)) - if(target && target.current) - var/datum/objective/target_obj = new /datum/objective/assassinate(null,job,target) - missions += target_obj - missions[target_obj] = target_obj.weight - return missions - -/proc/GenerateFrame(var/job,var/datum/mind/traitor) - var/list/datum/objective/frame/missions = list() - - for(var/datum/mind/target in ticker.minds) - if((target != traitor) && istype(target.current, /mob/living/carbon/human)) - if(target && target.current) - var/datum/objective/target_obj = new /datum/objective/frame(null,job,target) - missions += target_obj - missions[target_obj] = target_obj.weight - return missions - -/proc/GenerateProtection(var/job,var/datum/mind/traitor) - var/list/datum/objective/frame/missions = list() - - for(var/datum/mind/target in ticker.minds) - if((target != traitor) && istype(target.current, /mob/living/carbon/human)) - if(target && target.current) - var/datum/objective/target_obj = new /datum/objective/protection(null,job,target) - missions += target_obj - missions[target_obj] = target_obj.weight - return missions - - -/proc/SelectObjectives(var/job,var/datum/mind/traitor,var/hijack = 0) - var/list/chosenobjectives = list() - var/list/theftobjectives = GenerateTheft(job,traitor) //Separated all the objective types so they can be picked independantly of each other. - var/list/killobjectives = GenerateAssassinate(job,traitor) - var/list/frameobjectives = GenerateFrame(job,traitor) - var/list/protectobjectives = GenerateProtection(job,traitor) - var/total_weight - var/conflict - - var/steal_weight = THEFT_PROBABILITY - var/frame_weight = FRAME_PROBABILITY - var/kill_weight = KILL_PROBABILITY - var/protect_weight = PROTECT_PROBABILITY - var/target_weight = 50 - -///////////////////////////////////////////////////////////// -//HANDLE ASSIGNING OBJECTIVES BASED OFF OF PREVIOUS SUCCESS// -///////////////////////////////////////////////////////////// - - var/savefile/info = new("data/player_saves/[copytext(traitor.key, 1, 2)]/[traitor.key]/traitor.sav") - var/list/infos - info >> infos - if(istype(infos)) - var/total_attempts = infos["Total"] - var/total_overall_success = infos["Success"] - var/success_ratio = total_overall_success/total_attempts - var/steal_success = infos["Steal"] - var/kill_success = infos["Kill"] - var/frame_success = infos["Frame"] - var/protect_success = infos["Protect"] - - var/list/ordered_success = list(steal_success, kill_success, frame_success, protect_success) - - var/difficulty = pick(LENIENT, LENIENT, NORMAL, NORMAL, NORMAL, HARD, HARD, IMPOSSIBLE) - //Highest to lowest in terms of success rate, and resulting weight for later computation - var/success_weights = list(1, 1, 1, 1) - switch(difficulty) - if(LENIENT) - success_weights = list(1.5, 1, 0.75, 0.5) - target_weight = success_ratio*100 - if(NORMAL) - target_weight = success_ratio*150 - if(HARD) - success_weights = list(0.66, 0.8, 1, 1.25) - target_weight = success_ratio*200 - if(IMPOSSIBLE) //YOU SHALL NOT PASS - success_weights = list(0.5, 0.75, 1.2, 2) - target_weight = success_ratio*300 - - for(var/i = 1, i <= 4, i++) - //Iterate through the success rates, and determine the weights to chose based on the highest to - // the lowest to multiply it by the proper success ratio. - var/weight = max(ordered_success) - ordered_success -= weight - if(weight == steal_success) - steal_weight *= steal_success*success_weights[i] - else if(weight == frame_success) - frame_weight *= frame_success*success_weights[i] - else if(weight == protect_success) - protect_weight *= protect_success*success_weights[i] - else if(weight == kill_success) - kill_weight *= kill_success*success_weights[i] - - var/total_weights = kill_weight + protect_weight + frame_weight + steal_weight - frame_weight = round(frame_weight/total_weights) - kill_weight = round(kill_weight/total_weights) - steal_weight = round(steal_weight/total_weights) - //Protect is whatever is left over. - - var/steal_range = steal_weight - var/frame_range = frame_weight + steal_range - var/kill_range = kill_weight + frame_range - //Protect is whatever is left over. - - while(total_weight < target_weight) - var/selectobj = rand(1,100) //Randomly determine the type of objective to be given. - if(!length(killobjectives) || !length(protectobjectives)|| !length(frameobjectives)) //If any of these lists are empty, just give them theft objectives. - var/datum/objective/objective = pickweight(theftobjectives) - chosenobjectives += objective - total_weight += objective.points - theftobjectives -= objective - else switch(selectobj) - if(1 to steal_range) - if(!theftobjectives.len) - continue - var/datum/objective/objective = pickweight(theftobjectives) - for(1 to 10) - if(objective.points + total_weight <= 100 || !theftobjectives.len) - break - theftobjectives -= objective - objective = pickweight(theftobjectives) - if(!objective && !theftobjectives.len) - continue - chosenobjectives += objective - total_weight += objective.points - theftobjectives -= objective - if(steal_range + 1 to frame_range) //Framing Objectives (3% chance) - if(!frameobjectives.len) - continue - var/datum/objective/objective = pickweight(frameobjectives) - for(1 to 10) - if(objective.points + total_weight <= 100 || !frameobjectives.len) - break - frameobjectives -= objective - objective = pickweight(frameobjectives) - if(!objective && !frameobjectives.len) - continue - for(var/datum/objective/protection/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Assassinate somebody they need to Protect. - if(conflicttest.target == objective.target) - conflict = 1 - break - for(var/datum/objective/assassinate/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Protect somebody they need to Assassinate. - if(conflicttest.target == objective.target) - conflict = 1 - break - if(!conflict) - chosenobjectives += objective - total_weight += objective.points - frameobjectives -= objective - conflict = 0 - if(frame_range + 1 to kill_range) - if(!killobjectives.len) - continue - var/datum/objective/assassinate/objective = pickweight(killobjectives) - world << objective - for(1 to 10) - if(objective.points + total_weight <= 100 || !killobjectives.len) - break - killobjectives -= objective - objective = pickweight(killobjectives) - if(!objective && !killobjectives.len) - continue - for(var/datum/objective/protection/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Assassinate somebody they need to Protect. - if(conflicttest.target == objective.target) - conflict = 1 - break - for(var/datum/objective/frame/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Protect somebody they need to Assassinate. - if(conflicttest.target == objective.target) - conflict = 1 - break - if(!conflict) - chosenobjectives += objective - total_weight += objective.points - killobjectives -= objective - conflict = 0 - if(kill_range + 1 to 100) //Protection Objectives (5% chance) - if(!protectobjectives.len) - continue - var/datum/objective/protection/objective = pickweight(protectobjectives) - for(1 to 10) - if(objective.points + total_weight <= 100 || !protectobjectives.len) - break - protectobjectives -= objective - objective = pickweight(protectobjectives) - if(!objective || !protectobjectives.len) - continue - for(var/datum/objective/assassinate/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Protect somebody they need to Assassinate. - if(conflicttest.target == objective.target) - conflict = 1 - break - for(var/datum/objective/frame/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Protect somebody they need to Assassinate. - if(conflicttest.target == objective.target) - conflict = 1 - break - if(!conflict) - chosenobjectives += objective - total_weight += objective.points - protectobjectives -= objective - conflict = 0 - - if(!locate(/datum/objective/hijack) in chosenobjectives && !locate(/datum/objective/escape) in chosenobjectives) - if(hijack) - chosenobjectives += new /datum/objective/hijack(null,job) - else - chosenobjectives += new /datum/objective/escape(null,job) - return chosenobjectives - -datum - objective - var/datum/mind/owner - var/datum/mind/target - var/explanation_text = "text not set" - var/job - var/points = INFINITY //If this isn't set to something else, the objective is bugged and should be ignored - var/weight = INFINITY - - New(var/text,var/joba) - if(text) - src.explanation_text = text - job=joba - weight = get_weight(job) - points = get_points(job) - - proc/check_completion() - return 1 - proc/get_points(var/job) - return INFINITY - proc/get_weight(var/job) - return INFINITY - proc/find_target_by_role(role, role_type=0)//Option sets either to check assigned role or special role. Default to assigned. - for(var/datum/mind/possible_target in ticker.minds) - if((possible_target != owner) && ishuman(possible_target.current) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) ) - target = possible_target - break - - - frame - New(var/text,var/joba,var/datum/mind/targeta) - target = targeta - job = joba - weight = get_points(job) - explanation_text = "Frame [target.current.real_name], the [target.assigned_role] for a crime and make sure they are arrested and brought back to the Centcom station alive. We'll handle the rest from there." - - check_completion() - if(!emergency_shuttle.returned()) - return 0 - if(target.current.stat == 2) - return 0 - var/turf/location = get_turf(target.current.loc) - if(!location) - return 0 - if(!target.current:handcuffed && !istype(location, /turf/simulated/shuttle/floor4)) - return 0 - - if(location in locate(/area/shuttle/escape/centcom)) - return 1 - - return 0 - - get_points() - if(target) - var/difficulty = GetRank(target.assigned_role) + 1 - switch(GetRank(job)) - if(4) - return 20*difficulty - if(3) - return 30*difficulty - if(2) - return 40*difficulty - if(1) - return 55*difficulty - if(0) - return 60*difficulty - else - return INFINITY - - get_weight() - if(target) - return 1 - return 0 - - - protection - New(var/text,var/joba,var/datum/mind/targeta) - target = targeta - job = joba - weight = get_points(job) - explanation_text = "[target.current.real_name], the [target.assigned_role] is a [pick("relative of a","friend of a","") + pick("high ranking","important","well-liked")] Syndicate [pick("Leader","Officer","Agent","sympathiser")]. Make sure they get off the station safely, while minimizing intervention." - - check_completion() - if(!emergency_shuttle.returned()) - return 0 - - if(target.current.stat == 2) - return 0 - - var/turf/location = get_turf(target.current.loc) - if(!location) - return 0 - - if(location in locate(/area/shuttle/escape/centcom)) - return 1 - - return 0 - - get_points() - if(target) - return 30 - else - return INFINITY - - get_weight() - if(target) - return 1 - return 0 - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Protect [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)]." - else - explanation_text = "Free Objective" - return target - - - assassinate - - New(var/text,var/joba,var/datum/mind/targeta) - target = targeta - job = joba - weight = get_points(job) - explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role]." - - check_completion() - if(target && target.current) - if(target.current.stat == 2 || istype(get_area(target.current), /area/tdome) || issilicon(target.current) || isbrain(target.current)) - return 1 - else - return 0 - else - return 1 - get_points() - if(target) - var/difficulty = GetRank(target.assigned_role) + 1 - switch(GetRank(job)) - if(4) - return 20*difficulty - if(3) - return 30*difficulty - if(2) - return 40*difficulty - if(1) - return 55*difficulty - if(0) - return 60*difficulty - else - return 0 - - get_weight() - if(target) - return 1 - return 0 - - find_target_by_role(var/role) - for(var/datum/mind/possible_target in ticker.minds) - if((possible_target != owner) && istype(possible_target.current, /mob/living/carbon/human) && (possible_target.assigned_role == role)) - target = possible_target - break - - if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role]." - else - explanation_text = "Free Objective" - - return target - - - proc/find_target() - var/list/possible_targets = list() - - for(var/datum/mind/possible_target in ticker.minds) - if((possible_target != owner) && istype(possible_target.current, /mob/living/carbon/human)) - possible_targets += possible_target - - if(possible_targets.len > 0) - target = pick(possible_targets) - - if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role]." - else - explanation_text = "Free Objective" - - return target - - - capture - var/separation_time = 0 - var/almost_complete = 0 - - New(var/text,var/joba,var/datum/mind/targeta) - target = targeta - job = joba - explanation_text = "Capture [target.current.real_name], the [target.assigned_role]." - - check_completion() - if(target && target.current) - if(target.current.stat == 2) - if(config.require_heads_alive) return 0 - else - if(!target.current.handcuffed) - return 0 - else if(config.require_heads_alive) return 0 - return 1 - - find_target_by_role(var/role) - for(var/datum/mind/possible_target in ticker.minds) - if((possible_target != owner) && istype(possible_target.current, /mob/living/carbon/human) && (possible_target.assigned_role == role)) - target = possible_target - break - - if(target && target.current) - explanation_text = "Capture [target.current.real_name], the [target.assigned_role]." - else - explanation_text = "Free Objective" - - return target - - get_points() - if(target) - var/difficulty = GetRank(target.assigned_role) + 1 - switch(GetRank(job)) - if(4) - return 20*difficulty - if(3) - return 30*difficulty - if(2) - return 40*difficulty - if(1) - return 55*difficulty - if(0) - return 60*difficulty - else - return INFINITY - - get_weight() - if(target) - return 1 - return 0 - - - hijack - explanation_text = "Hijack the emergency shuttle by escaping alone." - - check_completion() - if(!emergency_shuttle.returned()) - return 0 - - if(!owner.current || owner.current.stat == 2) - return 0 - var/turf/location = get_turf(owner.current.loc) - - if(location in locate(/area/shuttle/escape/centcom)) - for(var/mob/living/player in locate(/area/shuttle/escape/centcom)) - if (player.mind && (player.mind != owner)) - if (player.stat != 2) //they're not dead - return 0 - return 1 - - return 0 - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 65 - if(2) - return 65 - if(3) - return 50 - if(4) - return 35 - - get_weight(var/job) - return 1 - - escape - explanation_text = "Escape on the shuttle alive, without being arrested." - - check_completion() - if(!emergency_shuttle.returned()) - return 0 - - if(!owner.current || owner.current.stat ==2) - return 0 - - var/turf/location = get_turf(owner.current.loc) - if(!location) - return 0 - - if(owner.current:handcuffed || istype(location, /turf/simulated/shuttle/floor4)) - return 0 - - if(location in locate(/area/shuttle/escape/centcom)) - return 1 - - return 0 - get_points() - return INFINITY - - get_weight(var/job) - return 1 - - - survive - explanation_text = "Stay alive." - - check_completion() - if(!owner.current || owner.current.stat == 2) - return 0 - - return 1 - get_points() - return INFINITY - - get_weight(var/job) - return 1 - - - steal - var/obj/item/steal_target - - check_completion() - if(steal_target) - if(owner.current.check_contents_for(steal_target)) - return 1 - else - return 0 - - - captainslaser - steal_target = /obj/item/weapon/gun/energy/laser/captain - explanation_text = "Steal the captain's antique laser gun." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 60 - if(1) - return 50 - if(2) - return 40 - if(3) - return 30 - if(4) - return 20 - - get_weight(var/job) - if(GetRank(job) == 4) - return 10 - else - return 20 - - - plasmatank - steal_target = /obj/item/weapon/tank/plasma - explanation_text = "Steal a small plasma tank." - weight = 20 - - get_points(var/job) - if(job in science_positions || job in command_positions) - return 20 - return 40 - - get_weight(var/job) - return 20 - - check_completion() - var/list/all_items = owner.current.get_contents() - for(var/obj/item/I in all_items) - if(!istype(I, steal_target)) continue//If it's not actually that item. - if(I:air_contents:toxins) return 1 //If they got one with plasma - return 0 - - - /*Removing this as an objective. Not necessary to have two theft objectives in the same room. - steal/captainssuit - steal_target = /obj/item/clothing/under/rank/captain - explanation_text = "Steal a captain's rank jumpsuit" - weight = 50 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return INFINITY - */ - - - handtele - steal_target = /obj/item/weapon/hand_tele - explanation_text = "Steal a hand teleporter." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - get_weight(var/job) - if(GetRank(job) == 4) - return 10 - else - return 20 - - - RCD - steal_target = /obj/item/weapon/rcd - explanation_text = "Steal a rapid construction device." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - get_weight(var/job) - if(GetRank(job) == 4) - return 10 - else - return 20 - - - /*burger - steal_target = /obj/item/weapon/reagent_containers/food/snacks/human/burger - explanation_text = "Steal a burger made out of human organs, this will be presented as proof of Nanotrasen's chronic lack of standards." - weight = 60 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 80 - if(1) - return 65 - if(2) - return 55 - if(3) - return 40 - if(4) - return 25*/ - - - jetpack - steal_target = /obj/item/weapon/tank/jetpack/oxygen - explanation_text = "Steal a blue oxygen jetpack." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - get_weight(var/job) - if(GetRank(job) == 4) - return 10 - else - return 20 - - - /*magboots - steal_target = /obj/item/clothing/shoes/magboots - explanation_text = "Steal a pair of \"Nanotrasen\" brand magboots." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - get_weight(var/job) - if(GetRank(job) == 4) - return 10 - else - return 20*/ - - - blueprints - steal_target = /obj/item/blueprints - explanation_text = "Steal the station's blueprints." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - get_weight(var/job) - if(GetRank(job) == 4) - return 10 - else - return 20 - - - voidsuit - steal_target = /obj/item/clothing/suit/space/nasavoid - explanation_text = "Steal a voidsuit." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - get_weight(var/job) - return 20 - - - nuke_disk - steal_target = /obj/item/weapon/disk/nuclear - explanation_text = "Steal the station's nuclear authentication disk." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 90 - if(1) - return 80 - if(2) - return 70 - if(3) - return 40 - if(4) - return 25 - - get_weight(var/job) - if(GetRank(job) == 4) - return 10 - else - return 20 - - nuke_gun - steal_target = /obj/item/weapon/gun/energy/gun/nuclear - explanation_text = "Steal a nuclear powered gun." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 90 - if(1) - return 85 - if(2) - return 80 - if(3) - return 75 - if(4) - return 75 - - get_weight(var/job) - return 2 - - diamond_drill - steal_target = /obj/item/weapon/pickaxe/drill/diamonddrill - explanation_text = "Steal a diamond drill." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 90 - if(1) - return 85 - if(2) - return 70 - if(3) - return 75 - if(4) - return 75 - - get_weight(var/job) - return 2 - - boh - steal_target = /obj/item/weapon/storage/backpack/holding - explanation_text = "Steal a \"bag of holding.\"" - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 90 - if(1) - return 85 - if(2) - return 80 - if(3) - return 75 - if(4) - return 75 - - get_weight(var/job) - return 2 - - hyper_cell - steal_target = /obj/item/weapon/stock_parts/cell/hyper - explanation_text = "Steal a hyper capacity power cell." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 90 - if(1) - return 85 - if(2) - return 80 - if(3) - return 75 - if(4) - return 75 - - get_weight(var/job) - return 2 - - lucy - steal_target = /obj/item/stack/sheet/diamond - explanation_text = "Steal 10 diamonds." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 90 - if(1) - return 85 - if(2) - return 80 - if(3) - return 75 - if(4) - return 75 - - get_weight(var/job) - return 2 - - check_completion() - var/target_amount = 10 - var/found_amount = 0.0//Always starts as zero. - for(var/obj/item/I in owner.current.get_contents()) - if(!istype(I, steal_target)) continue//If it's not actually that item. - found_amount += I:amount - return found_amount>=target_amount - - gold - steal_target = /obj/item/stack/sheet/gold - explanation_text = "Steal 50 gold bars." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 90 - if(1) - return 85 - if(2) - return 80 - if(3) - return 75 - if(4) - return 70 - - get_weight(var/job) - return 2 - - check_completion() - var/target_amount = 50 - var/found_amount = 0.0//Always starts as zero. - for(var/obj/item/I in owner.current.get_contents()) - if(!istype(I, steal_target)) continue//If it's not actually that item. - found_amount += I:amount - return found_amount>=target_amount - - uranium - steal_target = /obj/item/stack/sheet/uranium - explanation_text = "Steal 25 uranium bars." - weight = 20 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 90 - if(1) - return 85 - if(2) - return 80 - if(3) - return 75 - if(4) - return 70 - - get_weight(var/job) - return 2 - - check_completion() - var/target_amount = 25 - var/found_amount = 0.0//Always starts as zero. - for(var/obj/item/I in owner.current.get_contents()) - if(!istype(I, steal_target)) continue//If it's not actually that item. - found_amount += I:amount - return found_amount>=target_amount - - - /*Needs some work before it can be put in the game to differentiate ship implanters from syndicate implanters. - steal/implanter - steal_target = /obj/item/weapon/implanter - explanation_text = "Steal an implanter" - weight = 50 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return INFINITY - */ - cyborg - steal_target = /obj/item/robot_parts/robot_suit - explanation_text = "Steal a completed robot shell (no brain)" - weight = 30 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - check_completion() - if(steal_target) - for(var/obj/item/robot_parts/robot_suit/objective in owner.current.get_contents()) - if(istype(objective,/obj/item/robot_parts/robot_suit) && objective.check_completion()) - return 1 - return 0 - - get_weight(var/job) - return 20 - AI - steal_target = /obj/structure/AIcore - explanation_text = "Steal a finished AI, either by intellicard or stealing the whole construct." - weight = 50 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - get_weight(var/job) - return 15 - - check_completion() - if(steal_target) - for(var/obj/item/device/aicard/C in owner.current.get_contents()) - for(var/mob/living/silicon/ai/M in C) - if(istype(M, /mob/living/silicon/ai) && M.stat != 2) - return 1 - for(var/mob/living/silicon/ai/M in world) - if(istype(M.loc, /turf)) - if(istype(get_area(M), /area/shuttle/escape)) - return 1 - for(var/obj/structure/AIcore/M in world) - if(istype(M.loc, /turf) && M.state == 4) - if(istype(get_area(M), /area/shuttle/escape)) - return 1 - return 0 - - drugs - steal_target = /datum/reagent/space_drugs - explanation_text = "Steal some space drugs." - weight = 40 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - check_completion() - if(steal_target) - if(owner.current.check_contents_for_reagent(steal_target)) - return 1 - else - return 0 - - get_weight(var/job) - return 20 - - - pacid - steal_target = /datum/reagent/pacid - explanation_text = "Steal some polytrinic acid." - weight = 40 - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - check_completion() - if(steal_target) - if(owner.current.check_contents_for_reagent(steal_target)) - return 1 - else - return 0 - - get_weight(var/job) - return 20 - - - reagent - weight = 20 - var/target_name - New(var/text,var/joba) - ..() - var/list/items = list("Sulphuric acid", "Polytrinic acid", "Space Lube", "Unstable mutagen",\ - "Leporazine", "Cryptobiolin", "Lexorin ",\ - "Kelotane", "Dexalin", "Tricordrazine") - target_name = pick(items) - switch(target_name) - if("Sulphuric acid") - steal_target = /datum/reagent/acid - if("Polytrinic acid") - steal_target = /datum/reagent/pacid - if("Space Lube") - steal_target = /datum/reagent/lube - if("Unstable mutagen") - steal_target = /datum/reagent/mutagen - if("Leporazine") - steal_target = /datum/reagent/leporazine - if("Cryptobiolin") - steal_target =/datum/reagent/cryptobiolin - if("Lexorin") - steal_target = /datum/reagent/lexorin - if("Kelotane") - steal_target = /datum/reagent/kelotane - if("Dexalin") - steal_target = /datum/reagent/dexalin - if("Tricordrazine") - steal_target = /datum/reagent/tricordrazine - - explanation_text = "Steal a container filled with [target_name]." - - get_points(var/job) - switch(GetRank(job)) - if(0) - return 75 - if(1) - return 60 - if(2) - return 50 - if(3) - return 30 - if(4) - return 20 - - check_completion() - if(steal_target) - if(owner.current.check_contents_for_reagent(steal_target)) - return 1 - else - return 0 - - get_weight(var/job) - return 20 - - cash //must be in credits - atm and coins don't count - var/steal_amount = 2000 - explanation_text = "Beg, borrow or steal 2000 credits." - weight = 20 - - New(var/text,var/joba) - ..(text,joba) - steal_amount = 1250 + rand(0,3750) - explanation_text = "Beg, borrow or steal [steal_amount] credits." - - get_points(var/job) - return 10 + 25 * round(steal_amount / 5000) - - check_completion() - var/held_credits = 0 - for(var/obj/item/weapon/spacecash/M in owner.current.get_contents()) - held_credits += M.worth - if(held_credits >= steal_amount) - return 1 - return 0 - - get_weight(var/job) - return 20 - - - nuclear - explanation_text = "Destroy the station with a nuclear device." - - - block - explanation_text = "Do not allow any humans to escape on the shuttle alive." - - - check_completion() - if(!istype(owner.current, /mob/living/silicon)) - return 0 - if(!emergency_shuttle.returned()) - return 0 - if(!owner.current) - return 0 - var/area/shuttle = locate(/area/shuttle/escape/centcom) - var/protected_mobs[] = list(/mob/living/silicon/ai, /mob/living/silicon/pai, /mob/living/silicon/robot) - for(var/mob/living/player in world) - if(player.type in protected_mobs) continue - if (player.mind) - if (player.stat != 2) - if (get_turf(player) in shuttle) - return 0 - return 1 - - decapitate - New(var/text,var/joba,var/datum/mind/targeta) - target = targeta - job = joba - explanation_text = "Remove and recover the head of [target.current.real_name], the [target.assigned_role]." - proc/find_target() - ..() - if(target && target.current) - explanation_text = "[target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role], has defied us for the last time. Make an example of him, and bring us his severed head." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "[target.current.real_name], the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)], has defied us for the last time. Make an example of him, and bring us his severed head." - else - explanation_text = "Free Objective" - return target - - - check_completion() - if(target && target.current) - if(!owner.current||owner.current.stat==2)//If you're otherwise dead. - return 0 - var/list/all_items = owner.current.get_contents() - for(var/obj/item/weapon/organ/head/mmi in all_items) - if(mmi.brainmob&&mmi.brainmob.mind==target) - return 1 - return 0 - else - return 1 - - absorb - var/target_amount - proc/gen_amount_goal(var/lowbound = 4, var/highbound = 6) - target_amount = rand (lowbound,highbound) - if (ticker) - var/n_p = 1 //autowin - if (ticker.current_state == GAME_STATE_SETTING_UP) - for(var/mob/new_player/P in world) - if(P.client && P.ready && P.mind!=owner) - n_p ++ - else if (ticker.current_state == GAME_STATE_PLAYING) - for(var/mob/living/carbon/human/P in world) - if(P.client && !(P.mind in ticker.mode.changelings) && P.mind!=owner) - n_p ++ - target_amount = min(target_amount, n_p) - - explanation_text = "Absorb [target_amount] compatible genomes." - return target_amount - - check_completion() - if(owner && owner.current && owner.current.changeling && owner.current.changeling.absorbed_dna && ((owner.current.changeling.absorbed_dna.len - 1) >= target_amount)) - return 1 - else - return 0 - - meme_attune - var/target_amount - proc/gen_amount_goal(var/lowbound = 4, var/highbound = 6) - target_amount = rand (lowbound,highbound) - - explanation_text = "Attune [target_amount] humanoid brains." - return target_amount - - check_completion() - if(owner && owner.current && istype(owner.current,/mob/living/parasite/meme) && (owner.current:indoctrinated.len >= target_amount)) - return 1 - else - return 0 - - download - var/target_amount - proc/gen_amount_goal() - target_amount = rand(10,20) - explanation_text = "Download [target_amount] research levels." - return target_amount - - - check_completion() - return 0 - - - debrain//I want braaaainssss - New(var/text,var/joba,var/datum/mind/targeta) - target = targeta - job = joba - explanation_text = "Remove and recover the brain of [target.current.real_name], the [target.assigned_role]." - - proc/find_target() - ..() - if(target && target.current) - explanation_text = "Steal the brain of [target.current.real_name]." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Steal the brain of [target.current.real_name] the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)]." - else - explanation_text = "Free Objective" - return target - - - check_completion() - if(!target)//If it's a free objective. - return 1 - if(!owner.current||owner.current.stat==2)//If you're otherwise dead. - return 0 - var/list/all_items = owner.current.get_contents() - for(var/obj/item/device/mmi/mmi in all_items) - if(mmi.brainmob&&mmi.brainmob.mind==target) return 1 - for(var/obj/item/brain/brain in all_items) - if(brain.brainmob&&brain.brainmob.mind==target) return 1 - return 0 - - mutiny - proc/find_target() - ..() - if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role]." - else - explanation_text = "Free Objective" - return target - - - find_target_by_role(role, role_type=0) - ..(role, role_type) - if(target && target.current) - explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)]." - else - explanation_text = "Free Objective" - return target - - - check_completion() - if(target && target.current) - var/turf/T = get_turf(target.current) - if(target.current.stat == 2) - return 1 - else if((T) && !(T.z in config.station_levels))//If they leave the station they count as dead for this - return 2 - else - return 0 - else - return 1 - - capture - var/target_amount - proc/gen_amount_goal() - target_amount = rand(5,10) - explanation_text = "Accumulate [target_amount] capture points." - return target_amount - - - check_completion()//Basically runs through all the mobs in the area to determine how much they are worth. - return 0 - -datum/objective/silence - explanation_text = "Do not allow anyone to escape the station. Only allow the shuttle to be called when everyone is dead and your story is the only one left." - - check_completion() - if(!emergency_shuttle.returned()) - return 0 - - var/area/shuttle = locate(/area/shuttle/escape/centcom) - var/area/pod1 = locate(/area/shuttle/escape_pod1/centcom) - var/area/pod2 = locate(/area/shuttle/escape_pod2/centcom) - var/area/pod3 = locate(/area/shuttle/escape_pod3/centcom) - var/area/pod4 = locate(/area/shuttle/escape_pod5/centcom) - - for(var/mob/living/player in world) - if (player == owner.current) - continue - if (player.mind) - if (player.stat != 2) - if (get_turf(player) in shuttle) - return 0 - if (get_turf(player) in pod1) - return 0 - if (get_turf(player) in pod2) - return 0 - if (get_turf(player) in pod3) - return 0 - if (get_turf(player) in pod4) - return 0 - return 1 - -#undef FRAME_PROBABILITY -#undef THEFT_PROBABILITY -#undef KILL_PROBABILITY -#undef PROTECT_PROBABILITY -#undef LENIENT -#undef NORMAL -#undef HARD +#define FRAME_PROBABILITY 3 +#define THEFT_PROBABILITY 55 +#define KILL_PROBABILITY 37 +#define PROTECT_PROBABILITY 5 + +#define LENIENT 0 +#define NORMAL 1 +#define HARD 2 +#define IMPOSSIBLE 3 + + +/proc/GenerateTheft(var/job,var/datum/mind/traitor) + var/list/datum/objective/objectives = list() + + for(var/o in subtypesof(/datum/objective/steal)) + var/datum/objective/target = new o(null,job) + objectives += target + objectives[target] = target.weight + return objectives + +/proc/GenerateAssassinate(var/job,var/datum/mind/traitor) + var/list/datum/objective/assassinate/missions = list() + + for(var/datum/mind/target in ticker.minds) + if((target != traitor) && istype(target.current, /mob/living/carbon/human)) + if(target && target.current) + var/datum/objective/target_obj = new /datum/objective/assassinate(null,job,target) + missions += target_obj + missions[target_obj] = target_obj.weight + return missions + +/proc/GenerateFrame(var/job,var/datum/mind/traitor) + var/list/datum/objective/frame/missions = list() + + for(var/datum/mind/target in ticker.minds) + if((target != traitor) && istype(target.current, /mob/living/carbon/human)) + if(target && target.current) + var/datum/objective/target_obj = new /datum/objective/frame(null,job,target) + missions += target_obj + missions[target_obj] = target_obj.weight + return missions + +/proc/GenerateProtection(var/job,var/datum/mind/traitor) + var/list/datum/objective/frame/missions = list() + + for(var/datum/mind/target in ticker.minds) + if((target != traitor) && istype(target.current, /mob/living/carbon/human)) + if(target && target.current) + var/datum/objective/target_obj = new /datum/objective/protection(null,job,target) + missions += target_obj + missions[target_obj] = target_obj.weight + return missions + + +/proc/SelectObjectives(var/job,var/datum/mind/traitor,var/hijack = 0) + var/list/chosenobjectives = list() + var/list/theftobjectives = GenerateTheft(job,traitor) //Separated all the objective types so they can be picked independantly of each other. + var/list/killobjectives = GenerateAssassinate(job,traitor) + var/list/frameobjectives = GenerateFrame(job,traitor) + var/list/protectobjectives = GenerateProtection(job,traitor) + var/total_weight + var/conflict + + var/steal_weight = THEFT_PROBABILITY + var/frame_weight = FRAME_PROBABILITY + var/kill_weight = KILL_PROBABILITY + var/protect_weight = PROTECT_PROBABILITY + var/target_weight = 50 + +///////////////////////////////////////////////////////////// +//HANDLE ASSIGNING OBJECTIVES BASED OFF OF PREVIOUS SUCCESS// +///////////////////////////////////////////////////////////// + + var/savefile/info = new("data/player_saves/[copytext(traitor.key, 1, 2)]/[traitor.key]/traitor.sav") + var/list/infos + info >> infos + if(istype(infos)) + var/total_attempts = infos["Total"] + var/total_overall_success = infos["Success"] + var/success_ratio = total_overall_success/total_attempts + var/steal_success = infos["Steal"] + var/kill_success = infos["Kill"] + var/frame_success = infos["Frame"] + var/protect_success = infos["Protect"] + + var/list/ordered_success = list(steal_success, kill_success, frame_success, protect_success) + + var/difficulty = pick(LENIENT, LENIENT, NORMAL, NORMAL, NORMAL, HARD, HARD, IMPOSSIBLE) + //Highest to lowest in terms of success rate, and resulting weight for later computation + var/success_weights = list(1, 1, 1, 1) + switch(difficulty) + if(LENIENT) + success_weights = list(1.5, 1, 0.75, 0.5) + target_weight = success_ratio*100 + if(NORMAL) + target_weight = success_ratio*150 + if(HARD) + success_weights = list(0.66, 0.8, 1, 1.25) + target_weight = success_ratio*200 + if(IMPOSSIBLE) //YOU SHALL NOT PASS + success_weights = list(0.5, 0.75, 1.2, 2) + target_weight = success_ratio*300 + + for(var/i = 1, i <= 4, i++) + //Iterate through the success rates, and determine the weights to chose based on the highest to + // the lowest to multiply it by the proper success ratio. + var/weight = max(ordered_success) + ordered_success -= weight + if(weight == steal_success) + steal_weight *= steal_success*success_weights[i] + else if(weight == frame_success) + frame_weight *= frame_success*success_weights[i] + else if(weight == protect_success) + protect_weight *= protect_success*success_weights[i] + else if(weight == kill_success) + kill_weight *= kill_success*success_weights[i] + + var/total_weights = kill_weight + protect_weight + frame_weight + steal_weight + frame_weight = round(frame_weight/total_weights) + kill_weight = round(kill_weight/total_weights) + steal_weight = round(steal_weight/total_weights) + //Protect is whatever is left over. + + var/steal_range = steal_weight + var/frame_range = frame_weight + steal_range + var/kill_range = kill_weight + frame_range + //Protect is whatever is left over. + + while(total_weight < target_weight) + var/selectobj = rand(1,100) //Randomly determine the type of objective to be given. + if(!length(killobjectives) || !length(protectobjectives)|| !length(frameobjectives)) //If any of these lists are empty, just give them theft objectives. + var/datum/objective/objective = pickweight(theftobjectives) + chosenobjectives += objective + total_weight += objective.points + theftobjectives -= objective + else switch(selectobj) + if(1 to steal_range) + if(!theftobjectives.len) + continue + var/datum/objective/objective = pickweight(theftobjectives) + for(1 to 10) + if(objective.points + total_weight <= 100 || !theftobjectives.len) + break + theftobjectives -= objective + objective = pickweight(theftobjectives) + if(!objective && !theftobjectives.len) + continue + chosenobjectives += objective + total_weight += objective.points + theftobjectives -= objective + if(steal_range + 1 to frame_range) //Framing Objectives (3% chance) + if(!frameobjectives.len) + continue + var/datum/objective/objective = pickweight(frameobjectives) + for(1 to 10) + if(objective.points + total_weight <= 100 || !frameobjectives.len) + break + frameobjectives -= objective + objective = pickweight(frameobjectives) + if(!objective && !frameobjectives.len) + continue + for(var/datum/objective/protection/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Assassinate somebody they need to Protect. + if(conflicttest.target == objective.target) + conflict = 1 + break + for(var/datum/objective/assassinate/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Protect somebody they need to Assassinate. + if(conflicttest.target == objective.target) + conflict = 1 + break + if(!conflict) + chosenobjectives += objective + total_weight += objective.points + frameobjectives -= objective + conflict = 0 + if(frame_range + 1 to kill_range) + if(!killobjectives.len) + continue + var/datum/objective/assassinate/objective = pickweight(killobjectives) + world << objective + for(1 to 10) + if(objective.points + total_weight <= 100 || !killobjectives.len) + break + killobjectives -= objective + objective = pickweight(killobjectives) + if(!objective && !killobjectives.len) + continue + for(var/datum/objective/protection/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Assassinate somebody they need to Protect. + if(conflicttest.target == objective.target) + conflict = 1 + break + for(var/datum/objective/frame/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Protect somebody they need to Assassinate. + if(conflicttest.target == objective.target) + conflict = 1 + break + if(!conflict) + chosenobjectives += objective + total_weight += objective.points + killobjectives -= objective + conflict = 0 + if(kill_range + 1 to 100) //Protection Objectives (5% chance) + if(!protectobjectives.len) + continue + var/datum/objective/protection/objective = pickweight(protectobjectives) + for(1 to 10) + if(objective.points + total_weight <= 100 || !protectobjectives.len) + break + protectobjectives -= objective + objective = pickweight(protectobjectives) + if(!objective || !protectobjectives.len) + continue + for(var/datum/objective/assassinate/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Protect somebody they need to Assassinate. + if(conflicttest.target == objective.target) + conflict = 1 + break + for(var/datum/objective/frame/conflicttest in chosenobjectives) //Check to make sure we aren't telling them to Protect somebody they need to Assassinate. + if(conflicttest.target == objective.target) + conflict = 1 + break + if(!conflict) + chosenobjectives += objective + total_weight += objective.points + protectobjectives -= objective + conflict = 0 + + if(!locate(/datum/objective/hijack) in chosenobjectives && !locate(/datum/objective/escape) in chosenobjectives) + if(hijack) + chosenobjectives += new /datum/objective/hijack(null,job) + else + chosenobjectives += new /datum/objective/escape(null,job) + return chosenobjectives + +datum + objective + var/datum/mind/owner + var/datum/mind/target + var/explanation_text = "text not set" + var/job + var/points = INFINITY //If this isn't set to something else, the objective is bugged and should be ignored + var/weight = INFINITY + + New(var/text,var/joba) + if(text) + src.explanation_text = text + job=joba + weight = get_weight(job) + points = get_points(job) + + proc/check_completion() + return 1 + proc/get_points(var/job) + return INFINITY + proc/get_weight(var/job) + return INFINITY + proc/find_target_by_role(role, role_type=0)//Option sets either to check assigned role or special role. Default to assigned. + for(var/datum/mind/possible_target in ticker.minds) + if((possible_target != owner) && ishuman(possible_target.current) && ((role_type ? possible_target.special_role : possible_target.assigned_role) == role) ) + target = possible_target + break + + + frame + New(var/text,var/joba,var/datum/mind/targeta) + target = targeta + job = joba + weight = get_points(job) + explanation_text = "Frame [target.current.real_name], the [target.assigned_role] for a crime and make sure they are arrested and brought back to the Centcom station alive. We'll handle the rest from there." + + check_completion() + if(!emergency_shuttle.returned()) + return 0 + if(target.current.stat == 2) + return 0 + var/turf/location = get_turf(target.current.loc) + if(!location) + return 0 + if(!target.current:handcuffed && !istype(location, /turf/simulated/shuttle/floor4)) + return 0 + + if(location in locate(/area/shuttle/escape/centcom)) + return 1 + + return 0 + + get_points() + if(target) + var/difficulty = GetRank(target.assigned_role) + 1 + switch(GetRank(job)) + if(4) + return 20*difficulty + if(3) + return 30*difficulty + if(2) + return 40*difficulty + if(1) + return 55*difficulty + if(0) + return 60*difficulty + else + return INFINITY + + get_weight() + if(target) + return 1 + return 0 + + + protection + New(var/text,var/joba,var/datum/mind/targeta) + target = targeta + job = joba + weight = get_points(job) + explanation_text = "[target.current.real_name], the [target.assigned_role] is a [pick("relative of a","friend of a","") + pick("high ranking","important","well-liked")] Syndicate [pick("Leader","Officer","Agent","sympathiser")]. Make sure they get off the station safely, while minimizing intervention." + + check_completion() + if(!emergency_shuttle.returned()) + return 0 + + if(target.current.stat == 2) + return 0 + + var/turf/location = get_turf(target.current.loc) + if(!location) + return 0 + + if(location in locate(/area/shuttle/escape/centcom)) + return 1 + + return 0 + + get_points() + if(target) + return 30 + else + return INFINITY + + get_weight() + if(target) + return 1 + return 0 + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Protect [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)]." + else + explanation_text = "Free Objective" + return target + + + assassinate + + New(var/text,var/joba,var/datum/mind/targeta) + target = targeta + job = joba + weight = get_points(job) + explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role]." + + check_completion() + if(target && target.current) + if(target.current.stat == 2 || istype(get_area(target.current), /area/tdome) || issilicon(target.current) || isbrain(target.current)) + return 1 + else + return 0 + else + return 1 + get_points() + if(target) + var/difficulty = GetRank(target.assigned_role) + 1 + switch(GetRank(job)) + if(4) + return 20*difficulty + if(3) + return 30*difficulty + if(2) + return 40*difficulty + if(1) + return 55*difficulty + if(0) + return 60*difficulty + else + return 0 + + get_weight() + if(target) + return 1 + return 0 + + find_target_by_role(var/role) + for(var/datum/mind/possible_target in ticker.minds) + if((possible_target != owner) && istype(possible_target.current, /mob/living/carbon/human) && (possible_target.assigned_role == role)) + target = possible_target + break + + if(target && target.current) + explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role]." + else + explanation_text = "Free Objective" + + return target + + + proc/find_target() + var/list/possible_targets = list() + + for(var/datum/mind/possible_target in ticker.minds) + if((possible_target != owner) && istype(possible_target.current, /mob/living/carbon/human)) + possible_targets += possible_target + + if(possible_targets.len > 0) + target = pick(possible_targets) + + if(target && target.current) + explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role]." + else + explanation_text = "Free Objective" + + return target + + + capture + var/separation_time = 0 + var/almost_complete = 0 + + New(var/text,var/joba,var/datum/mind/targeta) + target = targeta + job = joba + explanation_text = "Capture [target.current.real_name], the [target.assigned_role]." + + check_completion() + if(target && target.current) + if(target.current.stat == 2) + if(config.require_heads_alive) return 0 + else + if(!target.current.handcuffed) + return 0 + else if(config.require_heads_alive) return 0 + return 1 + + find_target_by_role(var/role) + for(var/datum/mind/possible_target in ticker.minds) + if((possible_target != owner) && istype(possible_target.current, /mob/living/carbon/human) && (possible_target.assigned_role == role)) + target = possible_target + break + + if(target && target.current) + explanation_text = "Capture [target.current.real_name], the [target.assigned_role]." + else + explanation_text = "Free Objective" + + return target + + get_points() + if(target) + var/difficulty = GetRank(target.assigned_role) + 1 + switch(GetRank(job)) + if(4) + return 20*difficulty + if(3) + return 30*difficulty + if(2) + return 40*difficulty + if(1) + return 55*difficulty + if(0) + return 60*difficulty + else + return INFINITY + + get_weight() + if(target) + return 1 + return 0 + + + hijack + explanation_text = "Hijack the emergency shuttle by escaping alone." + + check_completion() + if(!emergency_shuttle.returned()) + return 0 + + if(!owner.current || owner.current.stat == 2) + return 0 + var/turf/location = get_turf(owner.current.loc) + + if(location in locate(/area/shuttle/escape/centcom)) + for(var/mob/living/player in locate(/area/shuttle/escape/centcom)) + if (player.mind && (player.mind != owner)) + if (player.stat != 2) //they're not dead + return 0 + return 1 + + return 0 + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 65 + if(2) + return 65 + if(3) + return 50 + if(4) + return 35 + + get_weight(var/job) + return 1 + + escape + explanation_text = "Escape on the shuttle alive, without being arrested." + + check_completion() + if(!emergency_shuttle.returned()) + return 0 + + if(!owner.current || owner.current.stat ==2) + return 0 + + var/turf/location = get_turf(owner.current.loc) + if(!location) + return 0 + + if(owner.current:handcuffed || istype(location, /turf/simulated/shuttle/floor4)) + return 0 + + if(location in locate(/area/shuttle/escape/centcom)) + return 1 + + return 0 + get_points() + return INFINITY + + get_weight(var/job) + return 1 + + + survive + explanation_text = "Stay alive." + + check_completion() + if(!owner.current || owner.current.stat == 2) + return 0 + + return 1 + get_points() + return INFINITY + + get_weight(var/job) + return 1 + + + steal + var/obj/item/steal_target + + check_completion() + if(steal_target) + if(owner.current.check_contents_for(steal_target)) + return 1 + else + return 0 + + + captainslaser + steal_target = /obj/item/weapon/gun/energy/laser/captain + explanation_text = "Steal the captain's antique laser gun." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 60 + if(1) + return 50 + if(2) + return 40 + if(3) + return 30 + if(4) + return 20 + + get_weight(var/job) + if(GetRank(job) == 4) + return 10 + else + return 20 + + + plasmatank + steal_target = /obj/item/weapon/tank/plasma + explanation_text = "Steal a small plasma tank." + weight = 20 + + get_points(var/job) + if(job in science_positions || job in command_positions) + return 20 + return 40 + + get_weight(var/job) + return 20 + + check_completion() + var/list/all_items = owner.current.get_contents() + for(var/obj/item/I in all_items) + if(!istype(I, steal_target)) continue//If it's not actually that item. + if(I:air_contents:toxins) return 1 //If they got one with plasma + return 0 + + + /*Removing this as an objective. Not necessary to have two theft objectives in the same room. + steal/captainssuit + steal_target = /obj/item/clothing/under/rank/captain + explanation_text = "Steal a captain's rank jumpsuit" + weight = 50 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return INFINITY + */ + + + handtele + steal_target = /obj/item/weapon/hand_tele + explanation_text = "Steal a hand teleporter." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return 20 + + get_weight(var/job) + if(GetRank(job) == 4) + return 10 + else + return 20 + + + RCD + steal_target = /obj/item/weapon/rcd + explanation_text = "Steal a rapid construction device." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return 20 + + get_weight(var/job) + if(GetRank(job) == 4) + return 10 + else + return 20 + + + /*burger + steal_target = /obj/item/weapon/reagent_containers/food/snacks/human/burger + explanation_text = "Steal a burger made out of human organs, this will be presented as proof of Nanotrasen's chronic lack of standards." + weight = 60 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 80 + if(1) + return 65 + if(2) + return 55 + if(3) + return 40 + if(4) + return 25*/ + + + jetpack + steal_target = /obj/item/weapon/tank/jetpack/oxygen + explanation_text = "Steal a blue oxygen jetpack." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return 20 + + get_weight(var/job) + if(GetRank(job) == 4) + return 10 + else + return 20 + + + /*magboots + steal_target = /obj/item/clothing/shoes/magboots + explanation_text = "Steal a pair of \"Nanotrasen\" brand magboots." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return 20 + + get_weight(var/job) + if(GetRank(job) == 4) + return 10 + else + return 20*/ + + + blueprints + steal_target = /obj/item/blueprints + explanation_text = "Steal the station's blueprints." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return 20 + + get_weight(var/job) + if(GetRank(job) == 4) + return 10 + else + return 20 + + + voidsuit + steal_target = /obj/item/clothing/suit/space/nasavoid + explanation_text = "Steal a voidsuit." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return 20 + + get_weight(var/job) + return 20 + + + nuke_disk + steal_target = /obj/item/weapon/disk/nuclear + explanation_text = "Steal the station's nuclear authentication disk." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 90 + if(1) + return 80 + if(2) + return 70 + if(3) + return 40 + if(4) + return 25 + + get_weight(var/job) + if(GetRank(job) == 4) + return 10 + else + return 20 + + nuke_gun + steal_target = /obj/item/weapon/gun/energy/gun/nuclear + explanation_text = "Steal a nuclear powered gun." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 90 + if(1) + return 85 + if(2) + return 80 + if(3) + return 75 + if(4) + return 75 + + get_weight(var/job) + return 2 + + diamond_drill + steal_target = /obj/item/weapon/pickaxe/drill/diamonddrill + explanation_text = "Steal a diamond drill." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 90 + if(1) + return 85 + if(2) + return 70 + if(3) + return 75 + if(4) + return 75 + + get_weight(var/job) + return 2 + + boh + steal_target = /obj/item/weapon/storage/backpack/holding + explanation_text = "Steal a \"bag of holding.\"" + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 90 + if(1) + return 85 + if(2) + return 80 + if(3) + return 75 + if(4) + return 75 + + get_weight(var/job) + return 2 + + hyper_cell + steal_target = /obj/item/weapon/stock_parts/cell/hyper + explanation_text = "Steal a hyper capacity power cell." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 90 + if(1) + return 85 + if(2) + return 80 + if(3) + return 75 + if(4) + return 75 + + get_weight(var/job) + return 2 + + lucy + steal_target = /obj/item/stack/sheet/diamond + explanation_text = "Steal 10 diamonds." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 90 + if(1) + return 85 + if(2) + return 80 + if(3) + return 75 + if(4) + return 75 + + get_weight(var/job) + return 2 + + check_completion() + var/target_amount = 10 + var/found_amount = 0.0//Always starts as zero. + for(var/obj/item/I in owner.current.get_contents()) + if(!istype(I, steal_target)) continue//If it's not actually that item. + found_amount += I:amount + return found_amount>=target_amount + + gold + steal_target = /obj/item/stack/sheet/gold + explanation_text = "Steal 50 gold bars." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 90 + if(1) + return 85 + if(2) + return 80 + if(3) + return 75 + if(4) + return 70 + + get_weight(var/job) + return 2 + + check_completion() + var/target_amount = 50 + var/found_amount = 0.0//Always starts as zero. + for(var/obj/item/I in owner.current.get_contents()) + if(!istype(I, steal_target)) continue//If it's not actually that item. + found_amount += I:amount + return found_amount>=target_amount + + uranium + steal_target = /obj/item/stack/sheet/uranium + explanation_text = "Steal 25 uranium bars." + weight = 20 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 90 + if(1) + return 85 + if(2) + return 80 + if(3) + return 75 + if(4) + return 70 + + get_weight(var/job) + return 2 + + check_completion() + var/target_amount = 25 + var/found_amount = 0.0//Always starts as zero. + for(var/obj/item/I in owner.current.get_contents()) + if(!istype(I, steal_target)) continue//If it's not actually that item. + found_amount += I:amount + return found_amount>=target_amount + + + /*Needs some work before it can be put in the game to differentiate ship implanters from syndicate implanters. + steal/implanter + steal_target = /obj/item/weapon/implanter + explanation_text = "Steal an implanter" + weight = 50 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return INFINITY + */ + cyborg + steal_target = /obj/item/robot_parts/robot_suit + explanation_text = "Steal a completed robot shell (no brain)" + weight = 30 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return 20 + + check_completion() + if(steal_target) + for(var/obj/item/robot_parts/robot_suit/objective in owner.current.get_contents()) + if(istype(objective,/obj/item/robot_parts/robot_suit) && objective.check_completion()) + return 1 + return 0 + + get_weight(var/job) + return 20 + AI + steal_target = /obj/structure/AIcore + explanation_text = "Steal a finished AI, either by intellicard or stealing the whole construct." + weight = 50 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return 20 + + get_weight(var/job) + return 15 + + check_completion() + if(steal_target) + for(var/obj/item/device/aicard/C in owner.current.get_contents()) + for(var/mob/living/silicon/ai/M in C) + if(istype(M, /mob/living/silicon/ai) && M.stat != 2) + return 1 + for(var/mob/living/silicon/ai/M in world) + if(istype(M.loc, /turf)) + if(istype(get_area(M), /area/shuttle/escape)) + return 1 + for(var/obj/structure/AIcore/M in world) + if(istype(M.loc, /turf) && M.state == 4) + if(istype(get_area(M), /area/shuttle/escape)) + return 1 + return 0 + + drugs + steal_target = /datum/reagent/space_drugs + explanation_text = "Steal some space drugs." + weight = 40 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return 20 + + check_completion() + if(steal_target) + if(owner.current.check_contents_for_reagent(steal_target)) + return 1 + else + return 0 + + get_weight(var/job) + return 20 + + + pacid + steal_target = /datum/reagent/pacid + explanation_text = "Steal some polytrinic acid." + weight = 40 + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return 20 + + check_completion() + if(steal_target) + if(owner.current.check_contents_for_reagent(steal_target)) + return 1 + else + return 0 + + get_weight(var/job) + return 20 + + + reagent + weight = 20 + var/target_name + New(var/text,var/joba) + ..() + var/list/items = list("Sulphuric acid", "Polytrinic acid", "Space Lube", "Unstable mutagen",\ + "Leporazine", "Cryptobiolin", "Lexorin ",\ + "Kelotane", "Dexalin", "Tricordrazine") + target_name = pick(items) + switch(target_name) + if("Sulphuric acid") + steal_target = /datum/reagent/acid + if("Polytrinic acid") + steal_target = /datum/reagent/pacid + if("Space Lube") + steal_target = /datum/reagent/lube + if("Unstable mutagen") + steal_target = /datum/reagent/mutagen + if("Leporazine") + steal_target = /datum/reagent/leporazine + if("Cryptobiolin") + steal_target =/datum/reagent/cryptobiolin + if("Lexorin") + steal_target = /datum/reagent/lexorin + if("Kelotane") + steal_target = /datum/reagent/kelotane + if("Dexalin") + steal_target = /datum/reagent/dexalin + if("Tricordrazine") + steal_target = /datum/reagent/tricordrazine + + explanation_text = "Steal a container filled with [target_name]." + + get_points(var/job) + switch(GetRank(job)) + if(0) + return 75 + if(1) + return 60 + if(2) + return 50 + if(3) + return 30 + if(4) + return 20 + + check_completion() + if(steal_target) + if(owner.current.check_contents_for_reagent(steal_target)) + return 1 + else + return 0 + + get_weight(var/job) + return 20 + + cash //must be in credits - atm and coins don't count + var/steal_amount = 2000 + explanation_text = "Beg, borrow or steal 2000 credits." + weight = 20 + + New(var/text,var/joba) + ..(text,joba) + steal_amount = 1250 + rand(0,3750) + explanation_text = "Beg, borrow or steal [steal_amount] credits." + + get_points(var/job) + return 10 + 25 * round(steal_amount / 5000) + + check_completion() + var/held_credits = 0 + for(var/obj/item/weapon/spacecash/M in owner.current.get_contents()) + held_credits += M.get_total() + if(held_credits >= steal_amount) + return 1 + return 0 + + get_weight(var/job) + return 20 + + + nuclear + explanation_text = "Destroy the station with a nuclear device." + + + block + explanation_text = "Do not allow any humans to escape on the shuttle alive." + + + check_completion() + if(!istype(owner.current, /mob/living/silicon)) + return 0 + if(!emergency_shuttle.returned()) + return 0 + if(!owner.current) + return 0 + var/area/shuttle = locate(/area/shuttle/escape/centcom) + var/protected_mobs[] = list(/mob/living/silicon/ai, /mob/living/silicon/pai, /mob/living/silicon/robot) + for(var/mob/living/player in world) + if(player.type in protected_mobs) continue + if (player.mind) + if (player.stat != 2) + if (get_turf(player) in shuttle) + return 0 + return 1 + + decapitate + New(var/text,var/joba,var/datum/mind/targeta) + target = targeta + job = joba + explanation_text = "Remove and recover the head of [target.current.real_name], the [target.assigned_role]." + proc/find_target() + ..() + if(target && target.current) + explanation_text = "[target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role], has defied us for the last time. Make an example of him, and bring us his severed head." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "[target.current.real_name], the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)], has defied us for the last time. Make an example of him, and bring us his severed head." + else + explanation_text = "Free Objective" + return target + + + check_completion() + if(target && target.current) + if(!owner.current||owner.current.stat==2)//If you're otherwise dead. + return 0 + var/list/all_items = owner.current.get_contents() + for(var/obj/item/weapon/organ/head/mmi in all_items) + if(mmi.brainmob&&mmi.brainmob.mind==target) + return 1 + return 0 + else + return 1 + + absorb + var/target_amount + proc/gen_amount_goal(var/lowbound = 4, var/highbound = 6) + target_amount = rand (lowbound,highbound) + if (ticker) + var/n_p = 1 //autowin + if (ticker.current_state == GAME_STATE_SETTING_UP) + for(var/mob/new_player/P in world) + if(P.client && P.ready && P.mind!=owner) + n_p ++ + else if (ticker.current_state == GAME_STATE_PLAYING) + for(var/mob/living/carbon/human/P in world) + if(P.client && !(P.mind in ticker.mode.changelings) && P.mind!=owner) + n_p ++ + target_amount = min(target_amount, n_p) + + explanation_text = "Absorb [target_amount] compatible genomes." + return target_amount + + check_completion() + if(owner && owner.current && owner.current.changeling && owner.current.changeling.absorbed_dna && ((owner.current.changeling.absorbed_dna.len - 1) >= target_amount)) + return 1 + else + return 0 + + meme_attune + var/target_amount + proc/gen_amount_goal(var/lowbound = 4, var/highbound = 6) + target_amount = rand (lowbound,highbound) + + explanation_text = "Attune [target_amount] humanoid brains." + return target_amount + + check_completion() + if(owner && owner.current && istype(owner.current,/mob/living/parasite/meme) && (owner.current:indoctrinated.len >= target_amount)) + return 1 + else + return 0 + + download + var/target_amount + proc/gen_amount_goal() + target_amount = rand(10,20) + explanation_text = "Download [target_amount] research levels." + return target_amount + + + check_completion() + return 0 + + + debrain//I want braaaainssss + New(var/text,var/joba,var/datum/mind/targeta) + target = targeta + job = joba + explanation_text = "Remove and recover the brain of [target.current.real_name], the [target.assigned_role]." + + proc/find_target() + ..() + if(target && target.current) + explanation_text = "Steal the brain of [target.current.real_name]." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Steal the brain of [target.current.real_name] the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)]." + else + explanation_text = "Free Objective" + return target + + + check_completion() + if(!target)//If it's a free objective. + return 1 + if(!owner.current||owner.current.stat==2)//If you're otherwise dead. + return 0 + var/list/all_items = owner.current.get_contents() + for(var/obj/item/device/mmi/mmi in all_items) + if(mmi.brainmob&&mmi.brainmob.mind==target) return 1 + for(var/obj/item/brain/brain in all_items) + if(brain.brainmob&&brain.brainmob.mind==target) return 1 + return 0 + + mutiny + proc/find_target() + ..() + if(target && target.current) + explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : target.assigned_role]." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Assassinate [target.current.real_name], the [target.role_alt_title ? target.role_alt_title : (!role_type ? target.assigned_role : target.special_role)]." + else + explanation_text = "Free Objective" + return target + + + check_completion() + if(target && target.current) + var/turf/T = get_turf(target.current) + if(target.current.stat == 2) + return 1 + else if((T) && !(T.z in config.station_levels))//If they leave the station they count as dead for this + return 2 + else + return 0 + else + return 1 + + capture + var/target_amount + proc/gen_amount_goal() + target_amount = rand(5,10) + explanation_text = "Accumulate [target_amount] capture points." + return target_amount + + + check_completion()//Basically runs through all the mobs in the area to determine how much they are worth. + return 0 + +datum/objective/silence + explanation_text = "Do not allow anyone to escape the station. Only allow the shuttle to be called when everyone is dead and your story is the only one left." + + check_completion() + if(!emergency_shuttle.returned()) + return 0 + + var/area/shuttle = locate(/area/shuttle/escape/centcom) + var/area/pod1 = locate(/area/shuttle/escape_pod1/centcom) + var/area/pod2 = locate(/area/shuttle/escape_pod2/centcom) + var/area/pod3 = locate(/area/shuttle/escape_pod3/centcom) + var/area/pod4 = locate(/area/shuttle/escape_pod5/centcom) + + for(var/mob/living/player in world) + if (player == owner.current) + continue + if (player.mind) + if (player.stat != 2) + if (get_turf(player) in shuttle) + return 0 + if (get_turf(player) in pod1) + return 0 + if (get_turf(player) in pod2) + return 0 + if (get_turf(player) in pod3) + return 0 + if (get_turf(player) in pod4) + return 0 + return 1 + +#undef FRAME_PROBABILITY +#undef THEFT_PROBABILITY +#undef KILL_PROBABILITY +#undef PROTECT_PROBABILITY +#undef LENIENT +#undef NORMAL +#undef HARD #undef IMPOSSIBLE \ No newline at end of file diff --git a/code/game/gamemodes/scoreboard.dm b/code/game/gamemodes/scoreboard.dm index 56f37477b76..faba9e82572 100644 --- a/code/game/gamemodes/scoreboard.dm +++ b/code/game/gamemodes/scoreboard.dm @@ -1,239 +1,247 @@ -/datum/controller/gameticker/proc/scoreboard() - - //Print a list of antagonists to the server log - var/list/total_antagonists = list() - //Look into all mobs in world, dead or alive - for(var/datum/mind/Mind in minds) - var/temprole = Mind.special_role - if(temprole) //if they are an antagonist of some sort. - if(temprole in total_antagonists) //If the role exists already, add the name to it - total_antagonists[temprole] += ", [Mind.name]([Mind.key])" - else - total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob - total_antagonists[temprole] += ": [Mind.name]([Mind.key])" - - //Now print them all into the log! - log_game("Antagonists at round end were...") - for(var/i in total_antagonists) - log_game("[i]s[total_antagonists[i]].") - - // Score Calculation and Display - - // Who is alive/dead, who escaped - for(var/mob/living/silicon/ai/I in mob_list) - if(I.stat == DEAD && (I.z in config.station_levels)) - score_deadaipenalty++ - score_deadcrew++ - - for(var/mob/living/carbon/human/I in mob_list) - if(I.stat == DEAD && (I.z in config.station_levels)) - score_deadcrew++ - - if(I && I.mind) - if(I.mind.assigned_role == "Clown") - for(var/thing in I.attack_log) - if(findtext(thing, "")) //This has to be the hackiest fucking way _ever_ to see attacks. - score_clownabuse++ - - - for(var/mob/living/player in mob_list) - if(player.client) - if (player.stat != DEAD) - var/turf/location = get_turf(player.loc) - var/area/escape_zone = locate(/area/shuttle/escape/centcom) - if(location in escape_zone) - score_escapees++ - - - - var/cash_score = 0 - var/dmg_score = 0 - for(var/mob/living/carbon/human/E in mob_list) - cash_score = 0 - dmg_score = 0 - var/turf/location = get_turf(E.loc) - var/area/escape_zone = locate(/area/shuttle/escape/centcom) - - if(E.stat != DEAD && location in escape_zone) // Escapee Scores - for(var/obj/item/weapon/card/id/C1 in E.contents) - cash_score += C1.money - for(var/obj/item/weapon/spacecash/C2 in E.contents) - cash_score += C2.worth - for(var/obj/item/weapon/storage/S in E.contents) - for(var/obj/item/weapon/card/id/C3 in S.contents) - cash_score += C3.money - for(var/obj/item/weapon/spacecash/C4 in S.contents) - cash_score += C4.worth - - if(cash_score > score_richestcash) - score_richestcash = cash_score - score_richestname = E.real_name - score_richestjob = E.job - score_richestkey = E.key - - dmg_score = E.bruteloss + E.fireloss + E.toxloss + E.oxyloss - if(dmg_score > score_dmgestdamage) - score_dmgestdamage = dmg_score - score_dmgestname = E.real_name - score_dmgestjob = E.job - score_dmgestkey = E.key - - if(ticker && ticker.mode) - ticker.mode.set_scoreboard_gvars() - - - // Check station's power levels - for(var/obj/machinery/power/apc/A in machines) - if(!(A.z in config.station_levels)) continue - - for(var/obj/item/weapon/stock_parts/cell/C in A.contents) - if(C.charge < 2300) - score_powerloss++ //200 charge leeway - - - // Check how much uncleaned mess is on the station - for(var/obj/effect/decal/cleanable/M in world) - if(!(M.z in config.station_levels)) continue - if(istype(M, /obj/effect/decal/cleanable/blood/gibs)) - score_mess += 3 - - if(istype(M, /obj/effect/decal/cleanable/blood)) - score_mess += 1 - - if(istype(M, /obj/effect/decal/cleanable/poop)) - score_mess += 1 - - if(istype(M, /obj/effect/decal/cleanable/vomit)) - score_mess += 1 - - - // Bonus Modifiers - //var/traitorwins = score_traitorswon - var/deathpoints = score_deadcrew * 25 //done - var/researchpoints = score_researchdone * 30 - var/eventpoints = score_eventsendured * 50 - var/escapoints = score_escapees * 25 //done - var/harvests = score_stuffharvested * 5 //done - var/shipping = score_stuffshipped * 5 - var/mining = score_oremined * 2 //done - var/meals = score_meals * 5 //done, but this only counts cooked meals, not drinks served - var/power = score_powerloss * 20 - var/messpoints - if(score_mess != 0) - messpoints = score_mess //done - var/plaguepoints = score_disease * 30 - - - // Good Things - score_crewscore += shipping - score_crewscore += harvests - score_crewscore += mining - score_crewscore += researchpoints - score_crewscore += eventpoints - score_crewscore += escapoints - - if(power == 0) - score_crewscore += 2500 - score_powerbonus = 1 - - if(score_mess == 0) - score_crewscore += 3000 - score_messbonus = 1 - - - score_crewscore += meals - if(score_allarrested) - score_crewscore *= 3 // This needs to be here for the bonus to be applied properly - - - score_crewscore -= deathpoints - if(score_deadaipenalty) - score_crewscore -= 250 - score_crewscore -= power - - - score_crewscore -= messpoints - score_crewscore -= plaguepoints - - // Show the score - might add "ranks" later - world << "The crew's final score is:" - world << "[score_crewscore]" - for(var/mob/E in player_list) - if(E.client) - if(E.client.prefs && !(E.client.prefs.toggles & DISABLE_SCOREBOARD)) - E.scorestats() - - -/datum/game_mode/proc/get_scoreboard_stats() - return null - -/datum/game_mode/proc/set_scoreboard_gvars() - return null - -/mob/proc/scorestats() - var/dat = "Round Statistics and Score

" - if(ticker && ticker.mode) - dat += ticker.mode.get_scoreboard_stats() - - dat += {" - General Statistics
- The Good:
- - Useful Items Shipped: [score_stuffshipped] ([score_stuffshipped * 5] Points)
- Hydroponics Harvests: [score_stuffharvested] ([score_stuffharvested * 5] Points)
- Ore Mined: [score_oremined] ([score_oremined * 2] Points)
- Refreshments Prepared: [score_meals] ([score_meals * 5] Points)
- Research Completed: [score_researchdone] ([score_researchdone * 30] Points)
"} - if (!emergency_shuttle.location()) dat += "Shuttle Escapees: [score_escapees] ([score_escapees * 25] Points)
" - dat += {"Random Events Endured: [score_eventsendured] ([score_eventsendured * 50] Points)
- Whole Station Powered: [score_powerbonus ? "Yes" : "No"] ([score_powerbonus * 2500] Points)
- Ultra-Clean Station: [score_mess ? "No" : "Yes"] ([score_messbonus * 3000] Points)

- The bad:
- - Dead bodies on Station: [score_deadcrew] (-[score_deadcrew * 25] Points)
- Uncleaned Messes: [score_mess] (-[score_mess] Points)
- Station Power Issues: [score_powerloss] (-[score_powerloss * 20] Points)
- Rampant Diseases: [score_disease] (-[score_disease * 30] Points)
- AI Destroyed: [score_deadaipenalty ? "Yes" : "No"] (-[score_deadaipenalty * 250] Points)

- The Weird
- - Food Eaten: [score_foodeaten]
- Times a Clown was Abused: [score_clownabuse]

- "} - if (score_escapees) - dat += {"Richest Escapee: [score_richestname], [score_richestjob]: $[num2text(score_richestcash,50)] ([score_richestkey])
- Most Battered Escapee: [score_dmgestname], [score_dmgestjob]: [score_dmgestdamage] damage ([score_dmgestkey])
"} - else - if(emergency_shuttle.location()) - dat += "The station wasn't evacuated!
" - else - dat += "No-one escaped!
" - - dat += ticker.mode.declare_job_completion() - - dat += {" -

- FINAL SCORE: [score_crewscore]
- "} - - var/score_rating = "The Aristocrats!" - switch(score_crewscore) - if(-99999 to -50000) score_rating = "Even the Singularity Deserves Better" - if(-49999 to -5000) score_rating = "Singularity Fodder" - if(-4999 to -1000) score_rating = "You're All Fired" - if(-999 to -500) score_rating = "A Waste of Perfectly Good Oxygen" - if(-499 to -250) score_rating = "A Wretched Heap of Scum and Incompetence" - if(-249 to -100) score_rating = "Outclassed by Lab Monkeys" - if(-99 to -21) score_rating = "The Undesirables" - if(-20 to 20) score_rating = "Ambivalently Average" - if(21 to 99) score_rating = "Not Bad, but Not Good" - if(100 to 249) score_rating = "Skillful Servants of Science" - if(250 to 499) score_rating = "Best of a Good Bunch" - if(500 to 999) score_rating = "Lean Mean Machine Thirteen" - if(1000 to 4999) score_rating = "Promotions for Everyone" - if(5000 to 9999) score_rating = "Ambassadors of Discovery" - if(10000 to 49999) score_rating = "The Pride of Science Itself" - if(50000 to INFINITY) score_rating = "Nanotrasen's Finest" - - dat += "RATING: [score_rating]" +/datum/controller/gameticker/proc/scoreboard() + + //Print a list of antagonists to the server log + var/list/total_antagonists = list() + //Look into all mobs in world, dead or alive + for(var/datum/mind/Mind in minds) + var/temprole = Mind.special_role + if(temprole) //if they are an antagonist of some sort. + if(temprole in total_antagonists) //If the role exists already, add the name to it + total_antagonists[temprole] += ", [Mind.name]([Mind.key])" + else + total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob + total_antagonists[temprole] += ": [Mind.name]([Mind.key])" + + //Now print them all into the log! + log_game("Antagonists at round end were...") + for(var/i in total_antagonists) + log_game("[i]s[total_antagonists[i]].") + + // Score Calculation and Display + + // Who is alive/dead, who escaped + for(var/mob/living/silicon/ai/I in mob_list) + if(I.stat == DEAD && (I.z in config.station_levels)) + score_deadaipenalty++ + score_deadcrew++ + + for(var/mob/living/carbon/human/I in mob_list) + if(I.stat == DEAD && (I.z in config.station_levels)) + score_deadcrew++ + + if(I && I.mind) + if(I.mind.assigned_role == "Clown") + for(var/thing in I.attack_log) + if(findtext(thing, "")) //This has to be the hackiest fucking way _ever_ to see attacks. + score_clownabuse++ + + + for(var/mob/living/player in mob_list) + if(player.client) + if (player.stat != DEAD) + var/turf/location = get_turf(player.loc) + var/area/escape_zone = locate(/area/shuttle/escape/centcom) + if(location in escape_zone) + score_escapees++ + + + + var/cash_score = 0 + var/dmg_score = 0 + for(var/mob/living/carbon/human/E in mob_list) + cash_score = 0 + dmg_score = 0 + var/turf/location = get_turf(E.loc) + var/area/escape_zone = locate(/area/shuttle/escape/centcom) + + if(E.stat != DEAD && location in escape_zone) // Escapee Scores + cash_score = get_score_container_worth(E) + + if(cash_score > score_richestcash) + score_richestcash = cash_score + score_richestname = E.real_name + score_richestjob = E.job + score_richestkey = E.key + + dmg_score = E.bruteloss + E.fireloss + E.toxloss + E.oxyloss + if(dmg_score > score_dmgestdamage) + score_dmgestdamage = dmg_score + score_dmgestname = E.real_name + score_dmgestjob = E.job + score_dmgestkey = E.key + + if(ticker && ticker.mode) + ticker.mode.set_scoreboard_gvars() + + + // Check station's power levels + for(var/obj/machinery/power/apc/A in machines) + if(!(A.z in config.station_levels)) continue + + for(var/obj/item/weapon/stock_parts/cell/C in A.contents) + if(C.charge < 2300) + score_powerloss++ //200 charge leeway + + + // Check how much uncleaned mess is on the station + for(var/obj/effect/decal/cleanable/M in world) + if(!(M.z in config.station_levels)) continue + if(istype(M, /obj/effect/decal/cleanable/blood/gibs)) + score_mess += 3 + + if(istype(M, /obj/effect/decal/cleanable/blood)) + score_mess += 1 + + if(istype(M, /obj/effect/decal/cleanable/poop)) + score_mess += 1 + + if(istype(M, /obj/effect/decal/cleanable/vomit)) + score_mess += 1 + + + // Bonus Modifiers + //var/traitorwins = score_traitorswon + var/deathpoints = score_deadcrew * 25 //done + var/researchpoints = score_researchdone * 30 + var/eventpoints = score_eventsendured * 50 + var/escapoints = score_escapees * 25 //done + var/harvests = score_stuffharvested * 5 //done + var/shipping = score_stuffshipped * 5 + var/mining = score_oremined * 2 //done + var/meals = score_meals * 5 //done, but this only counts cooked meals, not drinks served + var/power = score_powerloss * 20 + var/messpoints + if(score_mess != 0) + messpoints = score_mess //done + var/plaguepoints = score_disease * 30 + + + // Good Things + score_crewscore += shipping + score_crewscore += harvests + score_crewscore += mining + score_crewscore += researchpoints + score_crewscore += eventpoints + score_crewscore += escapoints + + if(power == 0) + score_crewscore += 2500 + score_powerbonus = 1 + + if(score_mess == 0) + score_crewscore += 3000 + score_messbonus = 1 + + + score_crewscore += meals + if(score_allarrested) + score_crewscore *= 3 // This needs to be here for the bonus to be applied properly + + + score_crewscore -= deathpoints + if(score_deadaipenalty) + score_crewscore -= 250 + score_crewscore -= power + + + score_crewscore -= messpoints + score_crewscore -= plaguepoints + + // Show the score - might add "ranks" later + world << "The crew's final score is:" + world << "[score_crewscore]" + for(var/mob/E in player_list) + if(E.client) + if(E.client.prefs && !(E.client.prefs.toggles & DISABLE_SCOREBOARD)) + E.scorestats() + +// A recursive function to properly determine the wealthiest escapee +/datum/controller/gameticker/proc/get_score_container_worth(atom/C, level=0) + if(level >= 5) + // in case the containers recurse or something + return 0 + else + . = 0 + for(var/obj/item/weapon/card/id/id in C.contents) + var/datum/money_account/A = get_money_account(id.associated_account_number) + // has an account? + if(A) + . += A.money + for(var/obj/item/weapon/spacecash/cash in C.contents) + . += cash.get_total() + for(var/obj/item/weapon/storage/S in C.contents) + . += .(S, level + 1) + +/datum/game_mode/proc/get_scoreboard_stats() + return null + +/datum/game_mode/proc/set_scoreboard_gvars() + return null + +/mob/proc/scorestats() + var/dat = "Round Statistics and Score

" + if(ticker && ticker.mode) + dat += ticker.mode.get_scoreboard_stats() + + dat += {" + General Statistics
+ The Good:
+ + Useful Items Shipped: [score_stuffshipped] ([score_stuffshipped * 5] Points)
+ Hydroponics Harvests: [score_stuffharvested] ([score_stuffharvested * 5] Points)
+ Ore Mined: [score_oremined] ([score_oremined * 2] Points)
+ Refreshments Prepared: [score_meals] ([score_meals * 5] Points)
+ Research Completed: [score_researchdone] ([score_researchdone * 30] Points)
"} + if (!emergency_shuttle.location()) dat += "Shuttle Escapees: [score_escapees] ([score_escapees * 25] Points)
" + dat += {"Random Events Endured: [score_eventsendured] ([score_eventsendured * 50] Points)
+ Whole Station Powered: [score_powerbonus ? "Yes" : "No"] ([score_powerbonus * 2500] Points)
+ Ultra-Clean Station: [score_mess ? "No" : "Yes"] ([score_messbonus * 3000] Points)

+ The bad:
+ + Dead bodies on Station: [score_deadcrew] (-[score_deadcrew * 25] Points)
+ Uncleaned Messes: [score_mess] (-[score_mess] Points)
+ Station Power Issues: [score_powerloss] (-[score_powerloss * 20] Points)
+ Rampant Diseases: [score_disease] (-[score_disease * 30] Points)
+ AI Destroyed: [score_deadaipenalty ? "Yes" : "No"] (-[score_deadaipenalty * 250] Points)

+ The Weird
+ + Food Eaten: [score_foodeaten]
+ Times a Clown was Abused: [score_clownabuse]

+ "} + if (score_escapees) + dat += {"Richest Escapee: [score_richestname], [score_richestjob]: $[num2text(score_richestcash,50)] ([score_richestkey])
+ Most Battered Escapee: [score_dmgestname], [score_dmgestjob]: [score_dmgestdamage] damage ([score_dmgestkey])
"} + else + if(emergency_shuttle.location()) + dat += "The station wasn't evacuated!
" + else + dat += "No-one escaped!
" + + dat += ticker.mode.declare_job_completion() + + dat += {" +

+ FINAL SCORE: [score_crewscore]
+ "} + + var/score_rating = "The Aristocrats!" + switch(score_crewscore) + if(-99999 to -50000) score_rating = "Even the Singularity Deserves Better" + if(-49999 to -5000) score_rating = "Singularity Fodder" + if(-4999 to -1000) score_rating = "You're All Fired" + if(-999 to -500) score_rating = "A Waste of Perfectly Good Oxygen" + if(-499 to -250) score_rating = "A Wretched Heap of Scum and Incompetence" + if(-249 to -100) score_rating = "Outclassed by Lab Monkeys" + if(-99 to -21) score_rating = "The Undesirables" + if(-20 to 20) score_rating = "Ambivalently Average" + if(21 to 99) score_rating = "Not Bad, but Not Good" + if(100 to 249) score_rating = "Skillful Servants of Science" + if(250 to 499) score_rating = "Best of a Good Bunch" + if(500 to 999) score_rating = "Lean Mean Machine Thirteen" + if(1000 to 4999) score_rating = "Promotions for Everyone" + if(5000 to 9999) score_rating = "Ambassadors of Discovery" + if(10000 to 49999) score_rating = "The Pride of Science Itself" + if(50000 to INFINITY) score_rating = "Nanotrasen's Finest" + + dat += "RATING: [score_rating]" src << browse(dat, "window=roundstats;size=500x600") \ No newline at end of file diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index ad1761e2ece..769b932dcae 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -292,7 +292,7 @@ * usr is the mob who gets the change. */ /obj/machinery/vending/proc/pay_with_cash(var/obj/item/weapon/spacecash/cashmoney, mob/user) - if(currently_vending.price > cashmoney.worth) + if(currently_vending.price > cashmoney.get_total()) // This is not a status display message, since it's something the character // themselves is meant to see BEFORE putting the money in usr << "\icon[cashmoney] That is not enough money." @@ -304,7 +304,7 @@ // just assume that all spacecash that's not something else is a bill visible_message("[usr] inserts a credit chip into [src].") - var/left = cashmoney.worth - currently_vending.price + var/left = cashmoney.get_total() - currently_vending.price usr.unEquip(cashmoney) qdel(cashmoney) diff --git a/code/game/objects/items/weapons/cash.dm b/code/game/objects/items/weapons/cash.dm index 8aadcc91e92..294a697454a 100644 --- a/code/game/objects/items/weapons/cash.dm +++ b/code/game/objects/items/weapons/cash.dm @@ -1,108 +1,111 @@ -var/global/list/moneytypes=list( - /obj/item/weapon/spacecash/c1000 = 1000, - /obj/item/weapon/spacecash/c500 = 500, // Might get rid of this. - /obj/item/weapon/spacecash/c100 = 100, - /obj/item/weapon/spacecash/c10 = 10, - /obj/item/weapon/spacecash = 1, -) - -/obj/item/weapon/spacecash - name = "credit chip" - desc = "Money money money." - gender = PLURAL - icon = 'icons/obj/money.dmi' - icon_state = "cash1" - opacity = 0 - density = 0 - anchored = 0.0 - force = 1.0 - throwforce = 1.0 - throw_speed = 1 - throw_range = 2 - w_class = 1.0 - var/access = list() - access = access_crate_cash - var/worth = 1 // Per chip - var/amount = 1 // number of chips - var/stack_color = "#4E054F" - -/obj/item/weapon/spacecash/New(var/new_loc,var/new_amount=1) - loc = new_loc - name = "[worth] credit chip" - amount = new_amount - update_icon() - -/obj/item/weapon/spacecash/examine(mob/user) - if(amount>1) - user << "\icon[src] This is a stack of [amount] [src]s." - else - user << "\icon[src] This is \a [src]s." - user << "It's worth [worth*amount] credits." - -/obj/item/weapon/spacecash/update_icon() - icon_state = "cash[worth]" - // Up to 100 items per stack. - overlays = 0 - var/stacksize=round(amount/25) - pixel_x=rand(-7,7) - pixel_y=rand(-14,14) - if(stacksize) - // 0 = single - // 1 = 1/4 stack - // 2 = 1/2 stack - // 3 = 3/4 stack - // 4 = full stack - var/image/stack = image(icon,icon_state="cashstack[stacksize]") - stack.color=stack_color - overlays += stack - -/obj/item/weapon/spacecash/c10 - icon_state = "cash10" - worth = 10 - stack_color = "#663200" - -/obj/item/weapon/spacecash/c20 - icon_state = "cash10" - worth = 20 - stack_color = "#663200" - -/obj/item/weapon/spacecash/c50 - icon_state = "cash10" - worth = 50 - stack_color = "#663200" - -/obj/item/weapon/spacecash/c100 - icon_state = "cash100" - worth = 100 - stack_color = "#663200" - -/obj/item/weapon/spacecash/c200 - icon_state = "cash200" - worth = 200 - stack_color = "#663200" - -/obj/item/weapon/spacecash/c500 - icon_state = "cash500" - worth = 500 - stack_color = "#663200" - -/obj/item/weapon/spacecash/c1000 - icon_state = "cash1000" - worth = 1000 - stack_color = "#333333" - -/proc/dispense_cash(var/amount, var/loc) - for(var/cashtype in moneytypes) - var/slice = moneytypes[cashtype] - var/dispense_count = Floor(amount/slice) - amount = amount % slice - while(dispense_count>0) - var/dispense_this_time = min(dispense_count,100) - if(dispense_this_time > 0) - new cashtype(loc,dispense_this_time) - dispense_count -= dispense_this_time - -/proc/count_cash(var/list/cash) - . = 0 - for(var/obj/item/weapon/spacecash/C in cash) - . += C.amount * C.worth \ No newline at end of file +var/global/list/moneytypes=list( + /obj/item/weapon/spacecash/c1000 = 1000, + /obj/item/weapon/spacecash/c500 = 500, // Might get rid of this. + /obj/item/weapon/spacecash/c100 = 100, + /obj/item/weapon/spacecash/c10 = 10, + /obj/item/weapon/spacecash = 1, +) + +/obj/item/weapon/spacecash + name = "credit chip" + desc = "Money money money." + gender = PLURAL + icon = 'icons/obj/money.dmi' + icon_state = "cash1" + opacity = 0 + density = 0 + anchored = 0.0 + force = 1.0 + throwforce = 1.0 + throw_speed = 1 + throw_range = 2 + w_class = 1.0 + var/access = list() + access = access_crate_cash + var/worth = 1 // Per chip + var/amount = 1 // number of chips + var/stack_color = "#4E054F" + +/obj/item/weapon/spacecash/New(var/new_loc,var/new_amount=1) + loc = new_loc + name = "[worth] credit chip" + amount = new_amount + update_icon() + +/obj/item/weapon/spacecash/examine(mob/user) + if(amount>1) + user << "\icon[src] This is a stack of [amount] [src]s." + else + user << "\icon[src] This is \a [src]s." + user << "It's worth [worth*amount] credits." + +/obj/item/weapon/spacecash/update_icon() + icon_state = "cash[worth]" + // Up to 100 items per stack. + overlays = 0 + var/stacksize=round(amount/25) + pixel_x=rand(-7,7) + pixel_y=rand(-14,14) + if(stacksize) + // 0 = single + // 1 = 1/4 stack + // 2 = 1/2 stack + // 3 = 3/4 stack + // 4 = full stack + var/image/stack = image(icon,icon_state="cashstack[stacksize]") + stack.color=stack_color + overlays += stack + +/obj/item/weapon/spacecash/proc/get_total() + return worth * amount + +/obj/item/weapon/spacecash/c10 + icon_state = "cash10" + worth = 10 + stack_color = "#663200" + +/obj/item/weapon/spacecash/c20 + icon_state = "cash10" + worth = 20 + stack_color = "#663200" + +/obj/item/weapon/spacecash/c50 + icon_state = "cash10" + worth = 50 + stack_color = "#663200" + +/obj/item/weapon/spacecash/c100 + icon_state = "cash100" + worth = 100 + stack_color = "#663200" + +/obj/item/weapon/spacecash/c200 + icon_state = "cash200" + worth = 200 + stack_color = "#663200" + +/obj/item/weapon/spacecash/c500 + icon_state = "cash500" + worth = 500 + stack_color = "#663200" + +/obj/item/weapon/spacecash/c1000 + icon_state = "cash1000" + worth = 1000 + stack_color = "#333333" + +/proc/dispense_cash(var/amount, var/loc) + for(var/cashtype in moneytypes) + var/slice = moneytypes[cashtype] + var/dispense_count = Floor(amount/slice) + amount = amount % slice + while(dispense_count>0) + var/dispense_this_time = min(dispense_count,100) + if(dispense_this_time > 0) + new cashtype(loc,dispense_this_time) + dispense_count -= dispense_this_time + +/proc/count_cash(var/list/cash) + . = 0 + for(var/obj/item/weapon/spacecash/C in cash) + . += C.get_total() \ No newline at end of file diff --git a/code/modules/economy/ATM.dm b/code/modules/economy/ATM.dm index faf598f77e9..4e16a1325a0 100644 --- a/code/modules/economy/ATM.dm +++ b/code/modules/economy/ATM.dm @@ -1,403 +1,402 @@ -/* - -TODO: -give money an actual use (QM stuff, vending machines) -send money to people (might be worth attaching money to custom database thing for this, instead of being in the ID) -log transactions - -*/ - -#define NO_SCREEN 0 -#define CHANGE_SECURITY_LEVEL 1 -#define TRANSFER_FUNDS 2 -#define VIEW_TRANSACTION_LOGS 3 -#define PRINT_DELAY 100 - -/obj/item/weapon/card/id/var/money = 2000 - -/obj/machinery/atm - name = "Nanotrasen Automatic Teller Machine" - desc = "For all your monetary needs!" - icon = 'icons/obj/terminals.dmi' - icon_state = "atm" - anchored = 1 - use_power = 1 - idle_power_usage = 10 - var/obj/machinery/computer/account_database/linked_db - var/datum/money_account/authenticated_account - var/number_incorrect_tries = 0 - var/previous_account_number = 0 - var/max_pin_attempts = 3 - var/ticks_left_locked_down = 0 - var/ticks_left_timeout = 0 - var/machine_id = "" - var/obj/item/weapon/card/held_card - var/editing_security_level = 0 - var/view_screen = NO_SCREEN - var/lastprint = 0 // Printer needs time to cooldown - -/obj/machinery/atm/New() - ..() - machine_id = "[station_name()] RT #[num_financial_terminals++]" - -/obj/machinery/atm/initialize() - ..() - reconnect_database() - -/obj/machinery/atm/process() - if(stat & NOPOWER) - return - - if(linked_db && ( (linked_db.stat & NOPOWER) || !linked_db.activated ) ) - linked_db = null - authenticated_account = null - src.visible_message("\red \icon[src] [src] buzzes rudely, \"Connection to remote database lost.\"") - updateDialog() - - if(ticks_left_timeout > 0) - ticks_left_timeout-- - if(ticks_left_timeout <= 0) - authenticated_account = null - if(ticks_left_locked_down > 0) - ticks_left_locked_down-- - if(ticks_left_locked_down <= 0) - number_incorrect_tries = 0 - - if(authenticated_account) - var/turf/T = get_turf(src) - if(istype(T) && locate(/obj/item/weapon/spacecash) in T) - var/list/cash_found = list() - for(var/obj/item/weapon/spacecash/S in T) - cash_found+=S - if(cash_found.len>0) - if(prob(50)) - playsound(loc, 'sound/items/polaroid1.ogg', 50, 1) - else - playsound(loc, 'sound/items/polaroid2.ogg', 50, 1) - var/amount = count_cash(cash_found) - for(var/obj/item/weapon/spacecash/S in cash_found) - qdel(S) - authenticated_account.charge(-amount,null,"Credit deposit",terminal_id=machine_id,dest_name = "Terminal") - -/obj/machinery/atm/proc/reconnect_database() - for(var/obj/machinery/computer/account_database/DB in world) //Hotfix until someone finds out why it isn't in 'machines' - if( DB.z == src.z && !(DB.stat & NOPOWER) && DB.activated ) - linked_db = DB - break - -/obj/machinery/atm/attackby(obj/item/I as obj, mob/user as mob, params) - if(istype(I, /obj/item/weapon/card)) - var/obj/item/weapon/card/id/idcard = I - if(!held_card) - usr.drop_item() - idcard.loc = src - held_card = idcard - if(authenticated_account && held_card.associated_account_number != authenticated_account.account_number) - authenticated_account = null - else if(authenticated_account) - if(istype(I,/obj/item/weapon/spacecash)) - //consume the money - authenticated_account.money += I:worth * I:amount - if(prob(50)) - playsound(loc, 'sound/items/polaroid1.ogg', 50, 1) - else - playsound(loc, 'sound/items/polaroid2.ogg', 50, 1) - - //create a transaction log entry - var/datum/transaction/T = new() - T.target_name = authenticated_account.owner_name - T.purpose = "Credit deposit" - T.amount = I:worth - T.source_terminal = machine_id - T.date = current_date_string - T.time = worldtime2text() - authenticated_account.transaction_log.Add(T) - - user << "You insert [I] into [src]." - src.attack_hand(user) - qdel(I) - else - ..() - -/obj/machinery/atm/attack_hand(mob/user as mob) - if(istype(user, /mob/living/silicon)) - user << "\red Artificial unit recognized. Artificial units do not currently receive monetary compensation, as per Nanotrasen regulation #1005." - return - if(get_dist(src,user) <= 1) - //check to see if the user has low security enabled - scan_user(user) - - //js replicated from obj/machinery/computer/card - var/dat = {"

Nanotrasen Automatic Teller Machine

- For all your monetary needs!
- This terminal is [machine_id]. Report this code when contacting Nanotrasen IT Support
- Card: [held_card ? held_card.name : "------"]

"} - - if(ticks_left_locked_down > 0) - dat += "Maximum number of pin attempts exceeded! Access to this ATM has been temporarily disabled." - else if(authenticated_account) - switch(view_screen) - if(CHANGE_SECURITY_LEVEL) - dat += "Select a new security level for this account:

" - var/text = "Zero - Either the account number or card is required to access this account. EFTPOS transactions will require a card and ask for a pin, but not verify the pin is correct." - if(authenticated_account.security_level != 0) - text = "[text]" - dat += "[text]
" - text = "One - An account number and pin must be manually entered to access this account and process transactions." - if(authenticated_account.security_level != 1) - text = "[text]" - dat += "[text]
" - text = "Two - In addition to account number and pin, a card is required to access this account and process transactions." - if(authenticated_account.security_level != 2) - text = "[text]" - dat += {"[text]

- Back"} - if(VIEW_TRANSACTION_LOGS) - dat += {"Transaction logs
- Back - - - - - - - - - "} - for(var/datum/transaction/T in authenticated_account.transaction_log) - dat += {" - - - - - - - "} - dat += "
DateTimeTargetPurposeValueSource terminal ID
[T.date][T.time][T.target_name][T.purpose]$[T.amount][T.source_terminal]
" - if(TRANSFER_FUNDS) - dat += {"Account balance: $[authenticated_account.money]
- Back

-
- - - Target account number:
- Funds to transfer:
- Transaction purpose:
-
-
"} - else - dat += {"Welcome, [authenticated_account.owner_name].
- Account balance: $[authenticated_account.money] -
- - -
-
- Change account security level
- Make transfer
- View transaction log
- Print balance statement
- Logout
"} - else if(linked_db) - dat += {"
- - - Account:
- PIN:
-
-
"} - else - dat += "Unable to connect to accounts database, please retry and if the issue persists contact Nanotrasen IT support." - reconnect_database() - - user << browse(dat,"window=atm;size=550x650") - else - user << browse(null,"window=atm") - -/obj/machinery/atm/Topic(var/href, var/href_list) - if(href_list["choice"]) - switch(href_list["choice"]) - if("transfer") - if(authenticated_account && linked_db) - var/transfer_amount = text2num(href_list["funds_amount"]) - if(transfer_amount <= 0) - alert("That is not a valid amount.") - else if(transfer_amount <= authenticated_account.money) - var/target_account_number = text2num(href_list["target_acc_number"]) - var/transfer_purpose = href_list["purpose"] - if(linked_db.charge_to_account(target_account_number, authenticated_account.owner_name, transfer_purpose, machine_id, transfer_amount)) - usr << "\icon[src]Funds transfer successful." - authenticated_account.money -= transfer_amount - - //create an entry in the account transaction log - var/datum/transaction/T = new() - T.target_name = "Account #[target_account_number]" - T.purpose = transfer_purpose - T.source_terminal = machine_id - T.date = current_date_string - T.time = worldtime2text() - T.amount = "([transfer_amount])" - authenticated_account.transaction_log.Add(T) - else - usr << "\icon[src]Funds transfer failed." - - else - usr << "\icon[src]You don't have enough funds to do that!" - if("view_screen") - view_screen = text2num(href_list["view_screen"]) - if("change_security_level") - if(authenticated_account) - var/new_sec_level = max( min(text2num(href_list["new_security_level"]), 2), 0) - authenticated_account.security_level = new_sec_level - if("attempt_auth") - if(linked_db && !ticks_left_locked_down) - var/tried_account_num = text2num(href_list["account_num"]) - if(!tried_account_num) - tried_account_num = held_card.associated_account_number - var/tried_pin = text2num(href_list["account_pin"]) - - authenticated_account = attempt_account_access(tried_account_num, tried_pin, held_card && held_card.associated_account_number == tried_account_num ? 2 : 1) - if(!authenticated_account) - number_incorrect_tries++ - if(previous_account_number == tried_account_num) - if(number_incorrect_tries > max_pin_attempts) - //lock down the atm - ticks_left_locked_down = 30 - playsound(src, 'sound/machines/buzz-two.ogg', 50, 1) - - //create an entry in the account transaction log - var/datum/money_account/failed_account = linked_db.get_account(tried_account_num) - if(failed_account) - var/datum/transaction/T = new() - T.target_name = failed_account.owner_name - T.purpose = "Unauthorised login attempt" - T.source_terminal = machine_id - T.date = current_date_string - T.time = worldtime2text() - failed_account.transaction_log.Add(T) - else - usr << "\red \icon[src] Incorrect pin/account combination entered, [max_pin_attempts - number_incorrect_tries] attempts remaining." - previous_account_number = tried_account_num - playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1) - else - usr << "\red \icon[src] incorrect pin/account combination entered." - number_incorrect_tries = 0 - else - playsound(src, 'sound/machines/twobeep.ogg', 50, 1) - ticks_left_timeout = 120 - view_screen = NO_SCREEN - - //create a transaction log entry - var/datum/transaction/T = new() - T.target_name = authenticated_account.owner_name - T.purpose = "Remote terminal access" - T.source_terminal = machine_id - T.date = current_date_string - T.time = worldtime2text() - authenticated_account.transaction_log.Add(T) - - usr << "\blue \icon[src] Access granted. Welcome user '[authenticated_account.owner_name].'" - - previous_account_number = tried_account_num - if("withdrawal") - var/amount = max(text2num(href_list["funds_amount"]),0) - if(amount <= 0) - alert("That is not a valid amount.") - else if(authenticated_account && amount > 0) - if(amount <= authenticated_account.money) - playsound(src, 'sound/machines/chime.ogg', 50, 1) - - //remove the money - if(amount > 10000) // prevent crashes - usr << "\blue The ATM's screen flashes, 'Maximum single withdrawl limit reached, defaulting to 10,000.'" - amount = 10000 - authenticated_account.money -= amount - withdraw_arbitrary_sum(amount) - - //create an entry in the account transaction log - var/datum/transaction/T = new() - T.target_name = authenticated_account.owner_name - T.purpose = "Credit withdrawal" - T.amount = "([amount])" - T.source_terminal = machine_id - T.date = current_date_string - T.time = worldtime2text() - authenticated_account.transaction_log.Add(T) - else - usr << "\icon[src]You don't have enough funds to do that!" - if("balance_statement") - if(authenticated_account) - if(world.timeofday < lastprint + PRINT_DELAY) - usr << "The [src.name] flashes an error on its display." - return - lastprint = world.timeofday - var/obj/item/weapon/paper/R = new(src.loc) - R.name = "Account balance: [authenticated_account.owner_name]" - R.info = {"NT Automated Teller Account Statement

- Account holder: [authenticated_account.owner_name]
- Account number: [authenticated_account.account_number]
- Balance: $[authenticated_account.money]
- Date and time: [worldtime2text()], [current_date_string]

- Service terminal ID: [machine_id]
"} - - //stamp the paper - var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') - stampoverlay.icon_state = "paper_stamp-cent" - if(!R.stamped) - R.stamped = new - R.stamped += /obj/item/weapon/stamp - R.overlays += stampoverlay - R.stamps += "
This paper has been stamped by the Automatic Teller Machine." - - if(prob(50)) - playsound(loc, 'sound/items/polaroid1.ogg', 50, 1) - else - playsound(loc, 'sound/items/polaroid2.ogg', 50, 1) - if("insert_card") - if(held_card) - held_card.loc = src.loc - authenticated_account = null - - if(ishuman(usr) && !usr.get_active_hand()) - usr.put_in_hands(held_card) - held_card = null - - else - var/obj/item/I = usr.get_active_hand() - if (istype(I, /obj/item/weapon/card/id)) - usr.drop_item() - I.loc = src - held_card = I - if("logout") - authenticated_account = null - //usr << browse(null,"window=atm") - - src.attack_hand(usr) - -//create the most effective combination of notes to make up the requested amount -/obj/machinery/atm/proc/withdraw_arbitrary_sum(var/arbitrary_sum) - dispense_cash(arbitrary_sum,get_step(get_turf(src),turn(dir,180))) // Spawn on the ATM. - -//stolen wholesale and then edited a bit from newscasters, which are awesome and by Agouri -/obj/machinery/atm/proc/scan_user(mob/living/carbon/human/human_user as mob) - if(!authenticated_account && linked_db) - if(human_user.wear_id) - var/obj/item/weapon/card/id/I - if(istype(human_user.wear_id, /obj/item/weapon/card/id) ) - I = human_user.wear_id - else if(istype(human_user.wear_id, /obj/item/device/pda) ) - var/obj/item/device/pda/P = human_user.wear_id - I = P.id - if(I) - authenticated_account = attempt_account_access(I.associated_account_number) - if(authenticated_account) - human_user << "\blue \icon[src] Access granted. Welcome user '[authenticated_account.owner_name].'" - - //create a transaction log entry - var/datum/transaction/T = new() - T.target_name = authenticated_account.owner_name - T.purpose = "Remote terminal access" - T.source_terminal = machine_id - T.date = current_date_string - T.time = worldtime2text() - authenticated_account.transaction_log.Add(T) +/* + +TODO: +give money an actual use (QM stuff, vending machines) +send money to people (might be worth attaching money to custom database thing for this, instead of being in the ID) +log transactions + +*/ + +#define NO_SCREEN 0 +#define CHANGE_SECURITY_LEVEL 1 +#define TRANSFER_FUNDS 2 +#define VIEW_TRANSACTION_LOGS 3 +#define PRINT_DELAY 100 + +/obj/machinery/atm + name = "Nanotrasen Automatic Teller Machine" + desc = "For all your monetary needs!" + icon = 'icons/obj/terminals.dmi' + icon_state = "atm" + anchored = 1 + use_power = 1 + idle_power_usage = 10 + var/obj/machinery/computer/account_database/linked_db + var/datum/money_account/authenticated_account + var/number_incorrect_tries = 0 + var/previous_account_number = 0 + var/max_pin_attempts = 3 + var/ticks_left_locked_down = 0 + var/ticks_left_timeout = 0 + var/machine_id = "" + var/obj/item/weapon/card/held_card + var/editing_security_level = 0 + var/view_screen = NO_SCREEN + var/lastprint = 0 // Printer needs time to cooldown + +/obj/machinery/atm/New() + ..() + machine_id = "[station_name()] RT #[num_financial_terminals++]" + +/obj/machinery/atm/initialize() + ..() + reconnect_database() + +/obj/machinery/atm/process() + if(stat & NOPOWER) + return + + if(linked_db && ( (linked_db.stat & NOPOWER) || !linked_db.activated ) ) + linked_db = null + authenticated_account = null + src.visible_message("\red \icon[src] [src] buzzes rudely, \"Connection to remote database lost.\"") + updateDialog() + + if(ticks_left_timeout > 0) + ticks_left_timeout-- + if(ticks_left_timeout <= 0) + authenticated_account = null + if(ticks_left_locked_down > 0) + ticks_left_locked_down-- + if(ticks_left_locked_down <= 0) + number_incorrect_tries = 0 + + if(authenticated_account) + var/turf/T = get_turf(src) + if(istype(T) && locate(/obj/item/weapon/spacecash) in T) + var/list/cash_found = list() + for(var/obj/item/weapon/spacecash/S in T) + cash_found+=S + if(cash_found.len>0) + if(prob(50)) + playsound(loc, 'sound/items/polaroid1.ogg', 50, 1) + else + playsound(loc, 'sound/items/polaroid2.ogg', 50, 1) + var/amount = count_cash(cash_found) + for(var/obj/item/weapon/spacecash/S in cash_found) + qdel(S) + authenticated_account.charge(-amount,null,"Credit deposit",terminal_id=machine_id,dest_name = "Terminal") + +/obj/machinery/atm/proc/reconnect_database() + for(var/obj/machinery/computer/account_database/DB in world) //Hotfix until someone finds out why it isn't in 'machines' + if( DB.z == src.z && !(DB.stat & NOPOWER) && DB.activated ) + linked_db = DB + break + +/obj/machinery/atm/attackby(obj/item/I as obj, mob/user as mob, params) + if(istype(I, /obj/item/weapon/card)) + var/obj/item/weapon/card/id/idcard = I + if(!held_card) + usr.drop_item() + idcard.loc = src + held_card = idcard + if(authenticated_account && held_card.associated_account_number != authenticated_account.account_number) + authenticated_account = null + else if(authenticated_account) + if(istype(I,/obj/item/weapon/spacecash)) + //consume the money + var/obj/item/weapon/spacecash/C = I + authenticated_account.money += C.get_total() + if(prob(50)) + playsound(loc, 'sound/items/polaroid1.ogg', 50, 1) + else + playsound(loc, 'sound/items/polaroid2.ogg', 50, 1) + + //create a transaction log entry + var/datum/transaction/T = new() + T.target_name = authenticated_account.owner_name + T.purpose = "Credit deposit" + T.amount = C.get_total() + T.source_terminal = machine_id + T.date = current_date_string + T.time = worldtime2text() + authenticated_account.transaction_log.Add(T) + + user << "You insert [C] into [src]." + src.attack_hand(user) + qdel(I) + else + ..() + +/obj/machinery/atm/attack_hand(mob/user as mob) + if(istype(user, /mob/living/silicon)) + user << "\red Artificial unit recognized. Artificial units do not currently receive monetary compensation, as per Nanotrasen regulation #1005." + return + if(get_dist(src,user) <= 1) + //check to see if the user has low security enabled + scan_user(user) + + //js replicated from obj/machinery/computer/card + var/dat = {"

Nanotrasen Automatic Teller Machine

+ For all your monetary needs!
+ This terminal is [machine_id]. Report this code when contacting Nanotrasen IT Support
+ Card: [held_card ? held_card.name : "------"]

"} + + if(ticks_left_locked_down > 0) + dat += "Maximum number of pin attempts exceeded! Access to this ATM has been temporarily disabled." + else if(authenticated_account) + switch(view_screen) + if(CHANGE_SECURITY_LEVEL) + dat += "Select a new security level for this account:

" + var/text = "Zero - Either the account number or card is required to access this account. EFTPOS transactions will require a card and ask for a pin, but not verify the pin is correct." + if(authenticated_account.security_level != 0) + text = "[text]" + dat += "[text]
" + text = "One - An account number and pin must be manually entered to access this account and process transactions." + if(authenticated_account.security_level != 1) + text = "[text]" + dat += "[text]
" + text = "Two - In addition to account number and pin, a card is required to access this account and process transactions." + if(authenticated_account.security_level != 2) + text = "[text]" + dat += {"[text]

+ Back"} + if(VIEW_TRANSACTION_LOGS) + dat += {"Transaction logs
+ Back + + + + + + + + + "} + for(var/datum/transaction/T in authenticated_account.transaction_log) + dat += {" + + + + + + + "} + dat += "
DateTimeTargetPurposeValueSource terminal ID
[T.date][T.time][T.target_name][T.purpose]$[T.amount][T.source_terminal]
" + if(TRANSFER_FUNDS) + dat += {"Account balance: $[authenticated_account.money]
+ Back

+
+ + + Target account number:
+ Funds to transfer:
+ Transaction purpose:
+
+
"} + else + dat += {"Welcome, [authenticated_account.owner_name].
+ Account balance: $[authenticated_account.money] +
+ + +
+
+ Change account security level
+ Make transfer
+ View transaction log
+ Print balance statement
+ Logout
"} + else if(linked_db) + dat += {"
+ + + Account:
+ PIN:
+
+
"} + else + dat += "Unable to connect to accounts database, please retry and if the issue persists contact Nanotrasen IT support." + reconnect_database() + + user << browse(dat,"window=atm;size=550x650") + else + user << browse(null,"window=atm") + +/obj/machinery/atm/Topic(var/href, var/href_list) + if(href_list["choice"]) + switch(href_list["choice"]) + if("transfer") + if(authenticated_account && linked_db) + var/transfer_amount = text2num(href_list["funds_amount"]) + if(transfer_amount <= 0) + alert("That is not a valid amount.") + else if(transfer_amount <= authenticated_account.money) + var/target_account_number = text2num(href_list["target_acc_number"]) + var/transfer_purpose = href_list["purpose"] + if(linked_db.charge_to_account(target_account_number, authenticated_account.owner_name, transfer_purpose, machine_id, transfer_amount)) + usr << "\icon[src]Funds transfer successful." + authenticated_account.money -= transfer_amount + + //create an entry in the account transaction log + var/datum/transaction/T = new() + T.target_name = "Account #[target_account_number]" + T.purpose = transfer_purpose + T.source_terminal = machine_id + T.date = current_date_string + T.time = worldtime2text() + T.amount = "([transfer_amount])" + authenticated_account.transaction_log.Add(T) + else + usr << "\icon[src]Funds transfer failed." + + else + usr << "\icon[src]You don't have enough funds to do that!" + if("view_screen") + view_screen = text2num(href_list["view_screen"]) + if("change_security_level") + if(authenticated_account) + var/new_sec_level = max( min(text2num(href_list["new_security_level"]), 2), 0) + authenticated_account.security_level = new_sec_level + if("attempt_auth") + if(linked_db && !ticks_left_locked_down) + var/tried_account_num = text2num(href_list["account_num"]) + if(!tried_account_num) + tried_account_num = held_card.associated_account_number + var/tried_pin = text2num(href_list["account_pin"]) + + authenticated_account = attempt_account_access(tried_account_num, tried_pin, held_card && held_card.associated_account_number == tried_account_num ? 2 : 1) + if(!authenticated_account) + number_incorrect_tries++ + if(previous_account_number == tried_account_num) + if(number_incorrect_tries > max_pin_attempts) + //lock down the atm + ticks_left_locked_down = 30 + playsound(src, 'sound/machines/buzz-two.ogg', 50, 1) + + //create an entry in the account transaction log + var/datum/money_account/failed_account = linked_db.get_account(tried_account_num) + if(failed_account) + var/datum/transaction/T = new() + T.target_name = failed_account.owner_name + T.purpose = "Unauthorised login attempt" + T.source_terminal = machine_id + T.date = current_date_string + T.time = worldtime2text() + failed_account.transaction_log.Add(T) + else + usr << "\red \icon[src] Incorrect pin/account combination entered, [max_pin_attempts - number_incorrect_tries] attempts remaining." + previous_account_number = tried_account_num + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1) + else + usr << "\red \icon[src] incorrect pin/account combination entered." + number_incorrect_tries = 0 + else + playsound(src, 'sound/machines/twobeep.ogg', 50, 1) + ticks_left_timeout = 120 + view_screen = NO_SCREEN + + //create a transaction log entry + var/datum/transaction/T = new() + T.target_name = authenticated_account.owner_name + T.purpose = "Remote terminal access" + T.source_terminal = machine_id + T.date = current_date_string + T.time = worldtime2text() + authenticated_account.transaction_log.Add(T) + + usr << "\blue \icon[src] Access granted. Welcome user '[authenticated_account.owner_name].'" + + previous_account_number = tried_account_num + if("withdrawal") + var/amount = max(text2num(href_list["funds_amount"]),0) + if(amount <= 0) + alert("That is not a valid amount.") + else if(authenticated_account && amount > 0) + if(amount <= authenticated_account.money) + playsound(src, 'sound/machines/chime.ogg', 50, 1) + + //remove the money + if(amount > 10000) // prevent crashes + usr << "\blue The ATM's screen flashes, 'Maximum single withdrawl limit reached, defaulting to 10,000.'" + amount = 10000 + authenticated_account.money -= amount + withdraw_arbitrary_sum(amount) + + //create an entry in the account transaction log + var/datum/transaction/T = new() + T.target_name = authenticated_account.owner_name + T.purpose = "Credit withdrawal" + T.amount = "([amount])" + T.source_terminal = machine_id + T.date = current_date_string + T.time = worldtime2text() + authenticated_account.transaction_log.Add(T) + else + usr << "\icon[src]You don't have enough funds to do that!" + if("balance_statement") + if(authenticated_account) + if(world.timeofday < lastprint + PRINT_DELAY) + usr << "The [src.name] flashes an error on its display." + return + lastprint = world.timeofday + var/obj/item/weapon/paper/R = new(src.loc) + R.name = "Account balance: [authenticated_account.owner_name]" + R.info = {"NT Automated Teller Account Statement

+ Account holder: [authenticated_account.owner_name]
+ Account number: [authenticated_account.account_number]
+ Balance: $[authenticated_account.money]
+ Date and time: [worldtime2text()], [current_date_string]

+ Service terminal ID: [machine_id]
"} + + //stamp the paper + var/image/stampoverlay = image('icons/obj/bureaucracy.dmi') + stampoverlay.icon_state = "paper_stamp-cent" + if(!R.stamped) + R.stamped = new + R.stamped += /obj/item/weapon/stamp + R.overlays += stampoverlay + R.stamps += "
This paper has been stamped by the Automatic Teller Machine." + + if(prob(50)) + playsound(loc, 'sound/items/polaroid1.ogg', 50, 1) + else + playsound(loc, 'sound/items/polaroid2.ogg', 50, 1) + if("insert_card") + if(held_card) + held_card.loc = src.loc + authenticated_account = null + + if(ishuman(usr) && !usr.get_active_hand()) + usr.put_in_hands(held_card) + held_card = null + + else + var/obj/item/I = usr.get_active_hand() + if (istype(I, /obj/item/weapon/card/id)) + usr.drop_item() + I.loc = src + held_card = I + if("logout") + authenticated_account = null + //usr << browse(null,"window=atm") + + src.attack_hand(usr) + +//create the most effective combination of notes to make up the requested amount +/obj/machinery/atm/proc/withdraw_arbitrary_sum(var/arbitrary_sum) + dispense_cash(arbitrary_sum,get_step(get_turf(src),turn(dir,180))) // Spawn on the ATM. + +//stolen wholesale and then edited a bit from newscasters, which are awesome and by Agouri +/obj/machinery/atm/proc/scan_user(mob/living/carbon/human/human_user as mob) + if(!authenticated_account && linked_db) + if(human_user.wear_id) + var/obj/item/weapon/card/id/I + if(istype(human_user.wear_id, /obj/item/weapon/card/id) ) + I = human_user.wear_id + else if(istype(human_user.wear_id, /obj/item/device/pda) ) + var/obj/item/device/pda/P = human_user.wear_id + I = P.id + if(I) + authenticated_account = attempt_account_access(I.associated_account_number) + if(authenticated_account) + human_user << "\blue \icon[src] Access granted. Welcome user '[authenticated_account.owner_name].'" + + //create a transaction log entry + var/datum/transaction/T = new() + T.target_name = authenticated_account.owner_name + T.purpose = "Remote terminal access" + T.source_terminal = machine_id + T.date = current_date_string + T.time = worldtime2text() + authenticated_account.transaction_log.Add(T) diff --git a/code/modules/economy/POS.dm b/code/modules/economy/POS.dm index 5a107e8f11a..bd2e7248f73 100644 --- a/code/modules/economy/POS.dm +++ b/code/modules/economy/POS.dm @@ -1,538 +1,538 @@ -/************************ -* Point Of Sale -* -* Takes cash or credit. -*************************/ - -/line_item - parent_type = /datum - - var/name = "" - var/price = 0 // Per unit - var/units = 0 - -var/global/current_pos_id = 1 -var/global/pos_sales = 0 - -var/const/RECEIPT_HEADER = {" - - - - -"} -var/const/POS_HEADER = {" - - - - -"} - -#define POS_TAX_RATE 0.10 // 10% - -#define POS_SCREEN_LOGIN 0 -#define POS_SCREEN_ORDER 1 -#define POS_SCREEN_FINALIZE 2 -#define POS_SCREEN_PRODUCTS 3 -#define POS_SCREEN_IMPORT 4 -#define POS_SCREEN_EXPORT 5 -#define POS_SCREEN_SETTINGS 6 -/obj/machinery/pos - icon = 'icons/obj/machines/pos.dmi' - icon_state = "pos" - density = 0 - name = "point of sale" - desc = "Also known as a cash register, or, more commonly, \"robbery magnet\"." - - var/id = 0 - var/sales = 0 - var/department - var/mob/logged_in - var/datum/money_account/linked_account - - var/credits_held = 0 - var/credits_needed = 0 - - var/list/products = list() // name = /line_item - var/list/line_items = list() // # = /line_item - - var/screen=POS_SCREEN_LOGIN - -/obj/machinery/pos/New() - ..() - id = current_pos_id++ - if(department) - linked_account = department_accounts[department] - else - linked_account = station_account - update_icon() - -/obj/machinery/pos/proc/AddToOrder(var/name, var/units) - if(!(name in products)) - return 0 - var/line_item/LI = products[name] - var/line_item/LIC = new - LIC.name=LI.name - LIC.price=LI.price - LIC.units=units - line_items.Add(LIC) - -/obj/machinery/pos/proc/RemoveFromOrder(var/order_id) - line_items.Cut(order_id,order_id+1) - -/obj/machinery/pos/proc/NewOrder() - line_items.Cut() - -/obj/machinery/pos/proc/PrintReceipt(var/order_id) - var/receipt = {"[RECEIPT_HEADER]
POINT OF SALE #[id]
- Paying to: [linked_account.owner_name]
- Cashier: [logged_in]
"} - if(myArea) - receipt += myArea.name - receipt += "
" - receipt += {"
-
[worldtime2text()], [current_date_string]
- - - - - - - "} - var/subtotal=0 - for(var/i=1;i<=line_items.len;i++) - var/line_item/LI = line_items[i] - var/linetotal=LI.units*LI.price - receipt += "" - subtotal += linetotal - var/taxes = POS_TAX_RATE*subtotal - receipt += {" - - - - - - "} - receipt += {" - - "} - receipt += "
ItemAmountUnit PriceLine Total
[LI.name][LI.units]$[num2septext(LI.price)]$[num2septext(linetotal)]
SUBTOTAL$[num2septext(subtotal)]
TAXES$[num2septext(taxes)]
TOTAL$[num2septext(taxes+subtotal)] -
" - - var/obj/item/weapon/paper/P = new(loc) - P.name="Receipt #[id]-[++sales]" - P.info=receipt - - P = new(loc) - P.name="Receipt #[id]-[sales] (Cashier Copy)" - P.info=receipt - - -/obj/machinery/pos/proc/LoginScreen() - return "
Please swipe ID to log in.
" - -/obj/machinery/pos/proc/OrderScreen() - var/receipt = {"
- POS Info - POINT OF SALE #[id]
- Paying to: [linked_account.owner_name]
- Cashier: [logged_in]
"} - if(myArea) - receipt += myArea.name - receipt += "
" - receipt += {"
Order Data -
- - - - - - - - - "} - var/subtotal=0 - if(line_items.len>0) - for(var/i=1;i<=line_items.len;i++) - var/line_item/LI = line_items[i] - var/linetotal=LI.units*LI.price - receipt += {" - - - - - - "} - subtotal += linetotal - var/taxes = POS_TAX_RATE*subtotal - var/presets = "(No presets available)" - if(products.len>0) - presets = {"" - receipt += {" - - - - - - - - - - - "} - receipt += {" - - "} - receipt += {"
ItemAmountUnit PriceLine Total...
[LI.name][LI.units]$[num2septext(LI.price)]$[num2septext(linetotal)]×
[presets] units
SUBTOTAL$[num2septext(subtotal)]
TAXES$[num2septext(taxes)]
TOTAL$[num2septext(taxes+subtotal)] -
- - -
-
"} - return receipt - -/obj/machinery/pos/proc/ProductsScreen() - var/dat={"
Product List -
- - - - - - - - "} - for(var/i in products) - var/line_item/LI = products[i] - dat += {" - - - - - "} - dat += {"
ItemUnit Price# Sold...
[LI.name]$[num2septext(LI.price)][LI.units]×
- New Product:
-
- $
-
- Import | Export -
-
"} - return dat - -/obj/machinery/pos/proc/ExportScreen() - var/dat={"
Export Products as CSV - - OK -
"} - return dat - -/obj/machinery/pos/proc/ImportScreen() - var/dat={"
- Import Products as CSV -
- - -

Data must be in the form of a CSV, with no headers or quotation marks.

-

First column must be product names, second must be prices as an unformatted number (####.##)

-

Deviations from this format will result in your import being rejected.

- -
-
"} - return dat - -/obj/machinery/pos/proc/FinalizeScreen() - return "
Waiting for Credit
Cancel
" - -/obj/machinery/pos/proc/SettingsScreen() - var/dat={"
- -
- Account Settings -
- Payable Account: -
-
-
- Locality Settings -
- Tax Rate: % (LOCKED) -
-
- -
"} - return dat - -/obj/machinery/pos/update_icon() - overlays = 0 - if(stat & (NOPOWER|BROKEN)) return - if(logged_in) - overlays += "pos-working" - else - overlays += "pos-standby" - -/obj/machinery/pos/attack_hand(var/mob/user) - user.set_machine(src) - var/logindata="" - if(logged_in) - logindata={"[logged_in.name]"} - var/dat = POS_HEADER + {" - "} - switch(screen) - if(POS_SCREEN_LOGIN) dat += LoginScreen() - if(POS_SCREEN_ORDER) dat += OrderScreen() - if(POS_SCREEN_FINALIZE) dat += FinalizeScreen() - if(POS_SCREEN_PRODUCTS) dat += ProductsScreen() - if(POS_SCREEN_EXPORT) dat += ExportScreen() - if(POS_SCREEN_IMPORT) dat += ImportScreen() - if(POS_SCREEN_SETTINGS) dat += SettingsScreen() - - dat += "" - // END AUTOFIX - user << browse(dat, "window=pos") - onclose(user, "pos") - return - -/obj/machinery/pos/proc/say(var/text) - src.visible_message("\icon[src] [name] states, \"[text]\"") - -/obj/machinery/pos/Topic(var/href, var/list/href_list) - if(..(href,href_list)) return - if("logout" in href_list) - if(alert(src, "You sure you want to log out?", "Confirm", "Yes", "No")!="Yes") return - logged_in=null - screen=POS_SCREEN_LOGIN - update_icon() - src.attack_hand(usr) - return - if(usr != logged_in) - usr << "\red [logged_in.name] is already logged in. You cannot use this machine until they log out." - return - if("act" in href_list) - switch(href_list["act"]) - if("Reset") - NewOrder() - screen=POS_SCREEN_ORDER - if("Finalize Sale") - var/subtotal=0 - if(line_items.len>0) - for(var/i=1;i<=line_items.len;i++) - var/line_item/LI = line_items[i] - subtotal += LI.units*LI.price - var/taxes = POS_TAX_RATE*subtotal - credits_needed=taxes+subtotal - say("Your total is $[num2septext(credits_needed)]. Please insert credit chips or swipe your ID.") - screen=POS_SCREEN_FINALIZE - if("Add Product") - var/line_item/LI = new - LI.name=sanitize(href_list["name"]) - LI.price=text2num(href_list["price"]) - products["[products.len+1]"]=LI - if("Add to Order") - AddToOrder(href_list["preset"],text2num(href_list["units"])) - if("Add Products") - for(var/list/line in text2list(href_list["csv"],"\n")) - var/list/cells = text2list(line,",") - if(cells.len<2) - usr << "\red The CSV must have at least two columns: Product Name, followed by Price (as a number)." - src.attack_hand(usr) - return - var/line_item/LI = new - LI.name=sanitize(cells[1]) - LI.price=text2num(cells[2]) - products["[products.len+1]"]=LI - if("Export Products") - screen=POS_SCREEN_EXPORT - if("Import Products") - screen=POS_SCREEN_IMPORT - if("Save Settings") - var/datum/money_account/new_linked_account = get_money_account(text2num(href_list["payableto"]),z) - if(!new_linked_account) - usr << "\red Unable to link new account." - else - linked_account = new_linked_account - screen=POS_SCREEN_SETTINGS - else if("screen" in href_list) - screen=text2num(href_list["screen"]) - else if("rmproduct" in href_list) - products.Remove(href_list["rmproduct"]) - else if("removefromorder" in href_list) - RemoveFromOrder(text2num(href_list["removefromorder"])) - else if("setunits" in href_list) - var/lid = text2num(href_list["setunits"]) - var/newunits = input(usr,"Enter the units sold.") as num - if(!newunits) return - var/line_item/LI = line_items[lid] - LI.units = newunits - line_items[lid]=LI - else if("setpname" in href_list) - var/newtext = sanitize(input(usr,"Enter the product's name.")) - if(!newtext) return - var/pid = href_list["setpname"] - var/line_item/LI = products[pid] - LI.name = newtext - products[pid]=LI - else if("setprice" in href_list) - var/newprice = input(usr,"Enter the product's price.") as num - if(!newprice) return - var/pid = href_list["setprice"] - var/line_item/LI = products[pid] - LI.price = newprice - products[pid]=LI - src.attack_hand(usr) - -/obj/machinery/pos/attackby(var/atom/movable/A, var/mob/user, params) - if(istype(A,/obj/item/weapon/card/id)) - var/obj/item/weapon/card/id/I = A - if(!logged_in) - user.visible_message("\blue The machine beeps, and logs you in","You hear a beep.") - logged_in = user - screen=POS_SCREEN_ORDER - update_icon() - src.attack_hand(user) //why'd you use usr nexis, why - return - else - if(!linked_account) - visible_message("\red The machine buzzes, and flashes \"NO LINKED ACCOUNT\" on the screen.","You hear a buzz.") - flick(src,"pos-error") - return - if(screen!=POS_SCREEN_FINALIZE) - visible_message("\blue The machine buzzes.","\red You hear a buzz.") - flick(src,"pos-error") - return - var/datum/money_account/acct = get_card_account(I) - if(!acct) - visible_message("\red The machine buzzes, and flashes \"NO ACCOUNT\" on the screen.","You hear a buzz.") - flick(src,"pos-error") - return - if(credits_needed > acct.money) - visible_message("\red The machine buzzes, and flashes \"NOT ENOUGH FUNDS\" on the screen.","You hear a buzz.") - flick(src,"pos-error") - return - visible_message("\blue The machine beeps, and begins printing a receipt","You hear a beep.") - PrintReceipt() - NewOrder() - acct.charge(credits_needed,linked_account,"Purchase at POS #[id].") - credits_needed=0 - screen=POS_SCREEN_ORDER - else if(istype(A,/obj/item/weapon/spacecash)) - if(!linked_account) - visible_message("\red The machine buzzes, and flashes \"NO LINKED ACCOUNT\" on the screen.","You hear a buzz.") - flick(src,"pos-error") - return - if(!logged_in || screen!=POS_SCREEN_FINALIZE) - visible_message("\blue The machine buzzes.","\red You hear a buzz.") - flick(src,"pos-error") - return - var/obj/item/weapon/spacecash/C=A - credits_held += C.worth*C.amount - if(credits_held >= credits_needed) - visible_message("\blue The machine beeps, and begins printing a receipt","You hear a beep and the sound of paper being shredded.") - PrintReceipt() - NewOrder() - credits_held -= credits_needed - credits_needed=0 - screen=POS_SCREEN_ORDER - if(credits_held) - var/obj/item/weapon/storage/box/B = new(loc) - dispense_cash(credits_held,B) - B.name="change" - B.desc="A box of change." - credits_held=0 - ..() +/************************ +* Point Of Sale +* +* Takes cash or credit. +*************************/ + +/line_item + parent_type = /datum + + var/name = "" + var/price = 0 // Per unit + var/units = 0 + +var/global/current_pos_id = 1 +var/global/pos_sales = 0 + +var/const/RECEIPT_HEADER = {" + + + + +"} +var/const/POS_HEADER = {" + + + + +"} + +#define POS_TAX_RATE 0.10 // 10% + +#define POS_SCREEN_LOGIN 0 +#define POS_SCREEN_ORDER 1 +#define POS_SCREEN_FINALIZE 2 +#define POS_SCREEN_PRODUCTS 3 +#define POS_SCREEN_IMPORT 4 +#define POS_SCREEN_EXPORT 5 +#define POS_SCREEN_SETTINGS 6 +/obj/machinery/pos + icon = 'icons/obj/machines/pos.dmi' + icon_state = "pos" + density = 0 + name = "point of sale" + desc = "Also known as a cash register, or, more commonly, \"robbery magnet\"." + + var/id = 0 + var/sales = 0 + var/department + var/mob/logged_in + var/datum/money_account/linked_account + + var/credits_held = 0 + var/credits_needed = 0 + + var/list/products = list() // name = /line_item + var/list/line_items = list() // # = /line_item + + var/screen=POS_SCREEN_LOGIN + +/obj/machinery/pos/New() + ..() + id = current_pos_id++ + if(department) + linked_account = department_accounts[department] + else + linked_account = station_account + update_icon() + +/obj/machinery/pos/proc/AddToOrder(var/name, var/units) + if(!(name in products)) + return 0 + var/line_item/LI = products[name] + var/line_item/LIC = new + LIC.name=LI.name + LIC.price=LI.price + LIC.units=units + line_items.Add(LIC) + +/obj/machinery/pos/proc/RemoveFromOrder(var/order_id) + line_items.Cut(order_id,order_id+1) + +/obj/machinery/pos/proc/NewOrder() + line_items.Cut() + +/obj/machinery/pos/proc/PrintReceipt(var/order_id) + var/receipt = {"[RECEIPT_HEADER]
POINT OF SALE #[id]
+ Paying to: [linked_account.owner_name]
+ Cashier: [logged_in]
"} + if(myArea) + receipt += myArea.name + receipt += "
" + receipt += {"
+
[worldtime2text()], [current_date_string]
+ + + + + + + "} + var/subtotal=0 + for(var/i=1;i<=line_items.len;i++) + var/line_item/LI = line_items[i] + var/linetotal=LI.units*LI.price + receipt += "" + subtotal += linetotal + var/taxes = POS_TAX_RATE*subtotal + receipt += {" + + + + + + "} + receipt += {" + + "} + receipt += "
ItemAmountUnit PriceLine Total
[LI.name][LI.units]$[num2septext(LI.price)]$[num2septext(linetotal)]
SUBTOTAL$[num2septext(subtotal)]
TAXES$[num2septext(taxes)]
TOTAL$[num2septext(taxes+subtotal)] +
" + + var/obj/item/weapon/paper/P = new(loc) + P.name="Receipt #[id]-[++sales]" + P.info=receipt + + P = new(loc) + P.name="Receipt #[id]-[sales] (Cashier Copy)" + P.info=receipt + + +/obj/machinery/pos/proc/LoginScreen() + return "
Please swipe ID to log in.
" + +/obj/machinery/pos/proc/OrderScreen() + var/receipt = {"
+ POS Info + POINT OF SALE #[id]
+ Paying to: [linked_account.owner_name]
+ Cashier: [logged_in]
"} + if(myArea) + receipt += myArea.name + receipt += "
" + receipt += {"
Order Data +
+ + + + + + + + + "} + var/subtotal=0 + if(line_items.len>0) + for(var/i=1;i<=line_items.len;i++) + var/line_item/LI = line_items[i] + var/linetotal=LI.units*LI.price + receipt += {" + + + + + + "} + subtotal += linetotal + var/taxes = POS_TAX_RATE*subtotal + var/presets = "(No presets available)" + if(products.len>0) + presets = {"" + receipt += {" + + + + + + + + + + + "} + receipt += {" + + "} + receipt += {"
ItemAmountUnit PriceLine Total...
[LI.name][LI.units]$[num2septext(LI.price)]$[num2septext(linetotal)]×
[presets] units
SUBTOTAL$[num2septext(subtotal)]
TAXES$[num2septext(taxes)]
TOTAL$[num2septext(taxes+subtotal)] +
+ + +
+
"} + return receipt + +/obj/machinery/pos/proc/ProductsScreen() + var/dat={"
Product List +
+ + + + + + + + "} + for(var/i in products) + var/line_item/LI = products[i] + dat += {" + + + + + "} + dat += {"
ItemUnit Price# Sold...
[LI.name]$[num2septext(LI.price)][LI.units]×
+ New Product:
+
+ $
+
+ Import | Export +
+
"} + return dat + +/obj/machinery/pos/proc/ExportScreen() + var/dat={"
Export Products as CSV + + OK +
"} + return dat + +/obj/machinery/pos/proc/ImportScreen() + var/dat={"
+ Import Products as CSV +
+ + +

Data must be in the form of a CSV, with no headers or quotation marks.

+

First column must be product names, second must be prices as an unformatted number (####.##)

+

Deviations from this format will result in your import being rejected.

+ +
+
"} + return dat + +/obj/machinery/pos/proc/FinalizeScreen() + return "
Waiting for Credit
Cancel
" + +/obj/machinery/pos/proc/SettingsScreen() + var/dat={"
+ +
+ Account Settings +
+ Payable Account: +
+
+
+ Locality Settings +
+ Tax Rate: % (LOCKED) +
+
+ +
"} + return dat + +/obj/machinery/pos/update_icon() + overlays = 0 + if(stat & (NOPOWER|BROKEN)) return + if(logged_in) + overlays += "pos-working" + else + overlays += "pos-standby" + +/obj/machinery/pos/attack_hand(var/mob/user) + user.set_machine(src) + var/logindata="" + if(logged_in) + logindata={"[logged_in.name]"} + var/dat = POS_HEADER + {" + "} + switch(screen) + if(POS_SCREEN_LOGIN) dat += LoginScreen() + if(POS_SCREEN_ORDER) dat += OrderScreen() + if(POS_SCREEN_FINALIZE) dat += FinalizeScreen() + if(POS_SCREEN_PRODUCTS) dat += ProductsScreen() + if(POS_SCREEN_EXPORT) dat += ExportScreen() + if(POS_SCREEN_IMPORT) dat += ImportScreen() + if(POS_SCREEN_SETTINGS) dat += SettingsScreen() + + dat += "" + // END AUTOFIX + user << browse(dat, "window=pos") + onclose(user, "pos") + return + +/obj/machinery/pos/proc/say(var/text) + src.visible_message("\icon[src] [name] states, \"[text]\"") + +/obj/machinery/pos/Topic(var/href, var/list/href_list) + if(..(href,href_list)) return + if("logout" in href_list) + if(alert(src, "You sure you want to log out?", "Confirm", "Yes", "No")!="Yes") return + logged_in=null + screen=POS_SCREEN_LOGIN + update_icon() + src.attack_hand(usr) + return + if(usr != logged_in) + usr << "\red [logged_in.name] is already logged in. You cannot use this machine until they log out." + return + if("act" in href_list) + switch(href_list["act"]) + if("Reset") + NewOrder() + screen=POS_SCREEN_ORDER + if("Finalize Sale") + var/subtotal=0 + if(line_items.len>0) + for(var/i=1;i<=line_items.len;i++) + var/line_item/LI = line_items[i] + subtotal += LI.units*LI.price + var/taxes = POS_TAX_RATE*subtotal + credits_needed=taxes+subtotal + say("Your total is $[num2septext(credits_needed)]. Please insert credit chips or swipe your ID.") + screen=POS_SCREEN_FINALIZE + if("Add Product") + var/line_item/LI = new + LI.name=sanitize(href_list["name"]) + LI.price=text2num(href_list["price"]) + products["[products.len+1]"]=LI + if("Add to Order") + AddToOrder(href_list["preset"],text2num(href_list["units"])) + if("Add Products") + for(var/list/line in text2list(href_list["csv"],"\n")) + var/list/cells = text2list(line,",") + if(cells.len<2) + usr << "\red The CSV must have at least two columns: Product Name, followed by Price (as a number)." + src.attack_hand(usr) + return + var/line_item/LI = new + LI.name=sanitize(cells[1]) + LI.price=text2num(cells[2]) + products["[products.len+1]"]=LI + if("Export Products") + screen=POS_SCREEN_EXPORT + if("Import Products") + screen=POS_SCREEN_IMPORT + if("Save Settings") + var/datum/money_account/new_linked_account = get_money_account(text2num(href_list["payableto"]),z) + if(!new_linked_account) + usr << "\red Unable to link new account." + else + linked_account = new_linked_account + screen=POS_SCREEN_SETTINGS + else if("screen" in href_list) + screen=text2num(href_list["screen"]) + else if("rmproduct" in href_list) + products.Remove(href_list["rmproduct"]) + else if("removefromorder" in href_list) + RemoveFromOrder(text2num(href_list["removefromorder"])) + else if("setunits" in href_list) + var/lid = text2num(href_list["setunits"]) + var/newunits = input(usr,"Enter the units sold.") as num + if(!newunits) return + var/line_item/LI = line_items[lid] + LI.units = newunits + line_items[lid]=LI + else if("setpname" in href_list) + var/newtext = sanitize(input(usr,"Enter the product's name.")) + if(!newtext) return + var/pid = href_list["setpname"] + var/line_item/LI = products[pid] + LI.name = newtext + products[pid]=LI + else if("setprice" in href_list) + var/newprice = input(usr,"Enter the product's price.") as num + if(!newprice) return + var/pid = href_list["setprice"] + var/line_item/LI = products[pid] + LI.price = newprice + products[pid]=LI + src.attack_hand(usr) + +/obj/machinery/pos/attackby(var/atom/movable/A, var/mob/user, params) + if(istype(A,/obj/item/weapon/card/id)) + var/obj/item/weapon/card/id/I = A + if(!logged_in) + user.visible_message("\blue The machine beeps, and logs you in","You hear a beep.") + logged_in = user + screen=POS_SCREEN_ORDER + update_icon() + src.attack_hand(user) //why'd you use usr nexis, why + return + else + if(!linked_account) + visible_message("\red The machine buzzes, and flashes \"NO LINKED ACCOUNT\" on the screen.","You hear a buzz.") + flick(src,"pos-error") + return + if(screen!=POS_SCREEN_FINALIZE) + visible_message("\blue The machine buzzes.","\red You hear a buzz.") + flick(src,"pos-error") + return + var/datum/money_account/acct = get_card_account(I) + if(!acct) + visible_message("\red The machine buzzes, and flashes \"NO ACCOUNT\" on the screen.","You hear a buzz.") + flick(src,"pos-error") + return + if(credits_needed > acct.money) + visible_message("\red The machine buzzes, and flashes \"NOT ENOUGH FUNDS\" on the screen.","You hear a buzz.") + flick(src,"pos-error") + return + visible_message("\blue The machine beeps, and begins printing a receipt","You hear a beep.") + PrintReceipt() + NewOrder() + acct.charge(credits_needed,linked_account,"Purchase at POS #[id].") + credits_needed=0 + screen=POS_SCREEN_ORDER + else if(istype(A,/obj/item/weapon/spacecash)) + if(!linked_account) + visible_message("\red The machine buzzes, and flashes \"NO LINKED ACCOUNT\" on the screen.","You hear a buzz.") + flick(src,"pos-error") + return + if(!logged_in || screen!=POS_SCREEN_FINALIZE) + visible_message("\blue The machine buzzes.","\red You hear a buzz.") + flick(src,"pos-error") + return + var/obj/item/weapon/spacecash/C=A + credits_held += C.get_total() + if(credits_held >= credits_needed) + visible_message("\blue The machine beeps, and begins printing a receipt","You hear a beep and the sound of paper being shredded.") + PrintReceipt() + NewOrder() + credits_held -= credits_needed + credits_needed=0 + screen=POS_SCREEN_ORDER + if(credits_held) + var/obj/item/weapon/storage/box/B = new(loc) + dispense_cash(credits_held,B) + B.name="change" + B.desc="A box of change." + credits_held=0 + ..() diff --git a/code/modules/economy/cash.dm b/code/modules/economy/cash.dm index 0703eb5deaa..c90ee6aa62e 100644 --- a/code/modules/economy/cash.dm +++ b/code/modules/economy/cash.dm @@ -1,66 +1,50 @@ -/obj/item/weapon/spacecash - name = "0 credit chip" - desc = "It's worth 0 credits." - gender = PLURAL - icon = 'icons/obj/items.dmi' - icon_state = "spacecash" - opacity = 0 - density = 0 - anchored = 0.0 - force = 1.0 - throwforce = 1.0 - throw_speed = 1 - throw_range = 2 - w_class = 1.0 - var/access = list() - access = access_crate_cash - var/worth = 0 - -/obj/item/weapon/spacecash/c1 - name = "1 credip chip" - icon_state = "spacecash" - desc = "It's worth 1 credit." - worth = 1 - -/obj/item/weapon/spacecash/c10 - name = "10 credit chip" - icon_state = "spacecash10" - desc = "It's worth 10 credits." - worth = 10 - -/obj/item/weapon/spacecash/c20 - name = "20 credit chip" - icon_state = "spacecash20" - desc = "It's worth 20 credits." - worth = 20 - -/obj/item/weapon/spacecash/c50 - name = "50 credit chip" - icon_state = "spacecash50" - desc = "It's worth 50 credits." - worth = 50 - -/obj/item/weapon/spacecash/c100 - name = "100 credit chip" - icon_state = "spacecash100" - desc = "It's worth 100 credits." - worth = 100 - -/obj/item/weapon/spacecash/c200 - name = "200 credit chip" - icon_state = "spacecash200" - desc = "It's worth 200 credits." - worth = 200 - -/obj/item/weapon/spacecash/c500 - name = "500 credit chip" - icon_state = "spacecash500" - desc = "It's worth 500 credits." - worth = 500 - -/obj/item/weapon/spacecash/c1000 - name = "1000 credit chip" - icon_state = "spacecash1000" - desc = "It's worth 1000 credits." - worth = 1000 - +/obj/item/weapon/spacecash + name = "0 credit chip" + desc = "It's worth 0 credits." + gender = PLURAL + icon = 'icons/obj/items.dmi' + icon_state = "spacecash" + opacity = 0 + density = 0 + anchored = 0.0 + force = 1.0 + throwforce = 1.0 + throw_speed = 1 + throw_range = 2 + w_class = 1.0 + var/access = list() + access = access_crate_cash + var/worth = 0 + +/obj/item/weapon/spacecash/c1 + icon_state = "spacecash" + worth = 1 + +/obj/item/weapon/spacecash/c10 + icon_state = "spacecash10" + worth = 10 + +/obj/item/weapon/spacecash/c20 + icon_state = "spacecash20" + worth = 20 + +/obj/item/weapon/spacecash/c50 + icon_state = "spacecash50" + worth = 50 + +/obj/item/weapon/spacecash/c100 + icon_state = "spacecash100" + worth = 100 + +/obj/item/weapon/spacecash/c200 + icon_state = "spacecash200" + worth = 200 + +/obj/item/weapon/spacecash/c500 + icon_state = "spacecash500" + worth = 500 + +/obj/item/weapon/spacecash/c1000 + icon_state = "spacecash1000" + worth = 1000 +