Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into tgui-alerts-and-what-not
This commit is contained in:
@@ -326,7 +326,7 @@ SUBSYSTEM_DEF(vote)
|
||||
return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.")
|
||||
GLOB.master_mode = "dynamic"
|
||||
if(. == "extended")
|
||||
GLOB.dynamic_forced_extended = TRUE
|
||||
GLOB.dynamic_extended = TRUE
|
||||
message_admins("The gamemode has been voted for, and has been changed to: [GLOB.master_mode]")
|
||||
log_admin("Gamemode has been voted for and switched to: [GLOB.master_mode].")
|
||||
if("restart")
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
GAS_N2=10,
|
||||
)
|
||||
normal_gases = list(
|
||||
GAS_O2=10,
|
||||
GAS_N2=10,
|
||||
GAS_CO2=10,
|
||||
GAS_O2=5,
|
||||
GAS_N2=5,
|
||||
GAS_CO2=5,
|
||||
)
|
||||
restricted_gases = list(
|
||||
GAS_BZ=0.1,
|
||||
|
||||
@@ -295,6 +295,16 @@
|
||||
/obj/item/stack/sheet/sinew = 1)
|
||||
category = CAT_PRIMAL
|
||||
|
||||
/datum/crafting_recipe/bone_anvil
|
||||
name = "Bone Anvil"
|
||||
result = /obj/structure/anvil/obtainable/bone
|
||||
time = 200
|
||||
reqs = list(/obj/item/stack/sheet/bone = 6,
|
||||
/obj/item/stack/sheet/sinew = 2,
|
||||
/obj/item/stack/sheet/animalhide/goliath_hide = 2)
|
||||
tools = list(/obj/item/weldingtool/experimental/ashwalker, /obj/item/wirecutters/ashwalker, /obj/item/crowbar/ashwalker)
|
||||
category = CAT_PRIMAL
|
||||
|
||||
/datum/crafting_recipe/bone_glaive
|
||||
name = "Necropolis Glaive"
|
||||
result = /obj/item/kinetic_crusher/glaive/bone
|
||||
|
||||
@@ -362,6 +362,7 @@ Unless you know what you're doing, only use the first three numbers. They're in
|
||||
color = "#e3dac9"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/bone
|
||||
strength_modifier = 1.05
|
||||
value_per_unit = 0.05
|
||||
armor_modifiers = list("melee" = 1.2, "bullet" = 0.75, "laser" = 0.75, "energy" = 1.2, "bomb" = 1, "bio" = 1, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5)
|
||||
beauty_modifier = -0.2
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#define RULESET_STOP_PROCESSING 1
|
||||
|
||||
#define FAKE_REPORT_CHANCE 8
|
||||
#define FAKE_REPORT_CHANCE 20
|
||||
#define REPORT_NEG_DIVERGENCE -15
|
||||
#define REPORT_POS_DIVERGENCE 15
|
||||
#define EXTENDED_CURVE_CENTER -7
|
||||
|
||||
// Are HIGH_IMPACT_RULESETs allowed to stack?
|
||||
GLOBAL_VAR_INIT(dynamic_no_stacking, TRUE)
|
||||
// If enabled does not accept or execute any rulesets.
|
||||
GLOBAL_VAR_INIT(dynamic_forced_extended, FALSE)
|
||||
// Antags still allowed, but no roundstart antags + midrounds are low impact
|
||||
GLOBAL_VAR_INIT(dynamic_extended, FALSE)
|
||||
// How high threat is required for HIGH_IMPACT_RULESETs stacking.
|
||||
// This is independent of dynamic_no_stacking.
|
||||
GLOBAL_VAR_INIT(dynamic_stacking_limit, 90)
|
||||
@@ -163,6 +166,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
dat += "Split parameters: centre = [roundstart_split_curve_centre] ; width = [roundstart_split_curve_width].<br/>"
|
||||
dat += "<i>On average, <b>[peaceful_percentage]</b>% of the rounds are more peaceful.</i><br/>"
|
||||
dat += "Forced extended: <a href='?src=\ref[src];[HrefToken()];forced_extended=1'><b>[GLOB.dynamic_forced_extended ? "On" : "Off"]</b></a><br/>"
|
||||
dat += "Dynamic extended: <a href='?src=\ref[src];[HrefToken()];extended=1'><b>[GLOB.dynamic_extended ? "On" : "Off"]</b></a><br/>"
|
||||
dat += "No stacking (only one round-ender): <a href='?src=\ref[src];[HrefToken()];no_stacking=1'><b>[GLOB.dynamic_no_stacking ? "On" : "Off"]</b></a><br/>"
|
||||
dat += "Stacking limit: [GLOB.dynamic_stacking_limit] <a href='?src=\ref[src];[HrefToken()];stacking_limit=1'>\[Adjust\]</A>"
|
||||
dat += "<br/>"
|
||||
@@ -192,6 +196,8 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
return
|
||||
if (href_list["forced_extended"])
|
||||
GLOB.dynamic_forced_extended = !GLOB.dynamic_forced_extended
|
||||
else if (href_list["extended"])
|
||||
GLOB.dynamic_extended = !GLOB.dynamic_extended
|
||||
else if (href_list["no_stacking"])
|
||||
GLOB.dynamic_no_stacking = !GLOB.dynamic_no_stacking
|
||||
else if (href_list["adjustthreat"])
|
||||
@@ -309,9 +315,10 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
|
||||
/// Generates the threat level using lorentz distribution and assigns peaceful_percentage.
|
||||
/datum/game_mode/dynamic/proc/generate_threat()
|
||||
if(GLOB.dynamic_extended)
|
||||
threat_curve_centre = EXTENDED_CURVE_CENTER
|
||||
var/relative_threat = LORENTZ_DISTRIBUTION(threat_curve_centre, threat_curve_width)
|
||||
threat_level = round(lorentz_to_amount(relative_threat), 0.1)
|
||||
|
||||
peaceful_percentage = round(LORENTZ_CUMULATIVE_DISTRIBUTION(relative_threat, threat_curve_centre, threat_curve_width), 0.01)*100
|
||||
|
||||
SSblackbox.record_feedback("tally","dynamic_threat",threat_level,"Initial threat level")
|
||||
@@ -321,14 +328,18 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
|
||||
/// Generates the midround and roundstart budgets
|
||||
/datum/game_mode/dynamic/proc/generate_budgets()
|
||||
var/relative_round_start_budget_scale = LORENTZ_DISTRIBUTION(roundstart_split_curve_centre, roundstart_split_curve_width)
|
||||
round_start_budget = round((lorentz_to_amount(relative_round_start_budget_scale) / 100) * threat_level, 0.1)
|
||||
initial_round_start_budget = round_start_budget
|
||||
mid_round_budget = threat_level - round_start_budget
|
||||
if(GLOB.dynamic_extended)
|
||||
mid_round_budget = threat_level
|
||||
round_start_budget = 0
|
||||
else
|
||||
var/relative_round_start_budget_scale = LORENTZ_DISTRIBUTION(roundstart_split_curve_centre, roundstart_split_curve_width)
|
||||
round_start_budget = round((lorentz_to_amount(relative_round_start_budget_scale) / 100) * threat_level, 0.1)
|
||||
initial_round_start_budget = round_start_budget
|
||||
mid_round_budget = threat_level - round_start_budget
|
||||
|
||||
/datum/game_mode/dynamic/proc/setup_parameters()
|
||||
log_game("DYNAMIC: Dynamic mode parameters for the round:")
|
||||
log_game("DYNAMIC: Centre is [threat_curve_centre], Width is [threat_curve_width], Forced extended is [GLOB.dynamic_forced_extended ? "Enabled" : "Disabled"], No stacking is [GLOB.dynamic_no_stacking ? "Enabled" : "Disabled"].")
|
||||
log_game("DYNAMIC: Centre is [threat_curve_centre], Width is [threat_curve_width], Extended is [GLOB.dynamic_extended ? "Enabled" : "Disabled"], No stacking is [GLOB.dynamic_no_stacking ? "Enabled" : "Disabled"].")
|
||||
log_game("DYNAMIC: Stacking limit is [GLOB.dynamic_stacking_limit].")
|
||||
if(GLOB.dynamic_forced_threat_level >= 0)
|
||||
threat_level = round(GLOB.dynamic_forced_threat_level, 0.1)
|
||||
@@ -346,9 +357,15 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
shown_threat = clamp(threat_level + rand(REPORT_NEG_DIVERGENCE, REPORT_POS_DIVERGENCE), 0, 100)
|
||||
|
||||
/datum/game_mode/dynamic/proc/set_cooldowns()
|
||||
var/coeff = GLOB.dynamic_extended ? 2 : 1
|
||||
latejoin_delay_min *= coeff
|
||||
latejoin_delay_max *= coeff
|
||||
var/latejoin_injection_cooldown_middle = 0.5*(latejoin_delay_max + latejoin_delay_min)
|
||||
latejoin_injection_cooldown = round(clamp(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), latejoin_delay_min, latejoin_delay_max)) + world.time
|
||||
|
||||
midround_delay_min *= coeff
|
||||
midround_delay_max *= coeff
|
||||
|
||||
var/midround_injection_cooldown_middle = 0.5*(midround_delay_max + midround_delay_min)
|
||||
midround_injection_cooldown = round(clamp(EXP_DISTRIBUTION(midround_injection_cooldown_middle), midround_delay_min, midround_delay_max)) + world.time
|
||||
|
||||
@@ -456,6 +473,9 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
if (GLOB.dynamic_forced_extended)
|
||||
log_game("DYNAMIC: Starting a round of forced extended.")
|
||||
return TRUE
|
||||
if (GLOB.dynamic_extended)
|
||||
log_game("DYNAMIC: Starting a round of dynamic extended.")
|
||||
return TRUE
|
||||
var/list/drafted_rules = list()
|
||||
for (var/datum/dynamic_ruleset/roundstart/rule in roundstart_rules)
|
||||
if (!rule.weight)
|
||||
@@ -563,9 +583,10 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
return FALSE
|
||||
// Check if the ruleset is high impact and if a high impact ruleset has been executed
|
||||
else if(new_rule.flags & HIGH_IMPACT_RULESET)
|
||||
if(threat_level < GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
|
||||
if(high_impact_ruleset_executed)
|
||||
return FALSE
|
||||
if(GLOB.dynamic_extended)
|
||||
return FALSE
|
||||
if(high_impact_ruleset_executed && threat_level < GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
|
||||
return FALSE
|
||||
|
||||
var/population = current_players[CURRENT_LIVING_PLAYERS].len
|
||||
if((new_rule.acceptable(population, threat_level) && new_rule.cost <= mid_round_budget) || forced)
|
||||
@@ -598,8 +619,8 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
/datum/game_mode/dynamic/proc/midround_rule_draft()
|
||||
set waitfor = FALSE
|
||||
if (midround_injection_cooldown < world.time)
|
||||
/*if (GLOB.dynamic_forced_extended)
|
||||
return*/
|
||||
if (GLOB.dynamic_forced_extended)
|
||||
return
|
||||
|
||||
// Somehow it managed to trigger midround multiple times so this was moved here.
|
||||
// There is no way this should be able to trigger an injection twice now.
|
||||
@@ -620,6 +641,11 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
for (var/datum/dynamic_ruleset/midround/rule in midround_rules)
|
||||
if (!rule.weight)
|
||||
continue
|
||||
if(rule.flags & HIGH_IMPACT_RULESET)
|
||||
if (high_impact_ruleset_executed && threat_level < GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
|
||||
continue
|
||||
if(GLOB.dynamic_extended)
|
||||
continue
|
||||
if (rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && mid_round_budget >= rule.cost)
|
||||
rule.trim_candidates()
|
||||
if (rule.ready())
|
||||
@@ -642,11 +668,17 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
forced_injection = dry_run
|
||||
return 100
|
||||
var/chance = 0
|
||||
var/max_pop_per_antag = max(5,15 - round(threat_level/10) - round(current_players[CURRENT_LIVING_PLAYERS].len/5))
|
||||
var/effective_living_players = current_players[CURRENT_LIVING_PLAYERS].len
|
||||
if(GLOB.dynamic_extended)
|
||||
effective_living_players = min(effective_living_players, length(SSjob.get_living_sec())*2 + length(SSjob.get_living_heads()))
|
||||
var/max_pop_per_antag = max(5,15 - round(threat_level/10) - round(effective_living_players/5))
|
||||
if (!current_players[CURRENT_LIVING_ANTAGS].len)
|
||||
chance += 50 // No antags at all? let's boost those odds!
|
||||
if(GLOB.dynamic_extended)
|
||||
chance += min(50,effective_living_players*5)
|
||||
else
|
||||
chance += 50 // No antags at all? let's boost those odds!
|
||||
else
|
||||
var/current_pop_per_antag = current_players[CURRENT_LIVING_PLAYERS].len / current_players[CURRENT_LIVING_ANTAGS].len
|
||||
var/current_pop_per_antag = effective_living_players / current_players[CURRENT_LIVING_ANTAGS].len
|
||||
if (current_pop_per_antag > max_pop_per_antag)
|
||||
chance += min(50, 25+10*(current_pop_per_antag-max_pop_per_antag))
|
||||
else
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
// like a recycler, but for plants only ig
|
||||
/obj/machinery/autoloom
|
||||
name = "autoloom"
|
||||
desc = "A large processing machine used to process raw biological matter, like cotton or logs. It also looks like a recycler. There's a display on the side."
|
||||
icon = 'icons/obj/recycling.dmi'
|
||||
icon_state = "grinder-o0"
|
||||
layer = ABOVE_ALL_MOB_LAYER // Overhead
|
||||
density = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/autoloom
|
||||
var/icon_name = "grinder-o"
|
||||
var/eat_dir = WEST
|
||||
var/process_efficiency = 0
|
||||
var/static/list/can_process = typecacheof(list(
|
||||
/obj/item/stack/sheet/cotton,
|
||||
/obj/item/grown/log,
|
||||
/obj/item/grown/cotton
|
||||
))
|
||||
|
||||
/obj/machinery/autoloom/RefreshParts()
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
process_efficiency = M.rating
|
||||
|
||||
/obj/machinery/recycler/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Biomatter processing efficiency at <b>[amount_produced*100]%</b>.</span>"
|
||||
|
||||
/obj/machinery/autoloom/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/autoloom/attackby(obj/item/I, mob/user, params)
|
||||
if(default_deconstruction_screwdriver(user, "grinder-oOpen", "grinder-o0", I))
|
||||
return
|
||||
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
|
||||
if(default_unfasten_wrench(user, I))
|
||||
return
|
||||
|
||||
if(default_deconstruction_crowbar(I))
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/autoloom/update_icon_state()
|
||||
var/is_powered = !(stat & (BROKEN|NOPOWER))
|
||||
icon_state = icon_name + "[is_powered]" // add the blood tag at the end
|
||||
|
||||
/obj/machinery/autoloom/CanPass(atom/movable/AM)
|
||||
. = ..()
|
||||
if(!anchored)
|
||||
return
|
||||
|
||||
var/move_dir = get_dir(loc, AM.loc)
|
||||
if(move_dir == eat_dir)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/autoloom/Crossed(atom/movable/AM)
|
||||
eat(AM)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/autoloom/proc/eat(atom/movable/AM0, sound=TRUE)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
if(!isturf(AM0.loc))
|
||||
return //I don't know how you called Crossed() but stop it.
|
||||
|
||||
if(is_type_in_list(AM0, can_process))
|
||||
process_item(AM0)
|
||||
|
||||
/obj/machinery/autoloom/proc/process_item(obj/item/I)
|
||||
. = list()
|
||||
for(var/A in I)
|
||||
var/atom/movable/AM = A
|
||||
AM.forceMove(loc)
|
||||
if(AM.loc == loc)
|
||||
. += AM
|
||||
|
||||
I.forceMove(loc)
|
||||
if(istype(I, /obj/item/grown/log))
|
||||
var/obj/item/grown/log/L = I
|
||||
var/seed_modifier = 0
|
||||
if(L.seed)
|
||||
seed_modifier = round(L.seed.potency / 25)
|
||||
new L.plank_type(src.loc, process_efficiency + seed_modifier)
|
||||
qdel(L)
|
||||
return
|
||||
|
||||
if(istype(I, /obj/item/stack/sheet/cotton))
|
||||
var/obj/item/stack/sheet/cotton/RS = I
|
||||
var/tomake = round((RS.amount / 4) * process_efficiency)
|
||||
new RS.loom_result(src.loc, tomake)
|
||||
qdel(RS)
|
||||
return
|
||||
|
||||
if(istype(I, /obj/item/grown/cotton))
|
||||
var/obj/item/grown/cotton/RC = I
|
||||
var/cottonAmt = 1 + round(RC.seed.potency / 25)
|
||||
var/newRaw = new RC.cotton_type(src.loc, cottonAmt)
|
||||
qdel(RC)
|
||||
process_item(newRaw)
|
||||
return
|
||||
@@ -82,9 +82,8 @@ GLOBAL_LIST_INIT(arcade_prize_pool, list(
|
||||
// If it's a generic arcade machine, pick a random arcade
|
||||
// circuit board for it and make the new machine
|
||||
if(!circuit)
|
||||
var/list/gameodds = list(/obj/item/circuitboard/computer/arcade/battle = 33,
|
||||
/obj/item/circuitboard/computer/arcade/orion_trail = 33,
|
||||
/obj/item/circuitboard/computer/arcade/minesweeper = 33,
|
||||
var/list/gameodds = list(/obj/item/circuitboard/computer/arcade/battle = 50,
|
||||
/obj/item/circuitboard/computer/arcade/orion_trail = 50,
|
||||
/obj/item/circuitboard/computer/arcade/amputation = 2)
|
||||
var/thegame = pickweight(gameodds)
|
||||
var/obj/item/circuitboard/CB = new thegame()
|
||||
|
||||
@@ -1,413 +0,0 @@
|
||||
#define MINESWEEPER_GAME_MAIN_MENU 0
|
||||
#define MINESWEEPER_GAME_PLAYING 1
|
||||
#define MINESWEEPER_GAME_LOST 2
|
||||
#define MINESWEEPER_GAME_WON 3
|
||||
#define MINESWEEPERIMG(what) {"<img style='border:0' <span class="minesweeper16x16 [#what]"></span>"} //Basically bypassing asset.icon_tag()
|
||||
|
||||
/obj/machinery/computer/arcade/minesweeper
|
||||
name = "Minesweeper"
|
||||
desc = "An arcade machine that generates grids. It seems that the machine sparks and screeches when a grid is generated, as if it cannot cope with the intensity of generating the grid."
|
||||
icon_state = "arcade"
|
||||
circuit = /obj/item/circuitboard/computer/arcade/minesweeper
|
||||
var/area
|
||||
var/difficulty = "" //To show what difficulty you are playing
|
||||
var/flag_text = ""
|
||||
var/flagging = FALSE
|
||||
var/game_status = MINESWEEPER_GAME_MAIN_MENU
|
||||
var/mine_limit = 0
|
||||
var/mine_placed = 0
|
||||
var/mine_sound = TRUE //So it doesn't get repeated when multiple mines are exposed
|
||||
var/randomcolour = 1
|
||||
var/randomnumber = 1 //Random emagged game iteration number to be displayed, put here so it is persistent across one individual arcade machine
|
||||
var/safe_squares_revealed
|
||||
var/saved_web = "" //To display the web if you click on the arcade
|
||||
var/win_condition
|
||||
var/rows = 1
|
||||
var/columns = 1
|
||||
var/table[31][51] //Make the board boys, 30x50 board
|
||||
var/spark_spam = FALSE
|
||||
|
||||
/obj/machinery/computer/arcade/minesweeper/interact(mob/user)
|
||||
var/emagged = CHECK_BITFIELD(obj_flags, EMAGGED)
|
||||
var/dat
|
||||
if(game_status == MINESWEEPER_GAME_MAIN_MENU)
|
||||
dat += "<head><title>Minesweeper</title></head><div align='center'><b>Minesweeper[emagged ? " <font color='red'>EXTREME EDITION</font>: Iteration <font color='[randomcolour]'>#[randomnumber]</font>" : ""]</b><br>" //Different colour mix for every random number made
|
||||
dat += "<font size='2'> [emagged ? "Explode in the game, explode in real life" : "Reveal all the squares without hitting a mine"]!<br>What difficulty do you want to play?<br><br><br><br><b><a href='byond://?src=[REF(src)];Easy=1'><font color='#cc66ff'>Easy (9x9 board, 10 mines)</font></a><br><a href='byond://?src=[REF(src)];Intermediate=1'><font color='#cc66ff'>Intermediate (16x16 board, 40 mines)</font></a><br><a href='byond://?src=[REF(src)];Hard=1'><font color='#cc66ff'>Hard (16x30 board, 99 mines)</font></a><br><a href='byond://?src=[REF(src)];Custom=1'><font color='#cc66ff'>Custom</font>"
|
||||
else
|
||||
dat = saved_web
|
||||
user = usr
|
||||
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/simple/minesweeper)
|
||||
assets.send(user)
|
||||
|
||||
user << browse(dat,"window=minesweeper,size=400x500")
|
||||
add_fingerprint(user)
|
||||
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/computer/arcade/minesweeper/proc/reset_spark_spam()
|
||||
spark_spam = FALSE
|
||||
|
||||
/obj/machinery/computer/arcade/minesweeper/Topic(href, href_list)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
var/exploding_hell = FALSE //For emagged failures
|
||||
var/reset_board = FALSE
|
||||
var/mob/living/user = usr //To identify who the hell is using this window, this should also make things like aliens and monkeys able to use the machine!!
|
||||
var/web_difficulty_menu = "<font size='2'> Reveal all the squares without hitting a mine!<br>What difficulty do you want to play?<br><br><br><br><b><a href='byond://?src=[REF(src)];Easy=1'><font color='#cc66ff'>Easy (9x9 board, 10 mines)</font></a><br><a href='byond://?src=[REF(src)];Intermediate=1'><font color='#cc66ff'>Intermediate (16x16 board, 40 mines)</font></a><br><a href='byond://?src=[REF(src)];Hard=1'><font color='#cc66ff'>Hard (16x30 board, 99 mines)</font></a><br><a href='byond://?src=[REF(src)];Custom=1'><font color='#cc66ff'>Custom</font>"
|
||||
var/web = "<head><title>Minesweeper</title></head><div align='center'><b>Minesweeper</b><br>"
|
||||
var/static_web = "<head><title>Minesweeper</title></head><div align='center'><b>Minesweeper</b><br>" //When we need to revert to the main menu we set web as this
|
||||
web = static_web
|
||||
|
||||
if(CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
web = "<head><title>Minesweeper</title></head><body><div align='center'><b>Minesweeper <font color='red'>EXTREME EDITION</font>: Iteration <font color='[randomcolour]'>#[randomnumber]</font></b><br>" //Different colour mix for every random number made
|
||||
if(!spark_spam)
|
||||
do_sparks(5, 1, src)
|
||||
spark_spam = TRUE
|
||||
addtimer(CALLBACK(src, .proc/reset_spark_spam), 30)
|
||||
|
||||
|
||||
var/startup_sound = CHECK_BITFIELD(obj_flags, EMAGGED) ? 'sound/arcade/minesweeper_emag2.ogg' : 'sound/arcade/minesweeper_startup.ogg'
|
||||
|
||||
if(href_list["Main_Menu"])
|
||||
game_status = MINESWEEPER_GAME_MAIN_MENU
|
||||
mine_limit = 0
|
||||
rows = 0
|
||||
columns = 0
|
||||
mine_placed = 0
|
||||
if(href_list["Easy"])
|
||||
playsound(loc, startup_sound, 50, FALSE, extrarange = -3)
|
||||
flag_text = "OFF"
|
||||
game_status = MINESWEEPER_GAME_PLAYING
|
||||
reset_board = TRUE
|
||||
difficulty = "Easy"
|
||||
rows = 10 //9x9 board
|
||||
columns = 10
|
||||
mine_limit = 10
|
||||
if(href_list["Intermediate"])
|
||||
playsound(loc, startup_sound, 50, FALSE, extrarange = -3)
|
||||
flag_text = "OFF"
|
||||
game_status = MINESWEEPER_GAME_PLAYING
|
||||
reset_board = TRUE
|
||||
difficulty = "Intermediate"
|
||||
rows = 17 //16x16 board
|
||||
columns = 17
|
||||
mine_limit = 40
|
||||
if(href_list["Hard"])
|
||||
playsound(loc, startup_sound, 50, FALSE, extrarange = -3)
|
||||
flag_text = "OFF"
|
||||
game_status = MINESWEEPER_GAME_PLAYING
|
||||
reset_board = TRUE
|
||||
difficulty = "Hard"
|
||||
rows = 17 //16x30 board
|
||||
columns = 31
|
||||
mine_limit = 99
|
||||
if(href_list["Custom"])
|
||||
if(custom_generation(usr))
|
||||
flag_text = "OFF"
|
||||
game_status = MINESWEEPER_GAME_PLAYING
|
||||
reset_board = TRUE
|
||||
difficulty = "Custom"
|
||||
playsound(loc, startup_sound, 50, FALSE, extrarange = -3)
|
||||
if(href_list["Flag"])
|
||||
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, FALSE, extrarange = -3)
|
||||
if(!flagging)
|
||||
flagging = TRUE
|
||||
flag_text = "ON"
|
||||
else
|
||||
flagging = FALSE
|
||||
flag_text = "OFF"
|
||||
|
||||
if(game_status == MINESWEEPER_GAME_MAIN_MENU)
|
||||
if(CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
playsound(loc, 'sound/arcade/minesweeper_emag2.ogg', 50, FALSE, extrarange = -3)
|
||||
web += "<font size='2'>Explode in the game, explode in real life!<br>What difficulty do you want to play?<br><br><br><br><b><a href='byond://?src=[REF(src)];Easy=1'><font color='#cc66ff'>Easy (9x9 board, 10 mines)</font></a><br><a href='byond://?src=[REF(src)];Intermediate=1'><font color='#cc66ff'>Intermediate (16x16 board, 40 mines)</font></a><br><a href='byond://?src=[REF(src)];Hard=1'><font color='#cc66ff'>Hard (16x30 board, 99 mines)</font></a><br><a href='byond://?src=[REF(src)];Custom=1'><font color='#cc66ff'>Custom</font>"
|
||||
else
|
||||
playsound(loc, 'sound/arcade/minesweeper_startup.ogg', 50, FALSE, extrarange = -3)
|
||||
web += web_difficulty_menu
|
||||
|
||||
if(game_status == MINESWEEPER_GAME_PLAYING)
|
||||
mine_sound = TRUE
|
||||
|
||||
area = (rows-1)*(columns-1)
|
||||
|
||||
if(reset_board)
|
||||
mine_placed = 0
|
||||
var/reset_everything = TRUE
|
||||
make_mines(reset_everything)
|
||||
|
||||
safe_squares_revealed = 0
|
||||
win_condition = area-mine_placed
|
||||
|
||||
if(game_status != MINESWEEPER_GAME_MAIN_MENU)
|
||||
for(var/y1=1;y1<rows;y1++)
|
||||
for(var/x1=1;x1<columns;x1++)
|
||||
var/coordinates
|
||||
coordinates = (y1*100)+x1
|
||||
if(href_list["[coordinates]"])
|
||||
if(game_status == MINESWEEPER_GAME_PLAYING) //Don't do anything if we won or something
|
||||
if(!flagging)
|
||||
if(table[y1][x1] < 10 && table[y1][x1] >= 0) //Check that it's not already revealed, and stop flag removal if we're out of flag mode
|
||||
table[y1][x1] += 10
|
||||
if(table[y1][x1] != 10)
|
||||
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, FALSE, extrarange = -3)
|
||||
else
|
||||
if(game_status != MINESWEEPER_GAME_LOST && game_status != MINESWEEPER_GAME_WON)
|
||||
game_status = MINESWEEPER_GAME_LOST
|
||||
if(CHECK_BITFIELD(obj_flags, EMAGGED) && !exploding_hell)
|
||||
exploding_hell = TRUE
|
||||
explode_EVERYTHING()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(mine_sound)
|
||||
switch(rand(1,3)) //Play every time a mine is hit
|
||||
if(1)
|
||||
playsound(loc, 'sound/arcade/minesweeper_explosion1.ogg', 50, FALSE, extrarange = -3)
|
||||
if(2)
|
||||
playsound(loc, 'sound/arcade/minesweeper_explosion2.ogg', 50, FALSE, extrarange = -3)
|
||||
if(3)
|
||||
playsound(loc, 'sound/arcade/minesweeper_explosion3.ogg', 50, FALSE, extrarange = -3)
|
||||
mine_sound = FALSE
|
||||
else
|
||||
playsound(loc, 'sound/arcade/minesweeper_boardpress.ogg', 50, FALSE, extrarange = -3)
|
||||
if(table[y1][x1] >= 0) //Check that it's not already flagged
|
||||
table[y1][x1] -= 10
|
||||
else if(table[y1][x1] < 0) //If flagged, remove the flag
|
||||
table[y1][x1] += 10
|
||||
if(table[y1][x1] > 10 && !reset_board)
|
||||
safe_squares_revealed += 1
|
||||
var/y2 = y1
|
||||
var/x2 = x1
|
||||
work_squares(y2, x2) //Work squares while in this loop so there's less load
|
||||
reset_board = FALSE
|
||||
CHECK_TICK
|
||||
|
||||
web += "<table>" //Start setting up the html table
|
||||
web += "<tbody>"
|
||||
for(var/y1=1;y1<rows;y1++)
|
||||
web += "<tr>"
|
||||
for(var/x1=1;x1<columns;x1++)
|
||||
var/coordinates
|
||||
coordinates = (y1*100)+x1
|
||||
switch(table[y1][x1])
|
||||
if(-10 to -1)
|
||||
if(game_status != MINESWEEPER_GAME_PLAYING)
|
||||
web += "<td>[MINESWEEPERIMG(flag)]</td>"
|
||||
else
|
||||
web += "<td><a href='byond://?src=[REF(src)];[coordinates]=1'>[MINESWEEPERIMG(flag)]</a></td>"
|
||||
if(0)
|
||||
if(game_status != MINESWEEPER_GAME_PLAYING)
|
||||
web += "<td>[MINESWEEPERIMG(mine)]</td>"
|
||||
else
|
||||
web += "<td><a href='byond://?src=[REF(src)];[coordinates]=1'>[MINESWEEPERIMG(hidden)]</a></td>" //Make unique hrefs for every square
|
||||
if(1 to 9)
|
||||
if(game_status != MINESWEEPER_GAME_PLAYING)
|
||||
web += "<td>[MINESWEEPERIMG(hidden)]</td>"
|
||||
else
|
||||
web += "<td><a href='byond://?src=[REF(src)];[coordinates]=1'>[MINESWEEPERIMG(hidden)]</a></td>" //Make unique hrefs for every square
|
||||
if(10)
|
||||
web += "<td>[MINESWEEPERIMG(minehit)]</td>"
|
||||
if(11)
|
||||
web += "<td>[MINESWEEPERIMG(empty)]</td>"
|
||||
if(12)
|
||||
web += "<td>[MINESWEEPERIMG(1)]</td>"
|
||||
if(13)
|
||||
web += "<td>[MINESWEEPERIMG(2)]</td>"
|
||||
if(14)
|
||||
web += "<td>[MINESWEEPERIMG(3)]</td>"
|
||||
if(15)
|
||||
web += "<td>[MINESWEEPERIMG(4)]</td>"
|
||||
if(16)
|
||||
web += "<td>[MINESWEEPERIMG(5)]</td>"
|
||||
if(17)
|
||||
web += "<td>[MINESWEEPERIMG(6)]</td>"
|
||||
if(18)
|
||||
web += "<td>[MINESWEEPERIMG(7)]</td>"
|
||||
if(19)
|
||||
web += "<td>[MINESWEEPERIMG(8)]</td>"
|
||||
CHECK_TICK
|
||||
web += "</tr>"
|
||||
web += "</table>"
|
||||
web += "</tbody>"
|
||||
web += "<br>"
|
||||
|
||||
if(safe_squares_revealed >= win_condition && game_status == MINESWEEPER_GAME_PLAYING)
|
||||
game_status = MINESWEEPER_GAME_WON
|
||||
if(rows < 10 || columns < 10) //If less than easy difficulty
|
||||
playsound(loc, 'sound/arcade/minesweeper_winfail.ogg', 50, FALSE, extrarange = -3)
|
||||
say("You cleared the board of all mines, but you picked too small of a board! Try again with at least a 9x9 board!")
|
||||
else
|
||||
playsound(loc, 'sound/arcade/minesweeper_win.ogg', 50, FALSE, extrarange = -3)
|
||||
say("You cleared the board of all mines! Congratulations!")
|
||||
if(CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
var/itemname
|
||||
switch(rand(1,3))
|
||||
if(1)
|
||||
itemname = "a syndicate bomb beacon"
|
||||
new /obj/item/sbeacondrop/bomb(loc)
|
||||
if(2)
|
||||
itemname = "a rocket launcher"
|
||||
new /obj/item/gun/ballistic/rocketlauncher/unrestricted(loc)
|
||||
new /obj/item/ammo_casing/caseless/rocket(loc)
|
||||
new /obj/item/ammo_casing/caseless/rocket(loc)
|
||||
new /obj/item/ammo_casing/caseless/rocket(loc)
|
||||
if(3)
|
||||
itemname = "two bags of c4"
|
||||
new /obj/item/storage/backpack/duffelbag/syndie/c4(loc)
|
||||
new /obj/item/storage/backpack/duffelbag/syndie/x4(loc)
|
||||
message_admins("[key_name_admin(user)] won emagged Minesweeper and got [itemname]!")
|
||||
visible_message("<span class='notice'>[src] dispenses [itemname]!</span>", "<span class='notice'>You hear a chime and a clunk.</span>")
|
||||
DISABLE_BITFIELD(obj_flags, EMAGGED)
|
||||
else
|
||||
var/dope_prizes = (area >= 480) ? 6 : (area >= 256) ? 4 : 2
|
||||
prizevend(user, dope_prizes)
|
||||
|
||||
if(game_status == MINESWEEPER_GAME_WON)
|
||||
web += "[(rows < 10 || columns < 10) ? "<font size='4'>You won, but your board was too small! Pick a bigger board next time!" : "<font size='6'>Congratulations, you have won!"]<br><font size='3'>Want to play again?<br><b><a href='byond://?src=[REF(src)];Easy=1'><font color='#cc66ff'>Easy (9x9 board, 10 mines)</font></a><br><a href='byond://?src=[REF(src)];Intermediate=1'><font color='#cc66ff'>Intermediate (16x16 board, 40 mines)</font></a><br><a href='byond://?src=[REF(src)];Hard=1'><font color='#cc66ff'>Hard (16x30 board, 99 mines)</font></a><br><a href='byond://?src=[REF(src)];Custom=1'><font color='#cc66ff'>Custom</font></a></b><br><a href='byond://?src=[REF(src)];Main_Menu=1'><font color='#cc66ff'>Return to Main Menu</font></a></b><br>"
|
||||
|
||||
if(game_status == MINESWEEPER_GAME_LOST)
|
||||
web += "<font size='6'>You have lost!<br><font size='3'>Try again?<br><b><a href='byond://?src=[REF(src)];Easy=1'><font color='#cc66ff'>Easy (9x9 board, 10 mines)</font></a><br><a href='byond://?src=[REF(src)];Intermediate=1'><font color='#cc66ff'>Intermediate (16x16 board, 40 mines)</font></a><br><a href='byond://?src=[REF(src)];Hard=1'><font color='#cc66ff'>Hard (16x30 board, 99 mines)</font></a><br><a href='byond://?src=[REF(src)];Custom=1'><font color='#cc66ff'>Custom</font></a></b><br><a href='byond://?src=[REF(src)];Main_Menu=1'><font color='#cc66ff'>Return to Main Menu</font></a></b><br>"
|
||||
|
||||
if(game_status == MINESWEEPER_GAME_PLAYING)
|
||||
web += "<a href='byond://?src=[REF(src)];Main_Menu=1'><font color='#cc66ff'>Return to Main Menu</font></a><br>"
|
||||
web += "<div align='right'>Difficulty: [difficulty]<br>Mines: [mine_placed]<br>Rows: [rows-1]<br>Columns: [columns-1]<br><a href='byond://?src=[REF(src)];Flag=1'><font color='#cc66ff'>Flagging mode: [flag_text]</font></a></div>"
|
||||
|
||||
web += "</div>"
|
||||
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/minesweeper)
|
||||
saved_web = sheet.css_tag()
|
||||
saved_web += web
|
||||
updateDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/arcade/minesweeper/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(CHECK_BITFIELD(obj_flags, EMAGGED))
|
||||
return
|
||||
desc = "An arcade machine that generates grids. It's clunking and sparking everywhere, almost as if threatening to explode at any moment!"
|
||||
do_sparks(5, 1, src)
|
||||
randomnumber = rand(1,255)
|
||||
randomcolour = rgb(randomnumber,randomnumber/2,randomnumber/3)
|
||||
ENABLE_BITFIELD(obj_flags, EMAGGED)
|
||||
if(game_status == MINESWEEPER_GAME_MAIN_MENU)
|
||||
to_chat(user, "<span class='warning'>An ominous tune plays from the arcade's speakers!</span>")
|
||||
playsound(user, 'sound/arcade/minesweeper_emag1.ogg', 100, FALSE, extrarange = 3)
|
||||
else //Can't let you do that, star fox!
|
||||
to_chat(user, "<span class='warning'>The machine buzzes and sparks... the game has been reset!</span>")
|
||||
playsound(user, 'sound/machines/buzz-sigh.ogg', 100, FALSE, extrarange = 3) //Loud buzz
|
||||
game_status = MINESWEEPER_GAME_MAIN_MENU
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/arcade/minesweeper/proc/custom_generation(mob/user)
|
||||
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, FALSE, extrarange = -3) //Entered into the menu so ping sound
|
||||
var/new_rows = tgui_input_num(user, "How many rows do you want? (Minimum: 4, Maximum: 30)", "Minesweeper Rows")
|
||||
if(!new_rows || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return FALSE
|
||||
new_rows = clamp(new_rows + 1, 4, 20)
|
||||
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, FALSE, extrarange = -3)
|
||||
var/new_columns = tgui_input_num(user, "How many columns do you want? (Minimum: 4, Maximum: 50)", "Minesweeper Squares")
|
||||
if(!new_columns || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return FALSE
|
||||
new_columns = clamp(new_columns + 1, 4, 30)
|
||||
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, FALSE, extrarange = -3)
|
||||
var/grid_area = (new_rows - 1) * (new_columns - 1)
|
||||
var/lower_limit = round(grid_area*0.156)
|
||||
var/upper_limit = round(grid_area*0.85)
|
||||
var/new_mine_limit = tgui_input_num(user, "How many mines do you want? (Minimum: [lower_limit], Maximum: [upper_limit])", "Minesweeper Mines")
|
||||
if(!new_mine_limit || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return FALSE
|
||||
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, FALSE, extrarange = -3)
|
||||
rows = new_rows
|
||||
columns = new_columns
|
||||
mine_limit = clamp(new_mine_limit, lower_limit, upper_limit)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/arcade/minesweeper/proc/make_mines(var/reset_everything)
|
||||
if(mine_placed < mine_limit)
|
||||
for(var/y1=1;y1<rows;y1++) //Board resetting and mine building
|
||||
for(var/x1=1;x1<columns;x1++)
|
||||
if(prob(area/mine_limit) && mine_placed < mine_limit && table[y1][x1] != 0) //Unlikely for this to happen but this has eaten mines before
|
||||
table[y1][x1] = 0
|
||||
mine_placed += 1
|
||||
else if(reset_everything)
|
||||
table[y1][x1] = 1
|
||||
reset_everything = FALSE
|
||||
make_mines() //In case the first pass doesn't generate enough mines
|
||||
|
||||
/obj/machinery/computer/arcade/minesweeper/proc/work_squares(var/y2, var/x2, var/y3, var/x3)
|
||||
if(y3 > 0 && x3 > 0)
|
||||
y2 = y3
|
||||
x2 = x3
|
||||
if(table[y2][x2] == 1)
|
||||
for(y3=y2-1;y3<y2+2;y3++)
|
||||
if(y3 >= rows || y3 < 1)
|
||||
continue
|
||||
for(x3=x2-1;x3<x2+2;x3++)
|
||||
if(x3 >= columns || x3 < 1)
|
||||
continue
|
||||
if(table[y3][x3] == 0)
|
||||
table[y2][x2] += 1
|
||||
if(table[y2][x2] == 11)
|
||||
for(y3=y2-1;y3<y2+2;y3++)
|
||||
if(y3 >= rows || y3 < 1)
|
||||
continue
|
||||
for(x3=x2-1;x3<x2+2;x3++)
|
||||
if(x3 >= columns || x3 < 1)
|
||||
continue
|
||||
if(table[y3][x3] > 0 && table[y3][x3] < 10)
|
||||
table[y3][x3] += 10
|
||||
work_squares(y3, x3) //Refresh so we check everything we might be missing
|
||||
|
||||
/obj/machinery/computer/arcade/minesweeper/proc/explode_EVERYTHING()
|
||||
var/mob/living/user = usr
|
||||
to_chat(user, "<span class='boldwarning'>You feel a great sense of dread wash over you, as if you just unleashed armageddon upon yourself!</span>")
|
||||
var/row_limit = rows-1
|
||||
var/column_limit = columns-1
|
||||
var/mine_limit_v2 = mine_limit
|
||||
if(rows > 21)
|
||||
row_limit = 20
|
||||
if(columns > 21)
|
||||
column_limit = 20
|
||||
if(mine_limit > (rows*columns) * 0.25)
|
||||
mine_limit_v2 = 24
|
||||
message_admins("[key_name_admin(user)] failed an emagged Minesweeper arcade and has unleashed an explosion armageddon of size [row_limit],[column_limit] around [ADMIN_LOOKUPFLW(user.loc)]!")
|
||||
if(mine_limit_v2 < 10)
|
||||
explosion(loc, 2, 5, 10, 15) //Thought you could survive by putting as few mines as possible, huh??
|
||||
else
|
||||
explosion(loc, 1, 3, rand(1,5), rand(1,10))
|
||||
var/list/targets = list()
|
||||
var/cur_y = y - round(row_limit * 0.5, 1)
|
||||
var/starting_row = 1
|
||||
if(cur_y < 1)
|
||||
starting_row -= cur_y - 1
|
||||
cur_y = 1
|
||||
var/start_x = x - round(column_limit * 0.5, 1)
|
||||
var/starting_column = 1
|
||||
if(start_x < 1)
|
||||
starting_column -= start_x - 1
|
||||
start_x = 1
|
||||
for(var/row in starting_row to length(table)) //translate the mines locations into actual turf coordinates.
|
||||
if(!locate(cur_y, start_x, z))
|
||||
break
|
||||
var/cur_x = start_x
|
||||
for(var/column in starting_column to length(table[row]))
|
||||
var/coord_value = table[row][column]
|
||||
if(coord_value == 10 || coord_value == 0) //there is a mine in here.
|
||||
var/turf/T = locate(cur_y, cur_x, z)
|
||||
if(!T)
|
||||
break
|
||||
targets += T
|
||||
cur_x++
|
||||
cur_y++
|
||||
var/num_explosions = 0
|
||||
for(var/T in shuffle(targets)) //Create a shitton of explosions in irl turfs if we lose, it will probably kill us
|
||||
addtimer(CALLBACK(GLOBAL_PROC, /proc/explosion, T, 0, rand(1,2),rand(1,5),rand(3,10), FALSE), 15 * ++num_explosions)
|
||||
if(num_explosions == mine_limit_v2)
|
||||
return
|
||||
|
||||
#undef MINESWEEPERIMG
|
||||
#undef MINESWEEPER_GAME_MAIN_MENU
|
||||
#undef MINESWEEPER_GAME_PLAYING
|
||||
#undef MINESWEEPER_GAME_LOST
|
||||
#undef MINESWEEPER_GAME_WON
|
||||
@@ -259,11 +259,6 @@
|
||||
|
||||
build_path = /obj/machinery/computer/arcade/orion_trail
|
||||
|
||||
/obj/item/circuitboard/computer/arcade/minesweeper
|
||||
name = "Minesweeper (Computer Board)"
|
||||
icon_state = "generic"
|
||||
build_path = /obj/machinery/computer/arcade/minesweeper
|
||||
|
||||
/obj/item/circuitboard/computer/holodeck// Not going to let people get this, but it's just here for future
|
||||
name = "Holodeck Control (Computer Board)"
|
||||
icon_state = "generic"
|
||||
|
||||
@@ -1295,6 +1295,15 @@
|
||||
/obj/item/stock_parts/manipulator = 1)
|
||||
needs_anchored = FALSE
|
||||
|
||||
/obj/item/circuitboard/machine/autoloom
|
||||
name = "Autoloom (Machine Board)"
|
||||
icon_state = "service"
|
||||
build_path = /obj/machinery/autoloom
|
||||
req_components = list(
|
||||
/obj/item/stock_parts/matter_bin = 1,
|
||||
/obj/item/stock_parts/manipulator = 1)
|
||||
needs_anchored = FALSE
|
||||
|
||||
/obj/item/circuitboard/machine/seed_extractor
|
||||
name = "Seed Extractor (Machine Board)"
|
||||
icon_state = "service"
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
pai.master_dna = M.dna.unique_enzymes
|
||||
to_chat(pai, "<span class='notice'>You have been bound to a new master.</span>")
|
||||
if(href_list["wipe"])
|
||||
var/confirm = input("Are you CERTAIN you wish to delete the current personality? This action cannot be undone.", "Personality Wipe") in list("Yes", "No")
|
||||
var/confirm = tgui_input_list(usr, "Are you CERTAIN you wish to delete the current personality? This action cannot be undone.", "Personality Wipe", list("Yes", "No"))
|
||||
if(confirm == "Yes")
|
||||
if(pai)
|
||||
to_chat(pai, "<span class='warning'>You feel yourself slipping away from reality.</span>")
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
icon_state = "paint_neutral"
|
||||
|
||||
/obj/item/paint/anycolor/attack_self(mob/user)
|
||||
var/t1 = input(user, "Please select a color:", "Locking Computer", null) in list( "red", "pink", "blue", "cyan", "green", "lime", "yellow", "orange", "violet", "purple", "black", "gray", "white")
|
||||
var/t1 = tgui_input_list(user, "Please select a color:", "Locking Computer", list( "red", "pink", "blue", "cyan", "green", "lime", "yellow", "orange", "violet", "purple", "black", "gray", "white"))
|
||||
if ((user.get_active_held_item() != src || user.stat || user.restrained()))
|
||||
return
|
||||
switch(t1)
|
||||
|
||||
@@ -761,7 +761,8 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \
|
||||
GLOBAL_LIST_INIT(bone_recipes, list(
|
||||
new /datum/stack_recipe("Bone Dagger", /obj/item/kitchen/knife/combat/bone, 2, time = 20), \
|
||||
new /datum/stack_recipe("Skull Helmet", /obj/item/clothing/head/helmet/skull, 4, time = 30), \
|
||||
new /datum/stack_recipe("Bone Armor", /obj/item/clothing/suit/armor/bone, 6, time = 30)))
|
||||
new /datum/stack_recipe("Bone Armor", /obj/item/clothing/suit/armor/bone, 6, time = 30),\
|
||||
new /datum/stack_recipe("Processable Bone", /obj/item/ingot/bone, 2, time = 20)))
|
||||
|
||||
/obj/item/stack/sheet/bone
|
||||
name = "bones"
|
||||
|
||||
@@ -800,6 +800,13 @@
|
||||
|
||||
/datum/outfit/ghostcafe/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source)
|
||||
..()
|
||||
if (isplasmaman(H))
|
||||
head = /obj/item/clothing/head/helmet/space/plasmaman
|
||||
uniform = /obj/item/clothing/under/plasmaman
|
||||
l_hand= /obj/item/tank/internals/plasmaman/belt/full
|
||||
mask = /obj/item/clothing/mask/breath
|
||||
return
|
||||
|
||||
var/suited = !preference_source || preference_source.prefs.jumpsuit_style == PREF_SUIT
|
||||
if (CONFIG_GET(flag/grey_assistants))
|
||||
uniform = suited ? /obj/item/clothing/under/color/grey : /obj/item/clothing/under/color/jumpskirt/grey
|
||||
@@ -809,6 +816,10 @@
|
||||
else
|
||||
uniform = suited ? /obj/item/clothing/under/color/random : /obj/item/clothing/under/color/jumpskirt/random
|
||||
|
||||
/datum/outfit/ghostcafe/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source)
|
||||
H.internal = H.get_item_for_held_index(1)
|
||||
H.update_internals_hud_icon(1)
|
||||
|
||||
/obj/item/storage/box/syndie_kit/chameleon/ghostcafe
|
||||
name = "ghost cafe costuming kit"
|
||||
desc = "Look just the way you did in life - or better!"
|
||||
|
||||
@@ -273,24 +273,6 @@
|
||||
"frenching" = 'icons/UI_Icons/Achievements/Misc/frenchingthebubble.png'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/minesweeper
|
||||
name = "minesweeper"
|
||||
assets = list(
|
||||
"1" = 'icons/UI_Icons/minesweeper_tiles/one.png',
|
||||
"2" = 'icons/UI_Icons/minesweeper_tiles/two.png',
|
||||
"3" = 'icons/UI_Icons/minesweeper_tiles/three.png',
|
||||
"4" = 'icons/UI_Icons/minesweeper_tiles/four.png',
|
||||
"5" = 'icons/UI_Icons/minesweeper_tiles/five.png',
|
||||
"6" = 'icons/UI_Icons/minesweeper_tiles/six.png',
|
||||
"7" = 'icons/UI_Icons/minesweeper_tiles/seven.png',
|
||||
"8" = 'icons/UI_Icons/minesweeper_tiles/eight.png',
|
||||
"empty" = 'icons/UI_Icons/minesweeper_tiles/empty.png',
|
||||
"flag" = 'icons/UI_Icons/minesweeper_tiles/flag.png',
|
||||
"hidden" = 'icons/UI_Icons/minesweeper_tiles/hidden.png',
|
||||
"mine" = 'icons/UI_Icons/minesweeper_tiles/mine.png',
|
||||
"minehit" = 'icons/UI_Icons/minesweeper_tiles/minehit.png'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/pills
|
||||
name = "pills"
|
||||
assets = list(
|
||||
|
||||
@@ -403,6 +403,9 @@
|
||||
if("incheck")
|
||||
send_signal(device_id, list("checks" = text2num(params["val"])^2), usr)
|
||||
. = TRUE
|
||||
if("direction")
|
||||
send_signal(device_id, list("direction" = text2num(params["val"])), usr)
|
||||
. = TRUE
|
||||
if("set_external_pressure", "set_internal_pressure")
|
||||
|
||||
var/target = params["value"]
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
var/obj/machinery/atmospherics/components/unary/heat_exchanger/partner = null
|
||||
var/update_cycle
|
||||
var/old_temperature = 0
|
||||
var/other_old_temperature = 0
|
||||
|
||||
pipe_state = "heunary"
|
||||
|
||||
@@ -59,9 +61,6 @@
|
||||
var/other_air_heat_capacity = partner_air_contents.heat_capacity()
|
||||
var/combined_heat_capacity = other_air_heat_capacity + air_heat_capacity
|
||||
|
||||
var/old_temperature = air_contents.return_temperature()
|
||||
var/other_old_temperature = partner_air_contents.return_temperature()
|
||||
|
||||
if(combined_heat_capacity > 0)
|
||||
var/combined_energy = partner_air_contents.return_temperature()*other_air_heat_capacity + air_heat_capacity*air_contents.return_temperature()
|
||||
|
||||
@@ -71,6 +70,8 @@
|
||||
|
||||
if(abs(old_temperature-air_contents.return_temperature()) > 1)
|
||||
update_parents()
|
||||
old_temperature = air_contents.return_temperature()
|
||||
|
||||
if(abs(other_old_temperature-partner_air_contents.return_temperature()) > 1)
|
||||
partner.update_parents()
|
||||
other_old_temperature = partner_air_contents.return_temperature()
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
"device" = "VP",
|
||||
"timestamp" = world.time,
|
||||
"power" = on,
|
||||
"direction" = pump_direction ? "release" : "siphon",
|
||||
"direction" = pump_direction,
|
||||
"checks" = pressure_checks,
|
||||
"internal" = internal_pressure_bound,
|
||||
"external" = external_pressure_bound,
|
||||
|
||||
@@ -171,11 +171,11 @@
|
||||
desc = "Start up your own grand casino with this crate filled with slot machine and arcade boards!"
|
||||
cost = 3000
|
||||
contains = list(/obj/item/circuitboard/computer/arcade/battle,
|
||||
/obj/item/circuitboard/computer/arcade/battle,
|
||||
/obj/item/circuitboard/computer/arcade/battle,
|
||||
/obj/item/circuitboard/computer/arcade/orion_trail,
|
||||
/obj/item/circuitboard/computer/arcade/orion_trail,
|
||||
/obj/item/circuitboard/computer/arcade/minesweeper,
|
||||
/obj/item/circuitboard/computer/arcade/minesweeper,
|
||||
/obj/item/circuitboard/computer/arcade/orion_trail,
|
||||
/obj/item/circuitboard/computer/slot_machine,
|
||||
/obj/item/circuitboard/computer/slot_machine,
|
||||
/obj/item/circuitboard/computer/slot_machine,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
typepath = /datum/round_event/ghost_role/operative
|
||||
weight = 0 //Admin only
|
||||
max_occurrences = 1
|
||||
dynamic_should_hijack = TRUE
|
||||
|
||||
/datum/round_event/ghost_role/operative
|
||||
minimum_required = 1
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
var/pirate_type = PIRATES_ROGUES //pick(PIRATES_ROGUES, PIRATES_SILVERSCALES, PIRATES_DUTCHMAN)
|
||||
var/datum/comm_message/threat_msg = new
|
||||
var/payoff = 0
|
||||
var/payoff_min = 1000
|
||||
var/payoff_min = 10000 //documented this time
|
||||
var/ship_template
|
||||
var/ship_name = "Space Privateers Association"
|
||||
var/initial_send_time = world.time
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
department_flag = CIVILIAN
|
||||
faction = "Station"
|
||||
total_positions = 0
|
||||
spawn_positions = 4
|
||||
spawn_positions = 0
|
||||
supervisors = "the security team"
|
||||
|
||||
outfit = /datum/outfit/job/prisoner
|
||||
|
||||
@@ -235,6 +235,9 @@
|
||||
icon_state = "crusher-bone"
|
||||
item_state = "crusher0-bone"
|
||||
|
||||
/obj/item/kinetic_crusher/glaive/bone/update_icon_state()
|
||||
item_state = "crusher[wielded]-bone"
|
||||
|
||||
//destablizing force
|
||||
/obj/item/projectile/destabilizer
|
||||
name = "destabilizing force"
|
||||
|
||||
@@ -116,19 +116,19 @@
|
||||
to_chat(src, "<span class='warning'>[L] is restraining [P], you cannot push past.</span>")
|
||||
return 1
|
||||
|
||||
//CIT CHANGES START HERE - makes it so resting stops you from moving through standing folks without a short delay
|
||||
if(!CHECK_MOBILITY(src, MOBILITY_STAND) && CHECK_MOBILITY(L, MOBILITY_STAND))
|
||||
//CIT CHANGES START HERE - makes it so resting stops you from moving through standing folks or over prone bodies without a short delay
|
||||
if(!CHECK_MOBILITY(src, MOBILITY_STAND))
|
||||
var/origtargetloc = L.loc
|
||||
if(!pulledby)
|
||||
if(combat_flags & COMBAT_FLAG_ATTEMPTING_CRAWL)
|
||||
return TRUE
|
||||
if(IS_STAMCRIT(src))
|
||||
to_chat(src, "<span class='warning'>You're too exhausted to crawl under [L].</span>")
|
||||
to_chat(src, "<span class='warning'>You're too exhausted to crawl [(CHECK_MOBILITY(L, MOBILITY_STAND)) ? "under": "over"] [L].</span>")
|
||||
return TRUE
|
||||
ENABLE_BITFIELD(combat_flags, COMBAT_FLAG_ATTEMPTING_CRAWL)
|
||||
visible_message("<span class='notice'>[src] is attempting to crawl under [L].</span>",
|
||||
"<span class='notice'>You are now attempting to crawl under [L].</span>",
|
||||
target = L, target_message = "<span class='notice'>[src] is attempting to crawl under you.</span>")
|
||||
visible_message("<span class='notice'>[src] is attempting to crawl [(CHECK_MOBILITY(L, MOBILITY_STAND)) ? "under" : "over"] [L].</span>",
|
||||
"<span class='notice'>You are now attempting to crawl [(CHECK_MOBILITY(L, MOBILITY_STAND)) ? "under": "over"] [L].</span>",
|
||||
target = L, target_message = "<span class='notice'>[src] is attempting to crawl [(CHECK_MOBILITY(L, MOBILITY_STAND)) ? "under" : "over"] you.</span>")
|
||||
if(!do_after(src, CRAWLUNDER_DELAY, target = src) || CHECK_MOBILITY(src, MOBILITY_STAND))
|
||||
DISABLE_BITFIELD(combat_flags, COMBAT_FLAG_ATTEMPTING_CRAWL)
|
||||
return TRUE
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
if(mover in buckled_mobs)
|
||||
return TRUE
|
||||
var/mob/living/L = mover //typecast first, check isliving and only check this if living using short circuit
|
||||
if(lying && L.lying) //if we're both lying down and aren't already being thrown/shipped around, don't pass
|
||||
return FALSE
|
||||
return (!density || (isliving(mover)? L.can_move_under_living(src) : !mover.density))
|
||||
|
||||
/mob/living/toggle_move_intent()
|
||||
|
||||
@@ -358,8 +358,16 @@
|
||||
var/obj/singularity/energy_ball/tesla = source
|
||||
if(istype(tesla))
|
||||
if(istype(closest_atom,/obj/machinery/power/grounding_rod) && tesla.energy>13 && !tesla.contained)
|
||||
qdel(closest_atom) // each rod deletes two miniballs,
|
||||
tesla.energy = round(tesla.energy/1.5625) // if there are no miniballs the rod stays and continues to pull the ball in
|
||||
|
||||
// getting the grounding rod's capacitor rating for quick maths
|
||||
var/obj/machinery/power/grounding_rod/rod = closest_atom
|
||||
// assuming the rod is fully constructed the second part will always be a capacitor
|
||||
var/obj/item/stock_parts/capacitor/capacitor = rod.component_parts[2]
|
||||
|
||||
tesla.energy = round(tesla.energy/(1 + 0.28125 * capacitor.rating))
|
||||
qdel(closest_atom) // each rod removes tesla energy depending on the power of the capacitor,
|
||||
// if there are no miniballs the rod stays and continues to pull the ball in
|
||||
|
||||
if(prob(20))//I know I know
|
||||
tesla_zap(closest_atom, next_range, power * 0.5, zap_flags, shocked_targets)
|
||||
tesla_zap(closest_atom, next_range, power * 0.5, zap_flags, shocked_targets)
|
||||
|
||||
@@ -21,14 +21,6 @@
|
||||
category = list("Computer Boards")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ALL
|
||||
|
||||
/datum/design/board/minesweeper
|
||||
name = "Computer Design (Minesweeper Arcade Machine)"
|
||||
desc = "Allows for the construction of circuit boards used to build a new Minesweeper machine."
|
||||
id = "arcade_minesweeper"
|
||||
build_path = /obj/item/circuitboard/computer/arcade/minesweeper
|
||||
category = list("Computer Boards")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ALL
|
||||
|
||||
/datum/design/board/slot_machine
|
||||
name = "Computer Design (Slot Machine)"
|
||||
desc = "Allows for the construction of circuit boards used to build a new slot machine."
|
||||
|
||||
@@ -10,6 +10,14 @@
|
||||
category = list ("Misc. Machinery")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ALL
|
||||
|
||||
/datum/design/board/autoloom
|
||||
name = "Machine Design (Autoloom Board)"
|
||||
desc = "The circuit board for an autoloom."
|
||||
id = "autoloom"
|
||||
build_path = /obj/item/circuitboard/machine/autoloom
|
||||
category = list ("Misc. Machinery")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
|
||||
|
||||
/datum/design/board/holopad
|
||||
name = "Machine Design (AI Holopad Board)"
|
||||
desc = "The circuit board for a holopad."
|
||||
|
||||
@@ -56,5 +56,5 @@
|
||||
display_name = "Games and Toys"
|
||||
description = "For the slackers on the station."
|
||||
prereq_ids = list("comptech")
|
||||
design_ids = list("arcade_battle", "arcade_orion", "arcade_minesweeper", "slotmachine", "autoylathe")
|
||||
design_ids = list("arcade_battle", "arcade_orion", "slotmachine", "autoylathe")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
display_name = "Botanical Engineering"
|
||||
description = "Botanical tools."
|
||||
prereq_ids = list("adv_engi", "biotech")
|
||||
design_ids = list("diskplantgene", "portaseeder", "plantgenes", "flora_gun", "hydro_tray", "biogenerator", "seed_extractor")
|
||||
design_ids = list("diskplantgene", "portaseeder", "plantgenes", "flora_gun", "hydro_tray", "biogenerator", "seed_extractor", "autoloom")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750)
|
||||
|
||||
/datum/techweb_node/exp_tools
|
||||
|
||||
@@ -286,6 +286,13 @@
|
||||
anvilquality = 0
|
||||
itemqualitymax = 6
|
||||
|
||||
/obj/structure/anvil/obtainable/bone
|
||||
name = "bone anvil"
|
||||
desc = "An anvil. It's made of goliath bones and hide and held together by watcher sinews."
|
||||
icon_state = "bonevil"
|
||||
anvilquality = 0
|
||||
itemqualitymax = 6
|
||||
|
||||
/obj/structure/anvil/obtainable/ratvar
|
||||
name = "brass anvil"
|
||||
desc = "A big block of what appears to be brass. Useable as an anvil, if whatever's holding the brass together lets you."
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
/obj/item/ingot/iron
|
||||
custom_materials = list(/datum/material/iron=12000)
|
||||
|
||||
/obj/item/ingot/bone
|
||||
custom_materials = list(/datum/material/bone=4000)
|
||||
|
||||
/obj/item/ingot/diamond
|
||||
custom_materials = list(/datum/material/diamond=12000)
|
||||
|
||||
|
||||
@@ -530,8 +530,8 @@
|
||||
gas_max[GAS_N2] = PP(breath, GAS_N2) + 5
|
||||
var/datum/breathing_class/class = GLOB.gas_data.breathing_classes[breathing_class]
|
||||
var/o2_pp = class.get_effective_pp(breath)
|
||||
safe_breath_min = 0.3 * o2_pp
|
||||
safe_breath_max = 1.3 * o2_pp
|
||||
safe_breath_min = min(3, 0.3 * o2_pp)
|
||||
safe_breath_max = max(18, 1.3 * o2_pp + 1)
|
||||
..()
|
||||
#undef SAFE_THRESHOLD_RATIO
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
playsound(src, pick('sound/vehicles/clowncar_ram1.ogg', 'sound/vehicles/clowncar_ram2.ogg', 'sound/vehicles/clowncar_ram3.ogg'), 75)
|
||||
log_combat(src, hittarget_living, "sucked up")
|
||||
return
|
||||
if(!istype(bumped, /turf/closed))
|
||||
if(!istype(bumped, /turf/closed) && !istype(bumped, /obj/machinery/door/airlock/external))
|
||||
return
|
||||
visible_message(span_warning("[src] rams into [bumped] and crashes!"))
|
||||
playsound(src, pick('sound/vehicles/clowncar_crash1.ogg', 'sound/vehicles/clowncar_crash2.ogg'), 75)
|
||||
@@ -237,6 +237,11 @@
|
||||
for(var/mob/busdriver as anything in return_drivers())
|
||||
busdriver.client.give_award(/datum/award/achievement/misc/the_best_driver, busdriver)
|
||||
|
||||
/obj/vehicle/sealed/car/clowncar/driver_move(mob/user, direction) //Prevent it from moving onto space
|
||||
if(isspaceturf(get_step(src, direction)))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/sealed/car/clowncar/twitch_plays
|
||||
key_type = null
|
||||
explode_on_death = FALSE
|
||||
|
||||
Reference in New Issue
Block a user