Merge remote-tracking branch 'ParadiseSS13/master' into toml-config

This commit is contained in:
AffectedArc07
2021-07-09 11:42:23 +01:00
210 changed files with 1803 additions and 2434 deletions
+9 -1
View File
@@ -1072,7 +1072,7 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
Returning TRUE here will override the above proc's result.
*/
/atom/proc/CanAStarPassTo(ID, dir, obj/destination)
return TRUE
return FALSE
/** Call this when you want to present a renaming prompt to the user.
@@ -1139,3 +1139,11 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
else
name = "[prefix][t]"
return t
/atom/proc/set_angle(degrees)
var/matrix/M = matrix()
M.Turn(degrees)
// If we aint 0, make it NN transform
if(degrees)
appearance_flags |= PIXEL_SCALE
transform = M
+2
View File
@@ -90,6 +90,8 @@
/mob/living/carbon/proc/has_virus()
for(var/thing in viruses)
var/datum/disease/D = thing
if(!D.discovered) // Early-stage viruses should not show up on med HUD (though health analywers can still pick them up)
continue
if((!(D.visibility_flags & HIDDEN_SCANNER)) && (D.severity != NONTHREAT))
return TRUE
return FALSE
+1
View File
@@ -185,6 +185,7 @@
activation_messages = list("You feel smarter.")
deactivation_messages = list("You feel dumber.")
instability = GENE_INSTABILITY_MAJOR
traits_to_add = list(TRAIT_TELEKINESIS)
activation_prob = 15
/datum/mutation/tk/New()
@@ -84,7 +84,7 @@
traitorcount += 1
continue
if(ishuman(player) || isAI(player))
if((ROLE_TRAITOR in player.client.prefs.be_special) && !player.client.skip_antag && !jobban_isbanned(player, ROLE_TRAITOR) && !jobban_isbanned(player, "Syndicate"))
if((ROLE_TRAITOR in player.client.prefs.be_special) && !player.client.skip_antag && !jobban_isbanned(player, ROLE_TRAITOR) && !jobban_isbanned(player, ROLE_SYNDICATE))
possible_traitors += player.mind
for(var/datum/mind/player in possible_traitors)
for(var/job in restricted_jobs)
@@ -144,7 +144,7 @@
if(SSshuttle.emergency.mode >= SHUTTLE_ESCAPE)
return
//message_admins("Late Join Check")
if(character.client && (ROLE_TRAITOR in character.client.prefs.be_special) && !character.client.skip_antag && !jobban_isbanned(character, ROLE_TRAITOR) && !jobban_isbanned(character, "Syndicate"))
if(character.client && (ROLE_TRAITOR in character.client.prefs.be_special) && !character.client.skip_antag && !jobban_isbanned(character, ROLE_TRAITOR) && !jobban_isbanned(character, ROLE_SYNDICATE))
//message_admins("Late Joiner has Be Syndicate")
//message_admins("Checking number of players")
var/playercount = 0
+1 -1
View File
@@ -57,7 +57,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
/datum/game_mode/blob/proc/get_blob_candidates()
var/list/candidates = list()
for(var/mob/living/carbon/human/player in GLOB.player_list)
if(!player.stat && player.mind && !player.client.skip_antag && !player.mind.special_role && !jobban_isbanned(player, "Syndicate") && (ROLE_BLOB in player.client.prefs.be_special))
if(!player.stat && player.mind && !player.client.skip_antag && !player.mind.special_role && !jobban_isbanned(player, ROLE_SYNDICATE) && (ROLE_BLOB in player.client.prefs.be_special))
candidates += player
return candidates
@@ -93,5 +93,7 @@ the same goes for Remove(). if you override Remove(), call parent or else your p
/datum/action/changeling/proc/transform_dna(mob/living/carbon/human/H, datum/dna/D)
if(!D)
return
H.change_dna(D, TRUE)
var/changesSpecies = TRUE
if (H.dna.species.name == D.species.name)
changesSpecies = FALSE
H.change_dna(D, changesSpecies)
@@ -1,11 +1,11 @@
/datum/action/changeling/digitalcamo
name = "Digital Camouflage"
desc = "By evolving the ability to distort our form and proprotions, we defeat common altgorithms used to detect lifeforms on cameras."
helptext = "We cannot be tracked by camera while using this skill. However, humans looking at us will find us... uncanny."
helptext = "We cannot be tracked by camera while using this skill."
button_icon_state = "digital_camo"
dna_cost = 1
//Prevents AIs tracking you but makes you easily detectable to the human-eye.
//Prevents AIs tracking you.
/datum/action/changeling/digitalcamo/sting_action(mob/user)
if(user.digitalcamo)
@@ -243,7 +243,6 @@
damage_type = BRUTE
range = 8
hitsound = 'sound/weapons/thudswoosh.ogg'
var/chain
var/obj/item/ammo_casing/magic/tentacle/source //the item that shot it
/obj/item/projectile/tentacle/New(obj/item/ammo_casing/magic/tentacle/tentacle_casing)
@@ -7,51 +7,7 @@
//Revive from regenerative stasis
/datum/action/changeling/revive/sting_action(mob/living/carbon/user)
user.setToxLoss(0, FALSE)
user.setOxyLoss(0, FALSE)
user.setCloneLoss(0, FALSE)
user.setBrainLoss(0, FALSE)
user.SetParalysis(0, FALSE)
user.SetStunned(0, FALSE)
user.SetWeakened(0, FALSE)
user.radiation = 0
user.SetEyeBlind(0, FALSE)
user.SetEyeBlurry(0, FALSE)
user.RestoreEars()
user.heal_overall_damage(user.getBruteLoss(), user.getFireLoss(), updating_health = FALSE)
user.cure_blind(null, FALSE)
user.CureDeaf()
user.cure_nearsighted(null, FALSE)
user.reagents.clear_reagents()
user.germ_level = 0
user.timeofdeath = 0
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.restore_blood()
H.next_pain_time = 0
H.dna.species.create_organs(H)
// Now that recreating all organs is necessary, the rest of this organ stuff probably
// isn't, but I don't want to remove it, just in case.
for(var/organ_name in H.bodyparts_by_name)
var/obj/item/organ/external/O = H.bodyparts_by_name[organ_name]
if(!O)
continue
O.brute_dam = 0
O.burn_dam = 0
O.damage_state = "00"
O.germ_level = 0
QDEL_NULL(O.hidden)
O.open = 0
O.internal_bleeding = FALSE
O.perma_injury = 0
O.status = 0
O.trace_chemicals.Cut()
for(var/obj/item/organ/internal/IO in H.internal_organs)
IO.rejuvenate()
IO.trace_chemicals.Cut()
H.remove_all_embedded_objects()
for(var/datum/disease/critical/C in user.viruses)
C.cure()
user.revive()
REMOVE_TRAIT(user, TRAIT_FAKEDEATH, "changeling")
user.updatehealth("revive sting")
user.update_blind_effects()
+6 -2
View File
@@ -848,8 +848,12 @@
uses += max(1, temp)
/obj/item/melee/blood_magic/manipulator/attack_self(mob/living/user)
var/list/options = list("Blood Orb (50)", "Blood Recharge (75)", "Blood Spear (150)", "Blood Bolt Barrage (300)")
var/choice = input(user, "Choose a greater blood rite...", "Greater Blood Rites") as null|anything in options
var/list/options = list("Blood Orb (50)" = image(icon = 'icons/obj/cult.dmi', icon_state = "summoning_orb"),
"Blood Recharge (75)" = image(icon = 'icons/mob/actions/actions_cult.dmi', icon_state = "blood_charge"),
"Blood Spear (150)" = image(icon = 'icons/mob/actions/actions_cult.dmi', icon_state = "bloodspear"),
"Blood Bolt Barrage (300)" = image(icon = 'icons/mob/actions/actions_cult.dmi', icon_state = "blood_barrage"))
var/choice = show_radial_menu(user, src, options)
switch(choice)
if("Blood Orb (50)")
if(uses < BLOOD_ORB_COST)
@@ -195,6 +195,7 @@
GLOBAL_LIST_INIT(blacklisted_pylon_turfs, typecacheof(list(
/turf/simulated/floor/engine/cult,
/turf/space,
/turf/simulated/wall/indestructible,
/turf/simulated/floor/plating/lava,
/turf/simulated/floor/chasm,
/turf/simulated/wall/cult,
+6
View File
@@ -130,6 +130,9 @@ To draw a rune, use a ritual dagger.
visible_message("<span class='danger'>[src] suddenly appears!</span>")
alpha = initial(alpha)
/obj/effect/rune/is_cleanable()
return TRUE
/*
There are a few different procs each rune runs through when a cultist activates it.
@@ -991,6 +994,9 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/narsie/cult_conceal() //can't hide this, and you wouldn't want to
return
/obj/effect/rune/narsie/is_cleanable() //No, you can't just yeet a cleaning grenade to remove it.
return FALSE
/obj/effect/rune/narsie/invoke(list/invokers)
if(used)
return
+1 -1
View File
@@ -238,7 +238,7 @@
// Assemble a list of active players without jobbans.
for(var/mob/new_player/player in GLOB.player_list)
if(player.client && player.ready && player.has_valid_preferences())
if(!jobban_isbanned(player, "Syndicate") && !jobban_isbanned(player, roletext))
if(!jobban_isbanned(player, ROLE_SYNDICATE) && !jobban_isbanned(player, roletext))
if(player_old_enough_antag(player.client,role))
players += player
@@ -128,8 +128,8 @@
if(cannotPossess(user))
to_chat(user, "<span class='boldnotice'>Upon using the antagHUD you forfeited the ability to join the round.</span>")
return
if(jobban_isbanned(user, "Syndicate"))
to_chat(user, "<span class='warning'>You are banned from antagonists!</span>")
if(jobban_isbanned(user, ROLE_SYNDICATE) || jobban_isbanned(user, ROLE_BORER))
to_chat(user, "<span class='warning'>You are banned from playing this antagonist!</span>")
return
if(key)
return
@@ -332,6 +332,14 @@
to_chat(S, "<span class='warning'>An inhospitable area may be created as a result of destroying this object. Aborting.</span>")
return FALSE
/obj/structure/fans/tiny/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>An inhospitable area may be created as a result of destroying this object. Aborting.</span>")
return FALSE
/obj/structure/holosign/barrier/atmos/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>An inhospitable area may be created as a result of destroying this object. Aborting.</span>")
return FALSE
/obj/machinery/tcomms/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This communications relay should be preserved, it will be a useful resource to our masters in the future. Aborting.</span>")
return FALSE
@@ -10,6 +10,7 @@
melee_damage_lower = 10
melee_damage_upper = 10
damage_transfer = 0.9
can_strip = TRUE
projectiletype = /obj/item/projectile/guardian
ranged_cooldown_time = 5 //fast!
projectilesound = 'sound/effects/hit_on_shattered_glass.ogg'
@@ -35,6 +36,7 @@
alpha = 255
range = 13
incorporeal_move = 0
can_strip = TRUE
to_chat(src, "<span class='danger'>You switch to combat mode.</span>")
toggle = FALSE
else
@@ -46,6 +48,7 @@
alpha = 60
range = 255
incorporeal_move = 1
can_strip = FALSE //spiritual pickpocketting is forbidden
to_chat(src, "<span class='danger'>You switch to scout mode.</span>")
toggle = TRUE
else
+28 -24
View File
@@ -188,6 +188,9 @@
M.regenerate_icons()
M.update_body()
if(!the_bomb)
the_bomb = locate(/obj/machinery/nuclearbomb/syndicate) in GLOB.poi_list
if(the_bomb)
synd_mind.store_memory("<B>Syndicate [the_bomb.name] Code</B>: [the_bomb.r_code]")
to_chat(synd_mind.current, "The code for \the [the_bomb.name] is: <B>[the_bomb.r_code]</B>")
@@ -436,54 +439,55 @@
return newname
/datum/game_mode/nuclear/set_scoreboard_gvars()
/datum/game_mode/nuclear/set_scoreboard_vars()
var/datum/scoreboard/scoreboard = SSticker.score
var/foecount = 0
for(var/datum/mind/M in SSticker.mode.syndicates)
foecount++
if(!M || !M.current)
GLOB.score_opkilled++
scoreboard.score_ops_killed++
continue
if(M.current.stat == DEAD)
GLOB.score_opkilled++
scoreboard.score_ops_killed++
else if(M.current.restrained())
GLOB.score_arrested++
scoreboard.score_arrested++
if(foecount == GLOB.score_arrested)
GLOB.score_allarrested = 1
if(foecount == scoreboard.score_arrested)
scoreboard.all_arrested = TRUE // how the hell did they manage that
for(var/obj/machinery/nuclearbomb/nuke in GLOB.machines)
if(nuke.r_code == "Nope") continue
var/obj/machinery/nuclearbomb/syndicate/nuke = locate() in GLOB.poi_list
if(nuke?.r_code != "Nope")
var/area/A = get_area(nuke)
var/list/thousand_penalty = list(/area/solar)
var/list/fiftythousand_penalty = list(/area/security/main, /area/security/brig, /area/security/armoury, /area/security/checkpoint2)
if(is_type_in_list(A, thousand_penalty))
GLOB.score_nuked_penalty = 1000
scoreboard.nuked_penalty = 1000
else if(is_type_in_list(A, fiftythousand_penalty))
GLOB.score_nuked_penalty = 50000
scoreboard.nuked_penalty = 50000
else if(istype(A, /area/engine))
GLOB.score_nuked_penalty = 100000
scoreboard.nuked_penalty = 100000
else
GLOB.score_nuked_penalty = 10000
scoreboard.nuked_penalty = 10000
break
var/killpoints = GLOB.score_opkilled * 250
var/arrestpoints = GLOB.score_arrested * 1000
GLOB.score_crewscore += killpoints
GLOB.score_crewscore += arrestpoints
if(GLOB.score_nuked)
GLOB.score_crewscore -= GLOB.score_nuked_penalty
var/killpoints = scoreboard.score_ops_killed * 250
var/arrestpoints = scoreboard.score_arrested * 1000
scoreboard.crewscore += killpoints
scoreboard.crewscore += arrestpoints
if(scoreboard.nuked)
scoreboard.crewscore -= scoreboard.nuked_penalty
/datum/game_mode/nuclear/get_scoreboard_stats()
var/datum/scoreboard/scoreboard = SSticker.score
var/foecount = 0
var/crewcount = 0
@@ -530,11 +534,11 @@
dat += "<br>"
dat += "<b>Operatives Arrested:</b> [GLOB.score_arrested] ([GLOB.score_arrested * 1000] Points)<br>"
dat += "<b>All Operatives Arrested:</b> [GLOB.score_allarrested ? "Yes" : "No"] (Score tripled)<br>"
dat += "<b>Operatives Arrested:</b> [scoreboard.score_arrested] ([scoreboard.score_arrested * 1000] Points)<br>"
dat += "<b>All Operatives Arrested:</b> [scoreboard.all_arrested ? "Yes" : "No"] (Score tripled)<br>"
dat += "<b>Operatives Killed:</b> [GLOB.score_opkilled] ([GLOB.score_opkilled * 1000] Points)<br>"
dat += "<b>Station Destroyed:</b> [GLOB.score_nuked ? "Yes" : "No"] (-[GLOB.score_nuked_penalty] Points)<br>"
dat += "<b>Operatives Killed:</b> [scoreboard.score_ops_killed] ([scoreboard.score_ops_killed * 1000] Points)<br>"
dat += "<b>Station Destroyed:</b> [scoreboard.nuked ? "Yes" : "No"] (-[scoreboard.nuked_penalty] Points)<br>"
dat += "<hr>"
return dat
+27 -26
View File
@@ -370,44 +370,45 @@
text += "<br>"
to_chat(world, text)
/datum/game_mode/revolution/set_scoreboard_gvars()
/datum/game_mode/revolution/set_scoreboard_vars()
var/datum/scoreboard/scoreboard = SSticker.score
var/foecount = 0
for(var/datum/mind/M in SSticker.mode.head_revolutionaries)
foecount++
if(!M || !M.current)
GLOB.score_opkilled++
scoreboard.score_ops_killed++
continue
if(M.current.stat == DEAD)
GLOB.score_opkilled++
scoreboard.score_ops_killed++
else if(M.current.restrained())
GLOB.score_arrested++
scoreboard.score_arrested++
if(foecount == GLOB.score_arrested)
GLOB.score_allarrested = 1
if(foecount == scoreboard.score_arrested)
scoreboard.all_arrested = TRUE
for(var/thing in GLOB.human_list)
var/mob/living/carbon/human/player = thing
if(player.mind)
var/role = player.mind.assigned_role
if(role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director"))
if(player.stat == DEAD)
GLOB.score_deadcommand++
for(var/I in GLOB.human_list)
var/mob/living/carbon/human/H = I
if(H.stat == DEAD && H.mind?.assigned_role)
if(H.mind.assigned_role in list("Captain", "Head of Security", "Head of Personnel", "Chief Engineer", "Research Director"))
scoreboard.score_dead_command++
var/arrestpoints = GLOB.score_arrested * 1000
var/killpoints = GLOB.score_opkilled * 500
var/comdeadpts = GLOB.score_deadcommand * 500
if(GLOB.score_traitorswon)
GLOB.score_crewscore -= 10000
var/arrestpoints = scoreboard.score_arrested * 1000
var/killpoints = scoreboard.score_ops_killed * 500
var/comdeadpts = scoreboard.score_dead_command * 500
if(scoreboard.score_greentext)
scoreboard.crewscore -= 10000
GLOB.score_crewscore += arrestpoints
GLOB.score_crewscore += killpoints
GLOB.score_crewscore -= comdeadpts
scoreboard.crewscore += arrestpoints
scoreboard.crewscore += killpoints
scoreboard.crewscore -= comdeadpts
/datum/game_mode/revolution/get_scoreboard_stats()
var/datum/scoreboard/scoreboard = SSticker.score
var/foecount = 0
var/comcount = 0
var/revcount = 0
@@ -444,12 +445,12 @@
dat += "<b>Number of Surviving Loyal Crew:</b> [loycount]<br>"
dat += "<br>"
dat += "<b>Revolution Heads Arrested:</b> [GLOB.score_arrested] ([GLOB.score_arrested * 1000] Points)<br>"
dat += "<b>All Revolution Heads Arrested:</b> [GLOB.score_allarrested ? "Yes" : "No"] (Score tripled)<br>"
dat += "<b>Revolution Heads Arrested:</b> [scoreboard.score_arrested] ([scoreboard.score_arrested * 1000] Points)<br>"
dat += "<b>All Revolution Heads Arrested:</b> [scoreboard.all_arrested ? "Yes" : "No"] (Score tripled)<br>"
dat += "<b>Revolution Heads Slain:</b> [GLOB.score_opkilled] ([GLOB.score_opkilled * 500] Points)<br>"
dat += "<b>Command Staff Slain:</b> [GLOB.score_deadcommand] (-[GLOB.score_deadcommand * 500] Points)<br>"
dat += "<b>Revolution Successful:</b> [GLOB.score_traitorswon ? "Yes" : "No"] (-[GLOB.score_traitorswon * 10000] Points)<br>"
dat += "<b>Revolution Heads Slain:</b> [scoreboard.score_ops_killed] ([scoreboard.score_ops_killed * 500] Points)<br>"
dat += "<b>Command Staff Slain:</b> [scoreboard.score_dead_command] (-[scoreboard.score_dead_command * 500] Points)<br>"
dat += "<b>Revolution Successful:</b> [scoreboard.score_greentext ? "Yes" : "No"] (-[scoreboard.score_greentext * 10000] Points)<br>"
dat += "<HR>"
return dat
+237 -163
View File
@@ -1,3 +1,5 @@
GLOBAL_VAR(scoreboard) // Variable to save the scoreboard string once it's been generated
//Thresholds for Score Ratings
#define SINGULARITY_DESERVES_BETTER -3500
#define SINGULARITY_FODDER -3000
@@ -14,190 +16,275 @@
#define PRIDE_OF_SCIENCE 4000
#define NANOTRANSEN_FINEST 5000
/datum/controller/subsystem/ticker/proc/scoreboard()
//Print a list of antagonists to the server log
/datum/scoreboard
/// Overall combined score for the whole round.
var/crewscore = 0
/// How many useful items have cargo shipped out?
var/score_things_shipped = 0
/// How many harvests have hydroponics done?
var/score_things_harvested = 0
/// How much ore has been mined on the mining z level?
var/score_ore_mined = 0
/// How much research was done by science?
var/score_research_done = 0
/// How many random events did the station survive?
var/score_events_endured = 0
/// How many APCs have poor charge?
var/score_power_loss = 0
/// How many people got out alive?
var/score_escapees = 0
/// How many people /didn't/ get out alive?
var/score_dead_crew = 0
/// How much blood, puke, stains etc went uncleaned?
var/score_mess = 0
/// How many meals were made?
var/score_meals = 0
/// How many rampant, uncured diseases are on board the station?
var/score_disease = 0
/// How many command members died? (Revolution)
var/score_dead_command = 0
/// How many antagonists are alive in the brig? (Nuke ops & Revolution)
var/score_arrested = 0
/// How many operatives were killed? (Nuke ops & Revolution)
var/score_ops_killed = 0
/// How much noms were had by the crew?
var/score_food_eaten = 0
/// How many times was the clown punched, struck, or otherwise maligned?
var/score_clown_abuse = 0
// Booleans //
/// Were the antagonists successful?
var/score_greentext = FALSE
/// Did the crew catch all of the antags alive?
var/all_arrested = FALSE
/// Is the NAD safe and secure?
var/disc_secure = FALSE
// Points penalties/bonuses //
/// If all APCs on the station are running optimally, big bonus.
var/power_bonus = FALSE
/// If there are no messes on the station anywhere, huge bonus.
var/mess_bonus = FALSE
/// If the AI is dead, big points penalty.
var/dead_ai = FALSE
/// Was the station blown into little bits?
var/nuked = FALSE
/// Points penalty for being blown to little bits.
var/nuked_penalty = 0
// Player Stats //
/// What was the name of the richest person on the shuttle?
var/richest_name = ""
/// What was the ckey of the richest person on the shuttle?
var/richest_key = ""
/// What was the job of the richest person on the shuttle?
var/richest_job = ""
/// How much money did the richest person on the shuttle have?
var/richest_cash = 0
/// What was the name of the most injured person on the shuttle?
var/damaged_name
/// What was the ckey of the most injured person on the shuttle?
var/damaged_key
/// What was the job of the most injured person on the shuttle?
var/damaged_job
/// How damaged was the most injured person on the shuttle?
var/damaged_health
/datum/scoreboard/proc/scoreboard()
// Print a list of antagonists to the server log.
log_antags()
for(var/_I in GLOB.mob_list)
var/mob/M = _I
if(is_station_level(M.z))
check_station_player(M)
else if(SSshuttle.emergency.mode >= SHUTTLE_ENDGAME && istype(get_area(M), SSshuttle.emergency.areaInstance))
check_shuttle_player(M)
check_apc_power()
check_cleanables()
generate_scoreboard()
/datum/scoreboard/proc/log_antags()
var/list/total_antagonists = list()
//Look into all mobs in world, dead or alive
for(var/datum/mind/Mind in SSticker.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])"
// Look into all mobs in the world, dead or alive
for(var/mind in SSticker.minds)
var/datum/mind/M = mind
var/role = M.special_role
//Now print them all into the log!
// If they're an antagonist of some sort.
if(role)
if(total_antagonists[role]) // If the role exists already, add the name to it.
total_antagonists[role] += ", [M.name]([M.key])"
else // If the role doesn't exist in the list, create it and add the mob
total_antagonists[role] += ": [M.name]([M.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 GLOB.mob_list)
if(I.stat == DEAD && is_station_level(I.z))
GLOB.score_deadaipenalty++
GLOB.score_deadcrew++
for(var/thing in GLOB.human_list)
var/mob/living/carbon/human/I = thing
if(I.stat == DEAD && is_station_level(I.z))
GLOB.score_deadcrew++
if(SSshuttle.emergency.mode >= SHUTTLE_ENDGAME)
for(var/mob/living/player in GLOB.mob_list)
if(player.client)
if(player.stat != DEAD)
var/turf/location = get_turf(player.loc)
var/area/escape_zone = locate(/area/shuttle/escape)
if(location in escape_zone)
GLOB.score_escapees++
for(var/I in total_antagonists)
log_game("[I]s[total_antagonists[I]].")
/datum/scoreboard/proc/check_station_player(mob/M)
if(!is_station_level(M.z) || M.stat < DEAD)
return
if(isAI(M))
dead_ai = TRUE
score_dead_crew++
else if(ishuman(M))
score_dead_crew++
var/cash_score = 0
var/dmg_score = 0
/datum/scoreboard/proc/check_shuttle_player(mob/M)
if(!M.mind || M.stat == DEAD || !ishuman(M))
return
var/mob/living/carbon/human/H = M
if(SSshuttle.emergency.mode >= SHUTTLE_ENDGAME)
for(var/thing in GLOB.human_list)
var/mob/living/carbon/human/E = thing
cash_score = 0
dmg_score = 0
var/turf/location = get_turf(E.loc)
var/area/escape_zone = SSshuttle.emergency.areaInstance
score_escapees++
if(E.stat != DEAD && (location in escape_zone)) // Escapee Scores
cash_score = get_score_container_worth(E)
var/cash_score = get_score_container_worth(H)
if(cash_score > richest_cash)
richest_cash = cash_score
richest_name = H.real_name
richest_job = H.job
richest_key = H.key
if(cash_score > GLOB.score_richestcash)
GLOB.score_richestcash = cash_score
GLOB.score_richestname = E.real_name
GLOB.score_richestjob = E.job
GLOB.score_richestkey = E.key
var/damage_score = H.getBruteLoss() + H.getFireLoss() + H.getToxLoss() + H.getOxyLoss()
if(damage_score > damaged_health)
damaged_health = damage_score
damaged_name = H.real_name
damaged_job = H.job
damaged_key = H.key
dmg_score = E.getBruteLoss() + E.getFireLoss() + E.getToxLoss() + E.getOxyLoss()
if(dmg_score > GLOB.score_dmgestdamage)
GLOB.score_dmgestdamage = dmg_score
GLOB.score_dmgestname = E.real_name
GLOB.score_dmgestjob = E.job
GLOB.score_dmgestkey = E.key
// A recursive function to properly determine the wealthiest escapee
/datum/scoreboard/proc/get_score_container_worth(atom/C, level = 0)
. = 0
if(level >= 5)
// in case the containers recurse or something
return 0
if(SSticker && SSticker.mode)
SSticker.mode.set_scoreboard_gvars()
for(var/obj/item/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/stack/spacecash/cash in C.contents)
. += cash.amount
for(var/obj/item/storage/S in C.contents)
. += .(S, level + 1)
/datum/scoreboard/proc/check_apc_power()
for(var/_A in GLOB.apcs)
var/obj/machinery/power/apc/A = _A
if(!is_station_level(A.z))
continue
var/obj/item/stock_parts/cell/C = A.cell
if(!C || C.charge < 2300)
score_power_loss++ //200 charge leeway
/datum/scoreboard/proc/check_cleanables()
for(var/obj/effect/decal/cleanable/C in world)
if(!is_station_level(C.z))
continue
if(istype(C, /obj/effect/decal/cleanable/blood/gibs))
score_mess += 3
else if(istype(C, /obj/effect/decal/cleanable/blood))
score_mess += 1
else if(istype(C, /obj/effect/decal/cleanable/vomit))
score_mess += 1
// Check station's power levels
for(var/thing in GLOB.apcs)
var/obj/machinery/power/apc/A = thing
if(!is_station_level(A.z)) continue
for(var/obj/item/stock_parts/cell/C in A.contents)
if(C.charge < 2300)
GLOB.score_powerloss++ //200 charge leeway
/datum/scoreboard/proc/generate_scoreboard()
// Point modifiers
var/points_events_endured = score_events_endured * 50
var/points_research_done = score_research_done * 30
var/points_disease = score_disease * 30
var/points_dead_crew = score_dead_crew * 25
var/points_escapees = score_escapees * 25
var/points_power_loss = score_power_loss * 20
var/points_things_harvested = score_things_harvested * 5
var/points_things_shipped = score_things_shipped * 5
var/points_meals = score_meals * 5
var/points_ore_mined = score_ore_mined * 2
// Bonuses
crewscore += points_events_endured
crewscore += points_research_done
crewscore += points_escapees
crewscore += points_things_harvested
crewscore += points_things_shipped
crewscore += points_meals
crewscore += points_ore_mined
// Check how much uncleaned mess is on the station
for(var/obj/effect/decal/cleanable/M in world)
if(!is_station_level(M.z)) continue
if(istype(M, /obj/effect/decal/cleanable/blood/gibs))
GLOB.score_mess += 3
if(!score_power_loss)
crewscore += 2500
power_bonus = TRUE
if(istype(M, /obj/effect/decal/cleanable/blood))
GLOB.score_mess += 1
if(!score_mess)
crewscore += 1500
mess_bonus = TRUE
if(istype(M, /obj/effect/decal/cleanable/vomit))
GLOB.score_mess += 1
if(all_arrested) // This only seems to be implemented for Rev and Nukies. -DaveKorhal
crewscore *= 3 // This needs to be here for the bonus to be applied properly
// Penalties
crewscore -= points_dead_crew
crewscore -= points_power_loss
crewscore -= points_disease
crewscore -= score_mess
// Bonus Modifiers
var/deathpoints = GLOB.score_deadcrew * 25 //done
var/researchpoints = GLOB.score_researchdone * 30
var/eventpoints = GLOB.score_eventsendured * 50
var/escapoints = GLOB.score_escapees * 25 //done
var/harvests = GLOB.score_stuffharvested * 5
var/shipping = GLOB.score_stuffshipped * 5
var/mining = GLOB.score_oremined * 2 //done, might want polishing
var/meals = GLOB.score_meals * 5
var/power = GLOB.score_powerloss * 20
var/messpoints
if(GLOB.score_mess != 0)
messpoints = GLOB.score_mess //done
var/plaguepoints = GLOB.score_disease * 30
if(dead_ai)
crewscore -= 250
// Good Things
GLOB.score_crewscore += shipping
GLOB.score_crewscore += harvests
GLOB.score_crewscore += mining
GLOB.score_crewscore += researchpoints
GLOB.score_crewscore += eventpoints
GLOB.score_crewscore += escapoints
if(power == 0)
GLOB.score_crewscore += 2500
GLOB.score_powerbonus = 1
GLOB.score_crewscore += meals
if(GLOB.score_allarrested) // This only seems to be implemented for Rev and Nukies. -DaveKorhal
GLOB.score_crewscore *= 3 // This needs to be here for the bonus to be applied properly
GLOB.score_crewscore -= deathpoints
if(GLOB.score_deadaipenalty)
GLOB.score_crewscore -= 250
GLOB.score_crewscore -= power
GLOB.score_crewscore -= messpoints
GLOB.score_crewscore -= plaguepoints
// Show the score - might add "ranks" later
to_chat(world, "<b>The crew's final score is:</b>")
to_chat(world, "<b><font size='4'>[GLOB.score_crewscore]</font></b>")
// Generate the score panel
var/dat = "<b>Round Statistics and Score</b><br><hr>"
if(mode)
dat += mode.get_scoreboard_stats()
var/list/dat = list("<b>Round Statistics and Score</b><br><hr>")
if(SSticker.mode)
dat += SSticker.mode.get_scoreboard_stats()
dat += {"
<b><u>General Statistics</u></b><br>
<u>The Good</u><br>
<b>Ore Mined:</b> [GLOB.score_oremined] ([GLOB.score_oremined * 2] Points)<br>"}
if(SSshuttle.emergency.mode == SHUTTLE_ENDGAME) dat += "<b>Shuttle Escapees:</b> [GLOB.score_escapees] ([GLOB.score_escapees * 25] Points)<br>"
dat += {"
<b>Whole Station Powered:</b> [GLOB.score_powerbonus ? "Yes" : "No"] ([GLOB.score_powerbonus * 2500] Points)<br><br>
<b>Ore Mined:</b> [score_ore_mined] ([points_ore_mined] Points)<br>"}
if(score_escapees)
dat += "<b>Shuttle Escapees:</b> [score_escapees] ([points_escapees] Points)<br>"
dat += "<b>Whole Station Powered:</b> [power_bonus ? "Yes" : "No"] ([power_bonus * 2500] Points)<br>"
dat += "<b>Whole Station Cleaned:</b> [mess_bonus ? "Yes" : "No"] ([mess_bonus * 1500] Points)<br><br>"
<U>The Bad</U><br>
<b>Dead bodies on Station:</b> [GLOB.score_deadcrew] (-[GLOB.score_deadcrew * 25] Points)<br>
<b>Uncleaned Messes:</b> [GLOB.score_mess] (-[GLOB.score_mess] Points)<br>
<b>Station Power Issues:</b> [GLOB.score_powerloss] (-[GLOB.score_powerloss * 20] Points)<br>
<b>AI Destroyed:</b> [GLOB.score_deadaipenalty ? "Yes" : "No"] (-[GLOB.score_deadaipenalty * 250] Points)<br><br>
dat += "<U>The Bad</U><br>"
dat += "<b>Dead bodies on Station:</b> [score_dead_crew] (-[points_dead_crew] Points)<br>"
if(!mess_bonus)
dat += "<b>Uncleaned Messes:</b> [score_mess] (-[score_mess] Points)<br>"
if(!power_bonus)
dat += "<b>Station Power Issues:</b> [score_power_loss] (-[points_power_loss] Points)<br>"
dat += {"
<b>AI Destroyed:</b> [dead_ai ? "Yes" : "No"] (-[dead_ai * 250] Points)<br><br>
<U>The Weird</U><br>
<b>Food Eaten:</b> [GLOB.score_foodeaten] bites/sips<br>
<b>Times a Clown was Abused:</b> [GLOB.score_clownabuse]<br><br>
"}
if(GLOB.score_escapees)
dat += {"<b>Richest Escapee:</b> [GLOB.score_richestname], [GLOB.score_richestjob]: $[num2text(GLOB.score_richestcash,50)] ([GLOB.score_richestkey])<br>
<b>Most Battered Escapee:</b> [GLOB.score_dmgestname], [GLOB.score_dmgestjob]: [GLOB.score_dmgestdamage] damage ([GLOB.score_dmgestkey])<br>"}
<b>Food Eaten:</b> [score_food_eaten] bites/sips.<br>
<b>Times a Clown was Abused:</b> [score_clown_abuse]<br><br>"}
if(score_escapees)
dat += "<b>Richest Escapee:</b> [richest_name], [richest_job]: $[num2text(richest_cash, 50)] ([richest_key])<br>"
if(damaged_health)
dat += "<b>Most Battered Escapee:</b> [damaged_name], [damaged_job]: [damaged_health] damage ([damaged_key])<br>"
else
if(SSshuttle.emergency.mode <= SHUTTLE_STRANDED)
dat += "The station wasn't evacuated!<br>"
else
dat += "No-one escaped!<br>"
dat += mode.declare_job_completion()
dat += SSticker.mode.declare_job_completion()
dat += {"
<hr><br>
<b><u>FINAL SCORE: [GLOB.score_crewscore]</u></b><br>
<b><u>FINAL SCORE: [crewscore]</u></b><br>
"}
var/score_rating = "The Aristocrats!"
switch(GLOB.score_crewscore)
if(-99999 to SINGULARITY_DESERVES_BETTER) score_rating = "Even the Singularity Deserves Better"
switch(crewscore)
if(-INFINITY to SINGULARITY_DESERVES_BETTER) score_rating = "Even the Singularity Deserves Better"
if(SINGULARITY_DESERVES_BETTER+1 to SINGULARITY_FODDER) score_rating = "Singularity Fodder"
if(SINGULARITY_FODDER+1 to ALL_FIRED) score_rating = "You're All Fired"
if(ALL_FIRED+1 to WASTE_OF_OXYGEN) score_rating = "A Waste of Perfectly Good Oxygen"
@@ -214,33 +301,20 @@
if(NANOTRANSEN_FINEST to INFINITY) score_rating = "Nanotrasen's Finest"
dat += "<b><u>RATING:</u></b> [score_rating]"
src << browse(dat, "window=roundstats;size=500x600")
GLOB.scoreboard = jointext(dat, "")
for(var/mob/E in GLOB.player_list)
if(E.client && !E.get_preference(PREFTOGGLE_DISABLE_SCOREBOARD))
E << browse(dat, "window=roundstats;size=500x600")
if(E.client)
to_chat(E, "<b>The crew's final score is:</b>")
to_chat(E, "<b><font size='4'><a href='?src=[E.UID()];scoreboard=1'>[crewscore]</a></font></b>")
if(!E.get_preference(PREFTOGGLE_DISABLE_SCOREBOARD))
E << browse(GLOB.scoreboard, "window=roundstats;size=500x600")
// A recursive function to properly determine the wealthiest escapee
/datum/controller/subsystem/ticker/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/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/stack/spacecash/cash in C.contents)
. += cash.amount
for(var/obj/item/storage/S in C.contents)
. += .(S, level + 1)
/datum/game_mode/proc/get_scoreboard_stats()
return null
/datum/game_mode/proc/set_scoreboard_gvars()
/datum/game_mode/proc/set_scoreboard_vars()
return null
#undef SINGULARITY_DESERVES_BETTER
@@ -9,6 +9,7 @@
action_background_icon_state = "bg_vampire"
var/required_blood = 0
var/gain_desc = null
var/deduct_blood_on_cast = TRUE //Do we want to take the blood when this is cast, or at a later point?
/obj/effect/proc_holder/spell/vampire/New()
..()
@@ -99,6 +100,8 @@
var/datum/vampire/vampire = usr.mind.vampire
if(required_blood <= vampire.bloodusable)
if(!deduct_blood_on_cast) //don't take the blood yet if this is false!
return
vampire.bloodusable -= required_blood
else
// stop!!
@@ -288,8 +291,10 @@
gain_desc = "You have gained the Enthrall ability which at a heavy blood cost allows you to enslave a human that is not loyal to any other for a random period of time."
action_icon_state = "vampire_enthrall"
required_blood = 300
deduct_blood_on_cast = FALSE
/obj/effect/proc_holder/spell/vampire/targetted/enthrall/cast(list/targets, mob/user = usr)
var/datum/vampire/vampire = user.mind.vampire
for(var/mob/living/target in targets)
user.visible_message("<span class='warning'>[user] bites [target]'s neck!</span>", "<span class='warning'>You bite [target]'s neck and begin the flow of power.</span>")
to_chat(target, "<span class='warning'>You feel the tendrils of evil invade your mind.</span>")
@@ -299,6 +304,7 @@
if(do_mob(user, target, 50))
if(can_enthrall(user, target))
handle_enthrall(user, target)
vampire.bloodusable -= required_blood //we take the blood after enthralling, not before
else
revert_cast(user)
to_chat(user, "<span class='warning'>You or your target either moved or you dont have enough usable blood.</span>")
+1 -1
View File
@@ -366,7 +366,7 @@
qdel(SS)
/proc/make_new_construct(mob/living/simple_animal/hostile/construct/c_type, mob/target, mob/user, cult_override = FALSE)
if(jobban_isbanned(target, "cultist"))
if(jobban_isbanned(target, ROLE_CULTIST))
return
var/mob/living/simple_animal/hostile/construct/C = new c_type(get_turf(target))
C.faction |= "\ref[user]"
+2 -2
View File
@@ -446,7 +446,7 @@
/datum/spellbook_entry/item/warp_cubes
name = "Warp Cubes"
desc = "Two magic cubes, that when they are twisted in hand, teleports the user to the location of the other cube instantly. Great for silently teleporting to a fixed location, or teleporting you to an appretnance, or vice versa. Do not leave on the wizard den, it will not work."
desc = "Two magic cubes, that when they are twisted in hand, teleports the user to the location of the other cube instantly. Great for silently teleporting to a fixed location, or teleporting you to an apprentice, or vice versa. Do not leave on the wizard den, it will not work."
item_path = /obj/item/warp_cube/red
log_name = "WC"
cost = 1
@@ -479,7 +479,7 @@
/datum/spellbook_entry/item/singularity_hammer
name = "Singularity Hammer"
desc = "A hammer that creates an intensely powerful field of gravity where it strikes, pulling everthing nearby to the point of impact."
desc = "A hammer that creates an intensely powerful field of gravity where it strikes, pulling everything nearby to the point of impact."
item_path = /obj/item/twohanded/singularityhammer
log_name = "SI"
category = "Weapons and Armors"
+1 -1
View File
@@ -226,7 +226,7 @@
to_chat(H, "<span class='danger'>Failed to locate a storage object on your mob, either you spawned with no hands free and no backpack or this is a bug.</span>")
qdel(G)
qdel(gear_leftovers)
gear_leftovers.Cut()
return 1
+38 -105
View File
@@ -4,133 +4,66 @@
icon_state = "liquid_dispenser"
layer = 3
plane = FLOOR_PLANE
anchored = 1.0
anchored = TRUE
max_integrity = 200
armor = list(melee = 50, bullet = 20, laser = 20, energy = 20, bomb = 0, bio = 0, rad = 0, fire = 50, acid = 30)
var/uses = 20
var/disabled = TRUE
var/lethal = 0
var/locked = TRUE
var/cooldown_time = 0
var/cooldown_timeleft = 0
var/cooldown_time = 10 SECONDS
var/cooldown_on = FALSE
req_access = list(ACCESS_AI_UPLOAD)
/obj/machinery/ai_slipper/examine(mob/user)
. = ..()
. += "<span class='notice'>A small counter shows it has: [uses] use\s remaining.</span>"
/obj/machinery/ai_slipper/power_change()
if(stat & BROKEN)
update_icon()
if(powered())
stat &= ~NOPOWER
else
if( powered() )
stat &= ~NOPOWER
else
stat |= NOPOWER
disabled = TRUE
update_icon()
/obj/machinery/ai_slipper/proc/setState(enabled, uses)
disabled = disabled
uses = uses
power_change()
/obj/machinery/ai_slipper/attackby(obj/item/W, mob/user, params)
if(stat & (NOPOWER|BROKEN))
return
if(istype(user, /mob/living/silicon))
return attack_hand(user)
if(allowed(usr)) // trying to unlock the interface
locked = !locked
to_chat(user, "You [locked ? "lock" : "unlock"] the device.")
if(locked)
if(user.machine == src)
user.unset_machine()
user << browse(null, "window=ai_slipper")
else
if(user.machine == src)
attack_hand(usr)
return
return ..()
/obj/machinery/ai_slipper/proc/ToggleOn()
if(stat & (NOPOWER|BROKEN))
return
disabled = !disabled
stat |= NOPOWER
update_icon()
/obj/machinery/ai_slipper/proc/Activate()
/obj/machinery/ai_slipper/attack_ai(mob/user)
add_hiddenprint(user)
return attack_hand(user)
/obj/machinery/ai_slipper/attack_ghost(mob/user)
if(user.can_advanced_admin_interact())
Activate(user)
/obj/machinery/ai_slipper/attack_hand(mob/user)
if(stat & (NOPOWER|BROKEN))
to_chat(user, "<span class='warning'>[src] has no power or is broken!</span>")
return
if(!allowed(user))
to_chat(user, "<span class='warning'>Access denied.</span>")
return
Activate(user)
/obj/machinery/ai_slipper/proc/Activate(mob/user)
if(stat & (NOPOWER|BROKEN))
return
if(cooldown_on || disabled)
if(!uses)
to_chat(user, "<span class='warning'>[src] is empty!</span>")
return
if(cooldown_on)
to_chat(user, "<span class='warning'>[src] is still recharging!</span>")
return
else
new /obj/effect/particle_effect/foam(loc)
uses--
cooldown_on = TRUE
cooldown_time = world.timeofday + 100
slip_process()
power_change()
addtimer(CALLBACK(src, .proc/recharge), cooldown_time)
/obj/machinery/ai_slipper/update_icon()
if(stat & (NOPOWER|BROKEN) || disabled)
if(stat & (NOPOWER|BROKEN) || cooldown_on || !uses)
icon_state = "liquid_dispenser"
else
icon_state = "liquid_dispenser_on"
/obj/machinery/ai_slipper/attack_ai(mob/user)
return attack_hand(user)
/obj/machinery/ai_slipper/attack_ghost(mob/user)
return attack_hand(user)
/obj/machinery/ai_slipper/attack_hand(mob/user)
if(stat & (NOPOWER|BROKEN))
/obj/machinery/ai_slipper/proc/recharge()
if(!uses)
return
if(get_dist(src, user) > 1 && (!issilicon(user) && !user.can_admin_interact()))
to_chat(user, "<span class='warning'>Too far away.</span>")
user.unset_machine()
user << browse(null, "window=ai_slipper")
return
user.set_machine(src)
var/area/myarea = get_area(src)
var/t = "<TT><B>AI Liquid Dispenser</B> ([myarea.name])<HR>"
if(locked && (!issilicon(user) && !user.can_admin_interact()))
t += "<I>(Swipe ID card to unlock control panel.)</I><BR>"
else
t += text("Dispenser [] - <A href='?src=[UID()];toggleOn=1'>[]?</a><br>\n", disabled ? "deactivated" : "activated", disabled ? "Enable" : "Disable")
t += text("Uses Left: [uses]. <A href='?src=[UID()];toggleUse=1'>Activate the dispenser?</A><br>\n")
user << browse(t, "window=computer;size=575x450")
onclose(user, "computer")
/obj/machinery/ai_slipper/Topic(href, href_list)
if(..())
return 1
if(locked && (!issilicon(usr) && !usr.can_admin_interact()))
to_chat(usr, "Control panel is locked!")
return 1
if(href_list["toggleOn"])
ToggleOn()
if(href_list["toggleUse"])
Activate()
attack_hand(usr)
/obj/machinery/ai_slipper/proc/slip_process()
while(cooldown_time - world.timeofday > 0)
var/ticksleft = cooldown_time - world.timeofday
if(ticksleft > 1e5)
cooldown_time = world.timeofday + 10 // midnight rollover
cooldown_timeleft = (ticksleft / 10)
sleep(5)
if(uses <= 0)
return
if(uses >= 0)
cooldown_on = FALSE
cooldown_on = FALSE
power_change()
+1 -123
View File
@@ -7,7 +7,6 @@
max_integrity = 100
var/state = 0
var/obj/item/circuitboard/circuit = null
var/base_mineral = /obj/item/stack/sheet/metal
/obj/structure/computerframe/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
@@ -18,7 +17,7 @@
deconstruct()
/obj/structure/computerframe/proc/drop_computer_parts()
new base_mineral(loc, 5)
new /obj/item/stack/sheet/metal(loc, 5)
if(circuit)
circuit.forceMove(loc)
circuit = null
@@ -357,14 +356,6 @@
build_path = /obj/machinery/computer/turbine_computer
origin_tech = "programming=4;engineering=4;powerstorage=4"
/obj/item/circuitboard/HONKputer
name = "Circuit board (HONKputer)"
build_path = /obj/machinery/computer/HONKputer
origin_tech = "programming=2"
icon = 'icons/obj/machines/HONKputer.dmi'
icon_state = "bananium_board"
board_type = "honkcomputer"
/obj/item/circuitboard/supplycomp/attackby(obj/item/I as obj, mob/user as mob, params)
if(istype(I,/obj/item/multitool))
@@ -552,116 +543,3 @@
if(I.use_tool(src, user, 50, volume = I.tool_volume) && !state)
to_chat(user, "<span class='notice'>You deconstruct [src].</span>")
deconstruct(TRUE)
/obj/structure/computerframe/HONKputer
name = "Bananium Computer-frame"
icon = 'icons/obj/machines/HONKputer.dmi'
base_mineral = /obj/item/stack/sheet/mineral/bananium
/obj/structure/computerframe/HONKputer/attackby(obj/item/P as obj, mob/user as mob, params)
switch(state)
if(0)
if(istype(P, /obj/item/wrench))
playsound(loc, P.usesound, 50, 1)
if(do_after(user, 20, target = src))
to_chat(user, "<span class='notice'>You wrench the frame into place.</span>")
anchored = 1
state = 1
if(1)
if(istype(P, /obj/item/wrench))
playsound(loc, P.usesound, 50, 1)
if(do_after(user, 20 * P.toolspeed, target = src))
to_chat(user, "<span class='notice'>You unfasten the frame.</span>")
anchored = 0
state = 0
if(istype(P, /obj/item/circuitboard) && !circuit)
var/obj/item/circuitboard/B = P
if(B.board_type == "honkcomputer")
playsound(loc, P.usesound, 50, 1)
to_chat(user, "<span class='notice'>You place the circuit board inside the frame.</span>")
icon_state = "1"
circuit = P
user.drop_item()
P.loc = src
else
to_chat(user, "<span class='warning'>This frame does not accept circuit boards of this type!</span>")
if(istype(P, /obj/item/screwdriver) && circuit)
playsound(loc, P.usesound, 50, 1)
to_chat(user, "<span class='notice'>You screw the circuit board into place.</span>")
state = 2
icon_state = "2"
if(istype(P, /obj/item/crowbar) && circuit)
playsound(loc, P.usesound, 50, 1)
to_chat(user, "<span class='notice'>You remove the circuit board.</span>")
state = 1
icon_state = "0"
circuit.loc = loc
circuit = null
return
if(2)
if(istype(P, /obj/item/screwdriver) && circuit)
playsound(loc, P.usesound, 50, 1)
to_chat(user, "<span class='notice'>You unfasten the circuit board.</span>")
state = 1
icon_state = "1"
if(istype(P, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = P
if(C.get_amount() >= 5)
playsound(loc, C.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add cables to the frame.</span>")
if(do_after(user, 20 * C.toolspeed, target = src))
if(state == 2 && C.get_amount() >= 5 && C.use(5))
to_chat(user, "<span class='notice'>You add cables to the frame.</span>")
state = 3
icon_state = "3"
else
to_chat(user, "<span class='warning'>At some point during construction you lost some cable. Make sure you have five lengths before trying again.</span>")
return
else
to_chat(user, "<span class='warning'>You need five lengths of cable to wire the frame.</span>")
return
if(3)
if(istype(P, /obj/item/wirecutters))
playsound(loc, P.usesound, 50, 1)
to_chat(user, "<span class='notice'>You remove the cables.</span>")
state = 2
icon_state = "2"
var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( loc )
A.amount = 5
if(istype(P, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = P
if(G.get_amount() >= 2)
playsound(loc, G.usesound, 50, 1)
to_chat(user, "<span class='notice'>You start to add the glass panel to the frame.</span>")
if(do_after(user, 20 * G.toolspeed, target = src))
if(state == 3 && G.get_amount() >= 2 && G.use(2))
to_chat(user, "<span class='notice'>You put in the glass panel.</span>")
state = 4
icon_state = "4"
else
to_chat(user, "<span class='warning'>At some point during construction you lost some glass. Make sure you have two sheets before trying again.</span>")
return
else
to_chat(user, "<span class='warning'>You need two sheets of glass for this.</span>")
return
if(4)
if(istype(P, /obj/item/crowbar))
playsound(loc, P.usesound, 50, 1)
to_chat(user, "<span class='notice'>You remove the glass panel.</span>")
state = 3
icon_state = "3"
new /obj/item/stack/sheet/glass(loc, 2)
if(istype(P, /obj/item/screwdriver))
playsound(loc, P.usesound, 50, 1)
to_chat(user, "<span class='notice'>You connect the monitor.</span>")
var/B = new circuit.build_path (loc)
if(circuit.powernet) B:powernet = circuit.powernet
if(circuit.id) B:id = circuit.id
if(circuit.records) B:records = circuit.records
if(circuit.frequency) B:frequency = circuit.frequency
qdel(src)
return
return ..()
@@ -75,7 +75,7 @@
for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
if(!C.can_use())
continue
if(C.network&networks)
if(length(C.network & networks))
camera_location = get_turf(C)
break
if(camera_location)
@@ -101,6 +101,8 @@
/mob/camera/aiEye/remote
name = "Inactive Camera Eye"
// Abductors dont trigger the Ai Detector
ai_detector_visible = FALSE
var/sprint = 10
var/cooldown = 0
var/acceleration = 1
-118
View File
@@ -1,118 +0,0 @@
/obj/machinery/computer/HONKputer
name = "\improper HONKputer Mark I"
desc = "A yellow computer used in case of critically low levels of HONK."
icon = 'icons/obj/machines/HONKputer.dmi'
icon_state = "honkputer"
icon_keyboard = "key_honk"
icon_screen = "honkcomms"
light_color = LIGHT_COLOR_PINK
req_access = list(ACCESS_CLOWN)
circuit = /obj/item/circuitboard/HONKputer
var/authenticated = 0
var/message_cooldown = 0
var/state = STATE_DEFAULT
var/const/STATE_DEFAULT = 1
/obj/machinery/computer/HONKputer/process()
if(..())
src.updateDialog()
/obj/machinery/computer/HONKputer/Topic(href, href_list)
if(..())
return 1
if(is_away_level(src.z))
to_chat(usr, "<span class='danger'>Unable to establish a connection</span>: You're too far away from the station!")
return
usr.set_machine(src)
if(!href_list["operation"])
return
switch(href_list["operation"])
// main interface
if("main")
src.state = STATE_DEFAULT
if("login")
var/mob/M = usr
var/obj/item/card/id/I = M.get_active_hand()
if(istype(I, /obj/item/pda))
var/obj/item/pda/pda = I
I = pda.id
if(I && istype(I))
if(src.check_access(I) || src.emagged==1)
authenticated = 1
if("logout")
authenticated = 0
if("MessageHonkplanet")
if(src.authenticated==1)
if(message_cooldown)
to_chat(usr, "Arrays recycling. Please stand by.")
return
var/input = stripped_input(usr, "Please choose a message to transmit to your HONKbrothers on the homeworld. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
if(!input || !(usr in view(1,src)))
return
HONK_announce(input, usr)
to_chat(usr, "Message transmitted.")
log_game("[key_name(usr)] has made a HONKplanet announcement: [input]")
message_cooldown = 1
spawn(6000)//10 minute cooldown
message_cooldown = 0
src.updateUsrDialog()
/obj/machinery/computer/HONKputer/emag_act(user as mob)
if(!emagged)
src.emagged = 1
to_chat(user, "You scramble the login circuits, allowing anyone to use the console!")
/obj/machinery/computer/HONKputer/attack_hand(mob/user as mob)
if(..())
return
if(is_away_level(src.z))
to_chat(user, "<span class='danger'>Unable to establish a connection</span>: You're too far away from the station!")
return
user.set_machine(src)
var/dat = "<head><title>HONKputer Interface</title></head><body>"
if(istype(user, /mob/living/silicon))
to_chat(user, "This console is not networked to the rest of the grid.")
return
switch(src.state)
if(STATE_DEFAULT)
if(src.authenticated)
dat += "<BR>\[ <A HREF='?src=[UID()];operation=logout'>Log Out</A> \]"
dat += "<BR>\[ <A HREF='?src=[UID()];operation=MessageHonkplanet'>Send an emergency message to Honkplanet</A> \]"
else
dat += "<BR>\[ <A HREF='?src=[UID()];operation=login'>Log In</A> \]"
dat += "<BR>\[ [(src.state != STATE_DEFAULT) ? "<A HREF='?src=[UID()];operation=main'>Main Menu</A> | " : ""]<A HREF='?src=[user.UID()];mach_close=honkputer'>Close</A> \]"
user << browse(dat, "window=honkputer;size=400x500")
onclose(user, "honkputer")
/obj/machinery/computer/HONKputer/attackby(obj/I, mob/user, params)
if(istype(I, /obj/item/screwdriver) && circuit)
var/obj/item/screwdriver/S = I
playsound(src.loc, S.usesound, 50, 1)
if(do_after(user, 20 * S.toolspeed, target = src))
var/obj/structure/computerframe/HONKputer/A = new /obj/structure/computerframe/HONKputer( src.loc )
var/obj/item/circuitboard/M = new circuit( A )
A.circuit = M
A.anchored = 1
for(var/obj/C in src)
C.loc = src.loc
if(src.stat & BROKEN)
to_chat(user, "<span class='notice'>The broken glass falls out.</span>")
new /obj/item/shard( src.loc )
A.state = 3
A.icon_state = "3"
else
to_chat(user, "<span class='notice'>You disconnect the monitor.</span>")
A.state = 4
A.icon_state = "4"
qdel(src)
else
return ..()
@@ -1,110 +0,0 @@
#define SALVAGE_SHIP_MOVE_TIME 300
#define SALVAGE_SHIP_COOLDOWN 800
/obj/machinery/computer/salvage_ship
name = "salvage ship terminal"
icon = 'icons/obj/computer.dmi'
icon_keyboard = "syndie_key"
icon_screen = "syndishuttle"
req_access = list(ACCESS_SALVAGE_CAPTAIN)
var/area/curr_location
var/moving = 0
var/lastMove = 0
/obj/machinery/computer/salvage_ship/New()
. = ..()
curr_location = locate(/area/shuttle/salvage/start)
/obj/machinery/computer/salvage_ship/proc/salvage_move_to(area/destination as area)
if(moving) return
if(lastMove + SALVAGE_SHIP_COOLDOWN > world.time) return
var/area/dest_location = locate(destination)
if(curr_location == dest_location) return
moving = 1
lastMove = world.time
if(curr_location.z != dest_location.z)
var/area/transit_location = locate(/area/shuttle/salvage/transit)
curr_location.move_contents_to(transit_location)
curr_location = transit_location
sleep(SALVAGE_SHIP_MOVE_TIME)
curr_location.move_contents_to(dest_location)
curr_location = dest_location
moving = 0
return 1
/obj/machinery/computer/salvage_ship/attack_ai(mob/user as mob)
src.add_hiddenprint(user)
return attack_hand(user)
/obj/machinery/computer/salvage_ship/attack_hand(mob/user as mob)
if(!allowed(user))
to_chat(user, "<span class='warning'>Access Denied</span>")
return
user.set_machine(src)
var/dat = {"Location: [curr_location]<br>
Ready to move[max(lastMove + SALVAGE_SHIP_COOLDOWN - world.time, 0) ? " in [max(round((lastMove + SALVAGE_SHIP_COOLDOWN - world.time) * 0.1), 0)] seconds" : ": now"]<br>
<a href='?src=[UID()];start=1'>Middle of Nowhere</a><br>
<a href='?src=[UID()];arrivals=1'>Station Auxiliary Docking</a> |
<a href='?src=[UID()];north=1'>North of the Station</a> |
<a href='?src=[UID()];east=1'>East of the Station</a> |
<a href='?src=[UID()];south=1'>South of the Station</a><br>
<a href='?src=[UID()];trading_post=1'>Trading Post</a><br>
<a href='?src=[UID()];clown_asteroid=1'>Clown Asteroid</a> |
<a href='?src=[UID()];derelict=1'>Derelict Station</a> |
<a href='?src=[UID()];djstation=1'>Ruskie DJ Station</a><br>
<a href='?src=[UID()];commssat=1'>Communications Satellite</a> |
<a href='?src=[UID()];abandoned_ship=1'>Abandoned Ship</a><br>
<a href='?src=[user.UID()];mach_close=computer'>Close</a>"}
user << browse(dat, "window=computer;size=575x450")
onclose(user, "computer")
return
/obj/machinery/computer/salvage_ship/Topic(href, href_list)
if(..())
return 1
if(!isliving(usr)) return
var/mob/living/user = usr
if(in_range(src, user) || istype(user, /mob/living/silicon))
user.set_machine(src)
if(href_list["salvage"])
salvage_move_to(/area/shuttle/salvage/start)
else if(href_list["start"])
salvage_move_to(/area/shuttle/salvage/start)
else if(href_list["arrivals"])
salvage_move_to(/area/shuttle/salvage/arrivals)
else if(href_list["derelict"])
salvage_move_to(/area/shuttle/salvage/derelict)
else if(href_list["djstation"])
salvage_move_to(/area/shuttle/salvage/djstation)
else if(href_list["north"])
salvage_move_to(/area/shuttle/salvage/north)
else if(href_list["east"])
salvage_move_to(/area/shuttle/salvage/east)
else if(href_list["south"])
salvage_move_to(/area/shuttle/salvage/south)
else if(href_list["commssat"])
salvage_move_to(/area/shuttle/salvage/commssat)
else if(href_list["abandoned_ship"])
salvage_move_to(/area/shuttle/salvage/abandoned_ship)
else if(href_list["clown_asteroid"])
salvage_move_to(/area/shuttle/salvage/clown_asteroid)
else if(href_list["trading_post"])
salvage_move_to(/area/shuttle/salvage/trading_post)
add_fingerprint(usr)
updateUsrDialog()
return
/obj/machinery/computer/salvage_ship/bullet_act(obj/item/projectile/Proj)
visible_message("[Proj] ricochets off [src]!")
@@ -1,338 +0,0 @@
//Config stuff
#define SPECOPS_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves.
#define SPECOPS_STATION_AREATYPE "/area/shuttle/specops/station" //Type of the spec ops shuttle area for station
#define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock
#define SPECOPS_RETURN_DELAY 6000 //Time between the shuttle is capable of moving.
GLOBAL_VAR_INIT(specops_shuttle_moving_to_station, 0)
GLOBAL_VAR_INIT(specops_shuttle_moving_to_centcom, 0)
GLOBAL_VAR_INIT(specops_shuttle_at_station, 0)
GLOBAL_VAR_INIT(specops_shuttle_can_send, 1)
GLOBAL_VAR_INIT(specops_shuttle_time, 0)
GLOBAL_VAR_INIT(specops_shuttle_timeleft, 0)
/obj/machinery/computer/specops_shuttle
name = "\improper Spec. Ops. shuttle console"
icon = 'icons/obj/computer.dmi'
icon_keyboard = "security_key"
icon_screen = "syndishuttle"
light_color = LIGHT_COLOR_PURE_CYAN
req_access = list(ACCESS_CENT_SPECOPS)
// req_access = list(ACCESS_CENT_SPECOPS)
var/temp = null
var/hacked = 0
var/allowedtocall = 0
var/specops_shuttle_timereset = 0
/proc/specops_return()
var/obj/item/radio/intercom/announcer = new /obj/item/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
announcer.config(list("Response Team" = 0))
var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
var/message = "\"THE SPECIAL OPERATIONS SHUTTLE IS PREPARING TO RETURN\""//Initial message shown.
if(announcer)
announcer.autosay(message, "A.L.I.C.E.", "Response Team", list(1,2))
while(GLOB.specops_shuttle_time - world.timeofday > 0)
var/ticksleft = GLOB.specops_shuttle_time - world.timeofday
if(ticksleft > 1e5)
GLOB.specops_shuttle_time = world.timeofday + 10 // midnight rollover
GLOB.specops_shuttle_timeleft = (ticksleft / 10)
//All this does is announce the time before launch.
if(announcer)
var/rounded_time_left = round(GLOB.specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions.
if(rounded_time_left in message_tracker)//If that time is in the list for message announce.
message = "\"ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN\""
if(rounded_time_left==0)
message = "\"ALERT: TAKEOFF\""
announcer.autosay(message, "A.L.I.C.E.", "Response Team")
message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle.
//Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that.
sleep(5)
GLOB.specops_shuttle_moving_to_station = 0
GLOB.specops_shuttle_moving_to_centcom = 0
GLOB.specops_shuttle_at_station = 1
var/area/start_location = locate(/area/shuttle/specops/station)
var/area/end_location = locate(/area/shuttle/specops/centcom)
var/list/dstturfs = list()
var/throwy = world.maxy
for(var/turf/T in end_location)
dstturfs += T
if(T.y < throwy)
throwy = T.y
// hey you, get out of the way!
for(var/turf/T in dstturfs)
// find the turf to move things to
var/turf/D = locate(T.x, throwy - 1, 1)
//var/turf/E = get_step(D, SOUTH)
for(var/atom/movable/AM as mob|obj in T)
AM.Move(D)
if(istype(T, /turf/simulated))
qdel(T)
for(var/mob/living/carbon/bug in end_location) // If someone somehow is still in the shuttle's docking area...
bug.gib()
for(var/mob/living/simple_animal/pest in end_location) // And for the other kind of bug...
pest.gib()
start_location.move_contents_to(end_location)
for(var/turf/T in get_area_turfs(end_location) )
var/mob/M = locate(/mob) in T
to_chat(M, "<span class='warning'>You have arrived at Central Command. Operation has ended!</span>")
GLOB.specops_shuttle_at_station = 0
for(var/obj/machinery/computer/specops_shuttle/S in GLOB.machines)
S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY
qdel(announcer)
/proc/specops_process()
var/area/centcom/specops/special_ops = locate()//Where is the specops area located?
var/obj/item/radio/intercom/announcer = new /obj/item/radio/intercom(null)//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
announcer.config(list("Response Team" = 0))
var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
var/message = "\"THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH\""//Initial message shown.
if(announcer)
announcer.autosay(message, "A.L.I.C.E.", "Response Team")
//message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD"
//announcer.autosay(message, "A.L.I.C.E.", "Response Team")
while(GLOB.specops_shuttle_time - world.timeofday > 0)
var/ticksleft = GLOB.specops_shuttle_time - world.timeofday
if(ticksleft > 1e5)
GLOB.specops_shuttle_time = world.timeofday + 10 // midnight rollover
GLOB.specops_shuttle_timeleft = (ticksleft / 10)
//All this does is announce the time before launch.
if(announcer)
var/rounded_time_left = round(GLOB.specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions.
if(rounded_time_left in message_tracker)//If that time is in the list for message announce.
message = "\"ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN\""
if(rounded_time_left==0)
message = "\"ALERT: TAKEOFF\""
announcer.autosay(message, "A.L.I.C.E.", "Response Team")
message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle.
//Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that.
sleep(5)
GLOB.specops_shuttle_moving_to_station = 0
GLOB.specops_shuttle_moving_to_centcom = 0
GLOB.specops_shuttle_at_station = 1
if(GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom) return
if(!specops_can_move())
to_chat(usr, "<span class='warning'>The Special Operations shuttle is unable to leave.</span>")
return
//Begin Marauder launchpad.
spawn(0)//So it parallel processes it.
for(var/obj/machinery/door/poddoor/M in special_ops)
switch(M.id_tag)
if("ASSAULT0")
spawn(10)//1 second delay between each.
M.open()
if("ASSAULT1")
spawn(20)
M.open()
if("ASSAULT2")
spawn(30)
M.open()
if("ASSAULT3")
spawn(40)
M.open()
sleep(10)
var/spawn_marauder[] = new()
for(var/thing in GLOB.landmarks_list)
var/obj/effect/landmark/L = thing
if(L.name == "Marauder Entry")
spawn_marauder.Add(L.loc)
for(var/thing in GLOB.landmarks_list)
var/obj/effect/landmark/L = thing
if(L.name == "Marauder Exit")
var/obj/effect/portal/P = new(L.loc, pick(spawn_marauder))
//P.invisibility = 101//So it is not seen by anyone.
P.failchance = 0//So it has no fail chance when teleporting.
spawn_marauder.Remove(P.target)
sleep(10)
for(var/obj/machinery/mass_driver/M in special_ops)
switch(M.id_tag)
if("ASSAULT0")
spawn(10)
M.drive()
if("ASSAULT1")
spawn(20)
M.drive()
if("ASSAULT2")
spawn(30)
M.drive()
if("ASSAULT3")
spawn(40)
M.drive()
sleep(50)//Doors remain open for 5 seconds.
for(var/obj/machinery/door/poddoor/M in special_ops)
switch(M.id_tag)//Doors close at the same time.
if("ASSAULT0")
spawn(0)
M.close()
if("ASSAULT1")
spawn(0)
M.close()
if("ASSAULT2")
spawn(0)
M.close()
if("ASSAULT3")
spawn(0)
M.close()
//End Marauder launchpad.
var/area/start_location = locate(/area/shuttle/specops/centcom)
var/area/end_location = locate(/area/shuttle/specops/station)
var/list/dstturfs = list()
var/throwy = world.maxy
for(var/turf/T in end_location)
dstturfs += T
if(T.y < throwy)
throwy = T.y
// hey you, get out of the way!
for(var/turf/T in dstturfs)
// find the turf to move things to
var/turf/D = locate(T.x, throwy - 1, 1)
//var/turf/E = get_step(D, SOUTH)
for(var/atom/movable/AM as mob|obj in T)
AM.Move(D)
if(istype(T, /turf/simulated))
qdel(T)
start_location.move_contents_to(end_location)
for(var/turf/T in get_area_turfs(end_location) )
var/mob/M = locate(/mob) in T
to_chat(M, "<span class='warning'>You have arrived to [station_name()]. Commence operation!</span>")
for(var/obj/machinery/computer/specops_shuttle/S in GLOB.machines)
S.specops_shuttle_timereset = world.time + SPECOPS_RETURN_DELAY
qdel(announcer)
/proc/specops_can_move()
if(GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom)
return 0
for(var/obj/machinery/computer/specops_shuttle/S in GLOB.machines)
if(world.timeofday <= S.specops_shuttle_timereset)
return 0
return 1
/obj/machinery/computer/specops_shuttle/attack_ai(mob/user as mob)
to_chat(user, "<span class='warning'>Access Denied.</span>")
return 1
/obj/machinery/computer/specops_shuttle/attackby(I as obj, user as mob, params)
if(istype(I,/obj/item/card/emag))
to_chat(user, "<span class='notice'>The electronic systems in this console are far too advanced for your primitive hacking peripherals.</span>")
else
return ..()
/obj/machinery/computer/specops_shuttle/attack_hand(mob/user as mob)
if(!allowed(user))
to_chat(user, "<span class='warning'>Access Denied.</span>")
return
//Commented out so admins can do shenanigans at their leisure. Also makes the force-spawned admin ERTs able to use the shuttle.
// if(sent_strike_team == 0 && send_emergency_team == 0)
// to_chat(usr, "<span class='warning'>The strike team has not yet deployed.</span>")
// return
if(..())
return
user.machine = src
var/dat
if(temp)
dat = temp
else
dat += {"<BR><B>Special Operations Shuttle</B><HR>
\nLocation: [GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom ? "Departing for [station_name()] in ([GLOB.specops_shuttle_timeleft] seconds.)":GLOB.specops_shuttle_at_station ? "Station":"Dock"]<BR>
[GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*<BR>\n<BR>":GLOB.specops_shuttle_at_station ? "\n<A href='?src=[UID()];sendtodock=1'>Shuttle standing by...</A><BR>\n<BR>":"\n<A href='?src=[UID()];sendtostation=1'>Depart to [station_name()]</A><BR>\n<BR>"]
\n<A href='?src=[user.UID()];mach_close=computer'>Close</A>"}
user << browse(dat, "window=computer;size=575x450")
onclose(user, "computer")
return
/obj/machinery/computer/specops_shuttle/Topic(href, href_list)
if(..())
return 1
if((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.machine = src
if(href_list["sendtodock"])
if(!GLOB.specops_shuttle_at_station|| GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom) return
if(!specops_can_move())
to_chat(usr, "<span class='notice'>Central Command will not allow the Special Operations shuttle to return yet.</span>")
if(world.timeofday <= specops_shuttle_timereset)
if(((world.timeofday - specops_shuttle_timereset)/10) > 60)
to_chat(usr, "<span class='notice'>[-((world.timeofday - specops_shuttle_timereset)/10)/60] minutes remain!</span>")
to_chat(usr, "<span class='notice'>[-(world.timeofday - specops_shuttle_timereset)/10] seconds remain!</span>")
return
to_chat(usr, "<span class='notice'>The Special Operations shuttle will arrive at Central Command in [(SPECOPS_MOVETIME/10)] seconds.</span>")
temp += "Shuttle departing.<BR><BR><A href='?src=[UID()];mainmenu=1'>OK</A>"
updateUsrDialog()
GLOB.specops_shuttle_moving_to_centcom = 1
GLOB.specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME
spawn(0)
specops_return()
else if(href_list["sendtostation"])
if(GLOB.specops_shuttle_at_station || GLOB.specops_shuttle_moving_to_station || GLOB.specops_shuttle_moving_to_centcom) return
if(!specops_can_move())
to_chat(usr, "<span class='warning'>The Special Operations shuttle is unable to leave.</span>")
return
to_chat(usr, "<span class='notice'>The Special Operations shuttle will arrive on [station_name()] in [(SPECOPS_MOVETIME/10)] seconds.</span>")
temp += "Shuttle departing.<BR><BR><A href='?src=[UID()];mainmenu=1'>OK</A>"
updateUsrDialog()
GLOB.specops_shuttle_moving_to_station = 1
GLOB.specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME
spawn(0)
specops_process()
else if(href_list["mainmenu"])
temp = null
add_fingerprint(usr)
updateUsrDialog()
return
@@ -1,254 +0,0 @@
//Config stuff
#define SYNDICATE_ELITE_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves.
#define SYNDICATE_ELITE_STATION_AREATYPE "/area/shuttle/syndicate_elite/station" //Type of the spec ops shuttle area for station
#define SYNDICATE_ELITE_DOCK_AREATYPE "/area/shuttle/syndicate_elite/mothership" //Type of the spec ops shuttle area for dock
GLOBAL_VAR_INIT(syndicate_elite_shuttle_moving_to_station, 0)
GLOBAL_VAR_INIT(syndicate_elite_shuttle_moving_to_mothership, 0)
GLOBAL_VAR_INIT(syndicate_elite_shuttle_at_station, 0)
GLOBAL_VAR_INIT(syndicate_elite_shuttle_can_send, 1)
GLOBAL_VAR_INIT(syndicate_elite_shuttle_time, 0)
GLOBAL_VAR_INIT(syndicate_elite_shuttle_timeleft, 0)
/obj/machinery/computer/syndicate_elite_shuttle
name = "\improper Elite Syndicate Squad shuttle console"
icon = 'icons/obj/computer.dmi'
icon_keyboard = "syndie_key"
icon_screen = "syndishuttle"
light_color = LIGHT_COLOR_PURE_CYAN
req_access = list(ACCESS_SYNDICATE)
bubble_icon = "syndibot"
var/temp = null
var/hacked = 0
var/allowedtocall = 0
/proc/syndicate_elite_process()
var/area/syndicate_mothership/control/syndicate_ship = locate()//To find announcer. This area should exist for this proc to work.
//var/area/syndicate_mothership/elite_squad/elite_squad = locate()//Where is the specops area located?
var/mob/living/silicon/decoy/announcer = locate() in syndicate_ship//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
var/message = "THE SYNDICATE ELITE SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown.
if(announcer)
announcer.say(message)
// message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD"
// announcer.say(message)
while(GLOB.syndicate_elite_shuttle_time - world.timeofday > 0)
var/ticksleft = GLOB.syndicate_elite_shuttle_time - world.timeofday
if(ticksleft > 1e5)
GLOB.syndicate_elite_shuttle_time = world.timeofday // midnight rollover
GLOB.syndicate_elite_shuttle_timeleft = (ticksleft / 10)
//All this does is announce the time before launch.
if(announcer)
var/rounded_time_left = round(GLOB.syndicate_elite_shuttle_timeleft)//Round time so that it will report only once, not in fractions.
if(rounded_time_left in message_tracker)//If that time is in the list for message announce.
message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN"
if(rounded_time_left==0)
message = "ALERT: TAKEOFF"
announcer.say(message)
message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle.
//Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that.
sleep(5)
GLOB.syndicate_elite_shuttle_moving_to_station = 0
GLOB.syndicate_elite_shuttle_moving_to_mothership = 0
GLOB.syndicate_elite_shuttle_at_station = 1
if(GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership) return
if(!syndicate_elite_can_move())
to_chat(usr, "<span class='warning'>The Syndicate Elite shuttle is unable to leave.</span>")
return
/*
//Begin Marauder launchpad.
spawn(0)//So it parallel processes it.
for(var/obj/machinery/door/poddoor/M in elite_squad)
switch(M.id)
if("ASSAULT0")
spawn(10)//1 second delay between each.
M.open()
if("ASSAULT1")
spawn(20)
M.open()
if("ASSAULT2")
spawn(30)
M.open()
if("ASSAULT3")
spawn(40)
M.open()
sleep(10)
var/spawn_marauder[] = new()
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
if(L.name == "Marauder Entry")
spawn_marauder.Add(L)
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
if(L.name == "Marauder Exit")
var/obj/effect/portal/P = new(L.loc)
P.invisibility = 101//So it is not seen by anyone.
P.failchance = 0//So it has no fail chance when teleporting.
P.target = pick(spawn_marauder)//Where the marauder will arrive.
spawn_marauder.Remove(P.target)
sleep(10)
for(var/obj/machinery/mass_driver/M in elite_squad)
switch(M.id)
if("ASSAULT0")
spawn(10)
M.drive()
if("ASSAULT1")
spawn(20)
M.drive()
if("ASSAULT2")
spawn(30)
M.drive()
if("ASSAULT3")
spawn(40)
M.drive()
sleep(50)//Doors remain open for 5 seconds.
for(var/obj/machinery/door/poddoor/M in elite_squad)
switch(M.id)//Doors close at the same time.
if("ASSAULT0")
spawn(0)
M.close()
if("ASSAULT1")
spawn(0)
M.close()
if("ASSAULT2")
spawn(0)
M.close()
if("ASSAULT3")
spawn(0)
M.close()
elite_squad.readyreset()//Reset firealarm after the team launched.
*/
//End Marauder launchpad.
for(var/thing in GLOB.landmarks_list)
var/obj/effect/landmark/L = thing
if(L.name == "Syndicate Breach Area")
explosion(L.loc,4,6,8,10,0)
sleep(40)
var/area/start_location = locate(/area/shuttle/syndicate_elite/mothership)
var/area/end_location = locate(/area/shuttle/syndicate_elite/station)
var/list/dstturfs = list()
var/throwy = world.maxy
for(var/turf/T in end_location)
dstturfs = T
if(T.y < throwy)
throwy = T.y
// hey you, get out of the way!
for(var/turf/T in dstturfs)
// find the turf to move things to
var/turf/D = locate(T.x, throwy - 1, 1)
//var/turf/E = get_step(D, SOUTH)
for(var/atom/movable/AM as mob|obj in T)
AM.Move(D)
if(istype(T, /turf/simulated))
qdel(T)
for(var/mob/living/carbon/bug in end_location) // If someone somehow is still in the shuttle's docking area...
bug.gib()
for(var/mob/living/simple_animal/pest in end_location) // And for the other kind of bug...
pest.gib()
start_location.move_contents_to(end_location)
for(var/turf/T in get_area_turfs(end_location) )
var/mob/M = locate(/mob) in T
to_chat(M, "<span class='warning'>You have arrived to [station_name()]. Commence operation!</span>")
/proc/syndicate_elite_can_move()
if(GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership) return 0
else return 1
/obj/machinery/computer/syndicate_elite_shuttle/attack_ai(mob/user as mob)
to_chat(user, "<span class='warning'>Access Denied.</span>")
return 1
/obj/machinery/computer/syndicate_elite_shuttle/attackby(I as obj, user as mob, params)
if(istype(I,/obj/item/card/emag))
to_chat(user, "<span class='notice'>The electronic systems in this console are far too advanced for your primitive hacking peripherals.</span>")
else
return ..()
/obj/machinery/computer/syndicate_elite_shuttle/attack_hand(mob/user as mob)
if(!allowed(user))
to_chat(user, "<span class='warning'>Access Denied.</span>")
return
// if(sent_syndicate_strike_team == 0)
// to_chat(usr, "<span class='warning'>The strike team has not yet deployed.</span>")
// return
if(..())
return
user.set_machine(src)
var/dat
if(temp)
dat = temp
else
dat = {"<BR><B>Special Operations Shuttle</B><HR>
\nLocation: [GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership ? "Departing for [station_name()] in ([GLOB.syndicate_elite_shuttle_timeleft] seconds.)":GLOB.syndicate_elite_shuttle_at_station ? "Station":"Dock"]<BR>
[GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership ? "\n*The Syndicate Elite shuttle is already leaving.*<BR>\n<BR>":GLOB.syndicate_elite_shuttle_at_station ? "\n<A href='?src=[UID()];sendtodock=1'>Shuttle Offline</A><BR>\n<BR>":"\n<A href='?src=[UID()];sendtostation=1'>Depart to [station_name()]</A><BR>\n<BR>"]
\n<A href='?src=[user.UID()];mach_close=computer'>Close</A>"}
user << browse(dat, "window=computer;size=575x450")
onclose(user, "computer")
return
/obj/machinery/computer/syndicate_elite_shuttle/Topic(href, href_list)
if(..())
return 1
if((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src)
if(href_list["sendtodock"])
if(!GLOB.syndicate_elite_shuttle_at_station|| GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership) return
to_chat(usr, "<span class='notice'>The Syndicate will not allow the Elite Squad shuttle to return.</span>")
return
else if(href_list["sendtostation"])
if(GLOB.syndicate_elite_shuttle_at_station || GLOB.syndicate_elite_shuttle_moving_to_station || GLOB.syndicate_elite_shuttle_moving_to_mothership) return
if(!specops_can_move())
to_chat(usr, "<span class='warning'>The Syndicate Elite shuttle is unable to leave.</span>")
return
to_chat(usr, "<span class='notice'>The Syndicate Elite shuttle will arrive on [station_name()] in [(SYNDICATE_ELITE_MOVETIME/10)] seconds.</span>")
temp = "Shuttle departing.<BR><BR><A href='?src=[UID()];mainmenu=1'>OK</A>"
updateUsrDialog()
GLOB.syndicate_elite_shuttle_moving_to_station = 1
GLOB.syndicate_elite_shuttle_time = world.timeofday + SYNDICATE_ELITE_MOVETIME
spawn(0)
syndicate_elite_process()
else if(href_list["mainmenu"])
temp = null
add_fingerprint(usr)
updateUsrDialog()
return
+4
View File
@@ -720,6 +720,10 @@
// Won't announce when used for cryoing.
silent = TRUE
/obj/machinery/cryopod/offstation/right
orient_right = TRUE
icon_state = "body_scanner_0-r"
/obj/machinery/computer/cryopod/robot
name = "robotic storage console"
desc = "An interface between crew and the robotic storage systems"
+2
View File
@@ -145,6 +145,8 @@
else if(our_rpd.mode == RPD_FLIP_MODE)
flip()
else if(our_rpd.mode == RPD_DELETE_MODE)
if(pipe_type == PIPE_CIRCULATOR) //Skip TEG heat circulators, they aren't really pipes
return ..()
our_rpd.delete_single_pipe(user, src)
else
return ..()
+6 -1
View File
@@ -657,6 +657,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
qdel(flick_holder)
set_raised_raising(FALSE, FALSE)
set_angle(0)
update_icon()
/obj/machinery/porta_turret/on_assess_perp(mob/living/carbon/human/perp)
@@ -678,7 +679,8 @@ GLOBAL_LIST_EMPTY(turret_icons)
last_target = target
if(has_cover)
popUp() //pop the turret up if it's not already up.
setDir(get_dir(src, target)) //even if you can't shoot, follow the target
// Set angle
set_angle(get_angle(src, target))
shootAt(target)
return TRUE
@@ -842,6 +844,9 @@ GLOBAL_LIST_EMPTY(turret_icons)
if(!user.unEquip(I))
to_chat(user, "<span class='notice'>\the [I] is stuck to your hand, you cannot put it in \the [src]</span>")
return
if(!E.can_fit_in_turrets)
to_chat(user, "<span class='notice'>[I] will not operate correctly in [src].</span>")
return
installation = I.type //installation becomes I.type
gun_charge = E.cell.charge //the gun's charge is stored in gun_charge
to_chat(user, "<span class='notice'>You add [I] to the turret.</span>")
+1 -1
View File
@@ -161,7 +161,7 @@
name = "syndicate suit storage unit"
suit_type = /obj/item/clothing/suit/space/hardsuit/syndi
mask_type = /obj/item/clothing/mask/gas/syndicate
storage_type = /obj/item/tank/jetpack/oxygen/harness
storage_type = /obj/item/tank/internals/oxygen/red
req_access = list(ACCESS_SYNDICATE)
safeties = FALSE //in a syndicate base, everything can be used as a murder weapon at a moment's notice.
+6 -3
View File
@@ -313,7 +313,7 @@
name = "teleporter hub"
desc = "It's the hub of a teleporting machine."
icon_state = "tele0"
var/accurate = FALSE
var/accurate = 0
use_power = IDLE_POWER_USE
idle_power_usage = 10
active_power_usage = 2000
@@ -353,6 +353,8 @@
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
A += M.rating
accurate = A
if(accurate >= 3)
calibrated = TRUE
/obj/machinery/teleport/hub/proc/link_power_station()
if(power_station)
@@ -401,12 +403,13 @@
if(!calibrated && com.cc_beacon)
visible_message("<span class='alert'>Cannot lock on target. Please calibrate the teleporter before attempting long range teleportation.</span>")
else if(!calibrated && prob(25 - ((accurate) * 10)) && !com.cc_beacon) //oh dear a problem
var/list/target_z = levels_by_trait(REACHABLE)
var/list/target_z = levels_by_trait(SPAWN_RUINS)
target_z -= M.z //Where to sir? Anywhere but here.
. = do_teleport(M, locate(rand((2*TRANSITIONEDGE), world.maxx - (2*TRANSITIONEDGE)), rand((2*TRANSITIONEDGE), world.maxy - (2*TRANSITIONEDGE)), pick(target_z)), 2, bypass_area_flag = com.area_bypass)
else
. = do_teleport(M, com.target, bypass_area_flag = com.area_bypass)
calibrated = FALSE
if(accurate < 3)
calibrated = FALSE
/obj/machinery/teleport/hub/update_icon()
if(panel_open)
+1 -1
View File
@@ -57,7 +57,7 @@
to_chat(user, "<span class='warning'>You feel a dark stirring inside of the Wish Granter, something you want nothing of. Your instincts are better than any man's.</warning>")
return TRUE
if(is_special_character(user) || jobban_isbanned(user, ROLE_TRAITOR) || jobban_isbanned(user, "Syndicate"))
if(is_special_character(user) || jobban_isbanned(user, ROLE_TRAITOR) || jobban_isbanned(user, ROLE_SYNDICATE))
to_chat(user, "<span class='warning'>Something instinctual makes you pull away.</span>")
return TRUE
@@ -483,7 +483,7 @@
if(R.can_synth && add_known_reagent(R.id, R.name))
occupant_message("Reagent analyzed, identified as [R.name] and added to database.")
send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form())
occupant_message("Analyzis complete.")
occupant_message("Analysis complete.")
return 1
/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/add_known_reagent(r_id,r_name)
+32 -24
View File
@@ -30,28 +30,38 @@
return
if(!cargo_holder)
return
if(istype(target,/obj))
if(isobj(target))
var/obj/O = target
if(!O.anchored)
if(cargo_holder.cargo.len < cargo_holder.cargo_capacity)
chassis.visible_message("[chassis] lifts [target] and starts to load it into cargo compartment.")
O.anchored = 1
if(do_after_cooldown(target))
cargo_holder.cargo += O
O.loc = chassis
O.anchored = 0
occupant_message("<span class='notice'>[target] successfully loaded.</span>")
log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]")
else
O.anchored = initial(O.anchored)
else
occupant_message("<span class='warning'>Not enough room in cargo compartment!</span>")
else
if(istype(target, /obj/machinery/power/supermatter_crystal)) //No, you can't pick up the SM with this you moron, did you think you were clever?
var/obj/mecha/working/ripley/R = chassis
QDEL_LIST(R.cargo) //We don't want to drop cargo that just spam hits the SM, let's delete it
occupant_message("<span class='userdanger'>You realise in horror what you have done as [chassis] starts warping around you!</span>")
chassis.occupant.dust()
target.Bumped(chassis)
return
if(O.anchored)
occupant_message("<span class='warning'>[target] is firmly secured!</span>")
return
if(length(cargo_holder.cargo) >= cargo_holder.cargo_capacity)
occupant_message("<span class='warning'>Not enough room in cargo compartment!</span>")
return
chassis.visible_message("<span class='notice'>[chassis] lifts [target] and starts to load it into cargo compartment.</span>")
var/anchor_state_before_load = O.anchored
O.anchored = TRUE
if(!do_after_cooldown(target))
O.anchored = anchor_state_before_load
return
cargo_holder.cargo += O
O.forceMove(chassis)
O.anchored = FALSE
occupant_message("<span class='notice'>[target] was successfully loaded.</span>")
log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - length(cargo_holder.cargo)]")
return
else if(istype(target,/mob/living))
if(isliving(target))
var/mob/living/M = target
if(M.stat == DEAD) return
if(M.stat == DEAD)
return
if(chassis.occupant.a_intent == INTENT_HARM)
M.take_overall_damage(dam_force)
if(!M)
@@ -62,12 +72,10 @@
"<span class='italics'>You hear something crack.</span>")
add_attack_logs(chassis.occupant, M, "Squeezed with [src] ([uppertext(chassis.occupant.a_intent)]) ([uppertext(damtype)])")
start_cooldown()
else
step_away(M,chassis)
occupant_message("<span class='notice'>You push [target] out of the way.</span>")
chassis.visible_message("<span class='notice'>[chassis] pushes [target] out of the way.</span>")
return 1
return
step_away(M, chassis)
occupant_message("<span class='notice'>You push [target] out of the way.</span>")
chassis.visible_message("<span class='notice'>[chassis] pushes [target] out of the way.</span>")
//This is pretty much just for the death-ripley
+3 -2
View File
@@ -1200,7 +1200,8 @@
/obj/mecha/Exited(atom/movable/M, atom/newloc)
if(occupant && occupant == M) // The occupant exited the mech without calling go_out()
go_out(1, newloc)
if(!isAI(occupant)) //This causes carded AIS to gib, so we do not want this to be called during carding.
go_out(1, newloc)
/obj/mecha/proc/go_out(forced, atom/newloc = loc)
if(!occupant)
@@ -1507,7 +1508,7 @@
if(internal_tank)
WR.crowbar_salvage += internal_tank
internal_tank.forceMove(WR)
cell = null
internal_tank = null
. = ..()
/obj/mecha/CtrlClick(mob/living/L)
+1 -1
View File
@@ -59,7 +59,7 @@
user.visible_message("<span class='notice'>[user] pries [S] from [src].</span>", "<span class='notice'>You pry [S] from [src].</span>")
crowbar_salvage -= S
return
to_chat(user, "<span class='notice'>You don't see anything that can be cut with [I]!</span>")
to_chat(user, "<span class='notice'>You don't see anything that can be pried with [I]!</span>")
/obj/structure/mecha_wreckage/welder_act(mob/user, obj/item/I)
. = TRUE
+4
View File
@@ -122,6 +122,10 @@
if(!in_range(user, src) || !isturf(user.loc) || user.incapacitated() || M.anchored)
return FALSE
if (isguardian(user))
if (M.loc == user.loc || user.alpha == 60) //Alpha is for detecting ranged guardians in scout mode
return //unmanifested guardians shouldn't be able to buckle mobs
add_fingerprint(user)
. = buckle_mob(M, check_loc = check_loc)
if(.)
@@ -53,6 +53,9 @@
/obj/effect/decal/cleanable/proc/can_bloodcrawl_in()
return FALSE
/obj/effect/decal/cleanable/is_cleanable()
return TRUE
/obj/effect/decal/cleanable/Initialize(mapload)
. = ..()
if(loc && isturf(loc))
+3
View File
@@ -25,6 +25,9 @@
/obj/effect/acid_act()
return
/obj/effect/proc/is_cleanable() //Called when you want to clean something, and usualy delete it after
return FALSE
/obj/effect/mech_melee_attack(obj/mecha/M)
return 0
+6 -2
View File
@@ -14,6 +14,7 @@
var/precision = TRUE // how close to the portal you will teleport. FALSE = on the portal, TRUE = adjacent
var/can_multitool_to_remove = FALSE
var/ignore_tele_proof_area_setting = FALSE
var/one_use = FALSE // Does this portal go away after one teleport?
/obj/effect/portal/New(loc, turf/target, creator = null, lifespan = 300)
..()
@@ -101,14 +102,17 @@
if(prob(failchance))
icon_state = fail_icon
if(!do_teleport(M, locate(rand(5, world.maxx - 5), rand(5, world.maxy -5), 3), 0, bypass_area_flag = ignore_tele_proof_area_setting)) // Try to send them to deep space.
var/list/target_z = levels_by_trait(SPAWN_RUINS)
target_z -= M.z
if(!do_teleport(M, locate(rand(5, world.maxx - 5), rand(5, world.maxy -5), pick(target_z)), 0, bypass_area_flag = ignore_tele_proof_area_setting)) // Try to send them to deep space.
invalid_teleport()
return FALSE
else
if(!do_teleport(M, target, precision, bypass_area_flag = ignore_tele_proof_area_setting)) // Try to send them to a turf adjacent to target.
invalid_teleport()
return FALSE
if(one_use)
qdel(src)
return TRUE
/obj/effect/portal/proc/invalid_teleport()
@@ -354,3 +354,12 @@
/obj/effect/temp_visual/impact_effect/ion
icon_state = "shieldsparkles"
duration = 6
/obj/effect/temp_visual/bsg_kaboom
name = "bluespace explosion"
icon = 'icons/effects/96x96.dmi'
icon_state = "explosionfast"
color = "blue"
pixel_x = -32
pixel_y = -32
duration = 42
+11
View File
@@ -424,6 +424,17 @@ GLOBAL_DATUM_INIT(fire_overlay, /image, image("icon" = 'icons/goonstation/effect
/obj/item/proc/on_enter_storage(obj/item/storage/S as obj)
return
/**
* Called to check if this item can be put into a storage item.
*
* Return `FALSE` if `src` can't be inserted, and `TRUE` if it can.
* Arguments:
* * S - The [/obj/item/storage] that `src` is being inserted into.
* * user - The mob trying to insert the item.
*/
/obj/item/proc/can_enter_storage(obj/item/storage/S, mob/user)
return TRUE
// called when "found" in pockets and storage items. Returns 1 if the search should end.
/obj/item/proc/on_found(mob/finder as mob)
return
+6
View File
@@ -30,6 +30,12 @@
else i = 3
icon_state = "candle[i][lit ? "_lit" : ""]"
/obj/item/candle/can_enter_storage(obj/item/storage/S, mob/user)
if(lit)
to_chat(user, "<span class='warning'>[S] can't hold [src] while it's lit!</span>")
return FALSE
else
return TRUE
/obj/item/candle/attackby(obj/item/W, mob/user, params)
if(is_hot(W))
-23
View File
@@ -1,23 +0,0 @@
/obj/item/changestone
name = "An uncut ruby"
desc = "The ruby shines and catches the light, despite being uncut"
icon = 'icons/obj/artifacts.dmi'
icon_state = "changerock"
/obj/item/changestone/attack_hand(mob/user as mob)
if(istype(user,/mob/living/carbon/human))
var/mob/living/carbon/human/H = user
if(!H.gloves)
if(H.gender == FEMALE)
H.change_gender(MALE)
else
H.change_gender(FEMALE)
H.dna.ready_dna(H)
H.update_body()
..()
@@ -50,6 +50,10 @@
/obj/item/radio/beacon/bacon/proc/digest_delay()
QDEL_IN(src, 600)
/obj/item/radio/beacon/emagged
syndicate = TRUE
emagged = TRUE
// SINGULO BEACON SPAWNER
/obj/item/radio/beacon/syndicate
name = "suspicious beacon"
@@ -71,6 +75,18 @@
user.drop_item()
qdel(src)
/obj/item/radio/beacon/syndicate/power_sink
name = "suspicious beacon"
desc = "A label on it reads: <i>Warning: Activating this device will send a power sink to your location</i>."
/obj/item/radio/beacon/syndicate/power_sink/attack_self(mob/user)
if(user)
to_chat(user, "<span class='notice'>Locked In</span>")
new /obj/item/powersink(user.loc)
playsound(src, 'sound/effects/pop.ogg', 100, TRUE, 1)
user.drop_item()
qdel(src)
/obj/item/radio/beacon/syndicate/bomb
name = "suspicious beacon"
desc = "A label on it reads: <i>Warning: Activating this device will send a high-ordinance explosive to your location</i>."
@@ -273,20 +273,20 @@ effective or pretty fucking useless.
/obj/item/teleporter/proc/dir_correction(mob/user) //Direction movement, screws with teleport distance and saving throw, and thus must be removed first
var/temp_direction = user.dir
switch(temp_direction)
if(NORTHEAST || SOUTHEAST)
if(NORTHEAST, SOUTHEAST)
user.dir = EAST
if(NORTHWEST || SOUTHWEST)
if(NORTHWEST, SOUTHWEST)
user.dir = WEST
/obj/item/teleporter/proc/panic_teleport(mob/user, turf/destination, direction = NORTH)
var/saving_throw
switch(direction)
if(NORTH || SOUTH)
if(NORTH, SOUTH)
if(prob(50))
saving_throw = EAST
else
saving_throw = WEST
if(EAST || WEST)
if(EAST, WEST)
if(prob(50))
saving_throw = NORTH
else
@@ -28,5 +28,5 @@
return TRUE
/obj/item/mounted/frame/apc_frame/do_build(turf/on_wall, mob/user)
new /obj/machinery/power/apc(get_turf(src), get_dir(user, on_wall), 1)
new /obj/machinery/power/apc(get_turf(src), get_dir(user, on_wall), TRUE)
qdel(src)
+1 -1
View File
@@ -226,7 +226,7 @@
to_chat(user, "<span class='warning'>Sticking an empty [M] into the frame would sort of defeat the purpose.</span>")
return
if(jobban_isbanned(M.brainmob, "Cyborg") || jobban_isbanned(M.brainmob,"nonhumandept"))
if(jobban_isbanned(M.brainmob, "Cyborg") || jobban_isbanned(M.brainmob, "nonhumandept"))
to_chat(user, "<span class='warning'>This [W] is not fit to serve as a cyborg!</span>")
return
@@ -71,7 +71,7 @@
if(replacement_type in special_rechargables)
R.module.special_rechargables += replacement
R.module.rebuild_modules()
R.module?.rebuild_modules()
return TRUE
/obj/item/borg/upgrade/reset
@@ -19,7 +19,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
new/datum/stack_recipe/window("fulltile window", /obj/structure/window/full/basic, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \
new/datum/stack_recipe("fishbowl", /obj/machinery/fishtank/bowl, 1, time = 10), \
new/datum/stack_recipe("fish tank", /obj/machinery/fishtank/tank, 3, time = 20, on_floor = TRUE), \
new/datum/stack_recipe("wall aquariam", /obj/machinery/fishtank/wall, 4, time = 40, on_floor = TRUE) \
new/datum/stack_recipe("wall aquarium", /obj/machinery/fishtank/wall, 4, time = 40, on_floor = TRUE) \
))
/obj/item/stack/sheet/glass
@@ -83,7 +83,6 @@ GLOBAL_LIST_INIT(bananium_recipes, list ( \
null, \
new/datum/stack_recipe("Clown Statue", /obj/structure/statue/bananium/clown, 5, one_per_turf = 1, on_floor = 1), \
null, \
new/datum/stack_recipe("bananium computer frame", /obj/structure/computerframe/HONKputer, 50, time = 25, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("bananium grenade casing", /obj/item/grenade/bananade/casing, 4, on_floor = 1), \
))
-1
View File
@@ -9,7 +9,6 @@
slot_flags = SLOT_BELT
force = 5
throwforce = 7
item_state = "crowbar"
w_class = WEIGHT_CLASS_SMALL
materials = list(MAT_METAL=50)
drop_sound = 'sound/items/handling/crowbar_drop.ogg'
@@ -83,6 +83,9 @@
if(chunk)
if(chunk.seenby.len)
for(var/mob/camera/aiEye/A in chunk.seenby)
//Checks if the A is to be detected or not
if(!A.ai_detector_visible)
continue
var/turf/detect_turf = get_turf(A)
if(get_dist(our_turf, detect_turf) < rangealert)
detect_state = PROXIMITY_ON_SCREEN
@@ -57,4 +57,8 @@
// Used in a callback that is passed by use_tool into do_after call. Do not override, do not call manually.
/obj/item/proc/tool_check_callback(mob/living/user, atom/target, amount, datum/callback/extra_checks)
return tool_use_check(user, amount) && (extra_checks && !extra_checks.Invoke())
if(!tool_use_check(user, amount))
return TRUE
if(extra_checks && !extra_checks.Invoke())
return TRUE
return FALSE
+9 -2
View File
@@ -16,7 +16,7 @@
w_class = WEIGHT_CLASS_SMALL
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
resistance_flags = FIRE_PROOF
materials = list(MAT_METAL=70, MAT_GLASS=30)
materials = list(MAT_METAL = 70, MAT_GLASS = 20)
origin_tech = "engineering=1;plasmatech=1"
tool_behaviour = TOOL_WELDER
toolspeed = 1
@@ -52,6 +52,13 @@
user.visible_message("<span class='suicide'>[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return FIRELOSS
/obj/item/weldingtool/can_enter_storage(obj/item/storage/S, mob/user)
if(tool_enabled)
to_chat(user, "<span class='warning'>[S] can't hold [src] while it's lit!</span>")
return FALSE
else
return TRUE
/obj/item/weldingtool/process()
if(tool_enabled)
var/turf/T = get_turf(src)
@@ -131,7 +138,7 @@
/obj/item/weldingtool/tool_check_callback(mob/living/user, amount, datum/callback/extra_checks)
. = ..()
if(. && user)
if(!. && user)
if(progress_flash_divisor == 0)
user.flash_eyes(min(light_intensity, 1))
progress_flash_divisor = initial(progress_flash_divisor)
+6
View File
@@ -61,6 +61,12 @@ LIGHTERS ARE IN LIGHTERS.DM
else
return ..()
/obj/item/clothing/mask/cigarette/can_enter_storage(obj/item/storage/S, mob/user)
if(lit)
to_chat(user, "<span class='warning'>[S] can't hold [initial(name)] while it's lit!</span>") // initial(name) so it doesn't say "lit" twice in a row
return FALSE
else
return TRUE
/obj/item/clothing/mask/cigarette/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
..()
@@ -64,11 +64,26 @@
M.update_inv_l_hand()
M.update_inv_r_hand()
/obj/item/flamethrower/can_enter_storage(obj/item/storage/S, mob/user)
if(lit)
to_chat(user, "<span class='warning'>[S] can't hold [src] while it's lit!</span>")
return FALSE
else
return TRUE
/obj/item/flamethrower/afterattack(atom/target, mob/user, flag)
. = ..()
if(flag)
return // too close
if(user && user.get_active_hand() == src) // Make sure our user is still holding us
if(!user)
return
if(user.mind?.martial_art?.no_guns)
to_chat(user, "<span class='warning'>[user.mind.martial_art.no_guns_message]</span>")
return
if(HAS_TRAIT(user, TRAIT_CHUNKYFINGERS))
to_chat(user, "<span class='warning'>Your meaty finger is far too large for the trigger guard!</span>")
return
if(user.get_active_hand() == src) // Make sure our user is still holding us
var/turf/target_turf = get_turf(target)
if(target_turf)
var/turflist = getline(user, target_turf)
@@ -44,11 +44,9 @@
update_mob()
playsound(loc, 'sound/effects/empulse.ogg', 50, 1)
radiation_pulse(src, rad_damage)
for(var/turf/T in view(freeze_range, loc))
if(isfloorturf(T))
var/turf/simulated/F = T
F.MakeSlippery(TURF_WET_PERMAFROST)
for(var/mob/living/carbon/L in T)
L.adjustStaminaLoss(stamina_damage)
L.adjust_bodytemperature(-230)
for(var/turf/simulated/floor/T in view(freeze_range, loc))
T.MakeSlippery(TURF_WET_ICE)
for(var/mob/living/carbon/L in T)
L.adjustStaminaLoss(stamina_damage)
L.adjust_bodytemperature(-230)
qdel(src)
@@ -29,6 +29,13 @@
else
turn_off_lighter(user)
/obj/item/lighter/can_enter_storage(obj/item/storage/S, mob/user)
if(lit)
to_chat(user, "<span class='warning'>[S] can't hold [src] while it's lit!</span>")
return FALSE
else
return TRUE
/obj/item/lighter/proc/turn_on_lighter(mob/living/user)
lit = TRUE
w_class = WEIGHT_CLASS_BULKY
@@ -227,6 +234,13 @@
matchburnout()
. = ..()
/obj/item/match/can_enter_storage(obj/item/storage/S, mob/user)
if(lit)
to_chat(user, "<span class='warning'>[S] can't hold [initial(name)] while it's lit!</span>") // initial(name) so it doesn't say "lit" twice in a row
return FALSE
else
return TRUE
/obj/item/match/attack(mob/living/carbon/M, mob/living/carbon/user)
if(!isliving(M))
return ..()
+1 -1
View File
@@ -28,7 +28,7 @@
if(reagents.has_reagent("water", 1) || reagents.has_reagent("cleaner", 1) || reagents.has_reagent("holywater", 1))
A.clean_blood()
for(var/obj/effect/O in A)
if(is_cleanable(O))
if(O.is_cleanable())
qdel(O)
reagents.reaction(A, REAGENT_TOUCH, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly.
reagents.remove_any(1) //reaction() doesn't use up the reagents
+2
View File
@@ -142,6 +142,8 @@
/obj/item/rpd/proc/delete_all_pipes(mob/user, turf/T) //Delete all pipes on a turf
var/eaten
for(var/obj/item/pipe/P in T)
if(P.pipe_type == PIPE_CIRCULATOR) //Skip TEG heat circulators, they aren't really pipes
continue
QDEL_NULL(P)
eaten = TRUE
for(var/obj/item/pipe_gsensor/G in T)
+1 -1
View File
@@ -52,7 +52,7 @@
/obj/item/soap/proc/clean_turf(turf/simulated/T)
T.clean_blood()
for(var/obj/effect/O in T)
if(is_cleanable(O))
if(O.is_cleanable())
qdel(O)
/obj/item/soap/attack(mob/target as mob, mob/user as mob)
@@ -104,7 +104,7 @@
/obj/item/stock_parts/matter_bin
name = "matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
desc = "A container used to hold compressed matter awaiting re-construction."
icon_state = "matter_bin"
origin_tech = "materials=1"
materials = list(MAT_METAL=80)
@@ -145,7 +145,7 @@
/obj/item/stock_parts/matter_bin/adv
name = "advanced matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
desc = "A container used to hold compressed matter awaiting re-construction."
icon_state = "advanced_matter_bin"
origin_tech = "materials=3"
rating = 2
@@ -187,7 +187,7 @@
/obj/item/stock_parts/matter_bin/super
name = "super matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
desc = "A container used to hold compressed matter awaiting re-construction."
icon_state = "super_matter_bin"
origin_tech = "materials=4;engineering=4"
rating = 3
@@ -229,7 +229,7 @@
/obj/item/stock_parts/matter_bin/bluespace
name = "bluespace matter bin"
desc = "A container for hold compressed matter awaiting re-construction."
desc = "A container used to hold compressed matter awaiting re-construction."
icon_state = "bluespace_matter_bin"
origin_tech = "materials=6;programming=4;engineering=4"
rating = 4
@@ -230,7 +230,9 @@
/obj/item/flashlight/seclite,
/obj/item/holosign_creator/security,
/obj/item/melee/classic_baton/telescopic,
/obj/item/restraints/legcuffs/bola)
/obj/item/restraints/legcuffs/bola,
/obj/item/clothing/mask/gas/sechailer,
/obj/item/spacepod_key)
/obj/item/storage/belt/security/sec/populate_contents()
new /obj/item/flashlight/seclite(src)
@@ -447,6 +449,7 @@
item_state = "bandolier"
storage_slots = 8
can_hold = list(/obj/item/ammo_casing/shotgun)
display_contents_with_number = TRUE
/obj/item/storage/belt/bandolier/Initialize(mapload)
. = ..()
@@ -163,7 +163,7 @@
/obj/item/storage/proc/show_to(mob/user)
if(!user.client)
return
if(user.s_active != src) // Switching from another container
if(user.s_active != src && !isobserver(user))
for(var/obj/item/I in src)
if(I.on_found(user)) // For mouse traps and such
return // If something triggered, don't open the UI
@@ -310,6 +310,9 @@
if(loc == I)
return FALSE //Means the item is already in the storage item
if(!I.can_enter_storage(src, usr))
return FALSE
if(length(contents) >= storage_slots)
if(!stop_messages)
to_chat(usr, "<span class='warning'>[I] won't fit in [src], make some space!</span>")
@@ -670,6 +670,8 @@
/obj/item/twohanded/singularityhammer/proc/vortex(turf/pull, mob/wielder)
for(var/atom/movable/X in orange(5, pull))
if(X.move_resist == INFINITY)
continue
if(X == wielder)
continue
if((X) && (!X.anchored) && (!ishuman(X)))
+1
View File
@@ -363,6 +363,7 @@ a {
/obj/proc/cult_reveal() //Called by cult reveal spell and chaplain's bible
return
/obj/proc/force_eject_occupant(mob/target)
// This proc handles safely removing occupant mobs from the object if they must be teleported out (due to being SSD/AFK, by admin teleport, etc) or transformed.
// In the event that the object doesn't have an overriden version of this proc to do it, log a runtime so one can be added.
@@ -69,6 +69,8 @@
togglelock(user)
/obj/structure/closet/secure_closet/AltClick(mob/user)
if(opened)
return ..()
if(Adjacent(user))
togglelock(user)
@@ -78,7 +80,7 @@
locked = FALSE
icon_state = icon_off
flick(icon_broken, src)
to_chat(user, "<span class='notice'>You break the lock on \the [src].</span>")
to_chat(user, "<span class='notice'>You break the lock on [src].</span>")
/obj/structure/closet/secure_closet/attack_hand(mob/user)
add_fingerprint(user)
@@ -23,7 +23,7 @@
/obj/structure/closet/syndicate/suits/populate_contents()
new /obj/item/clothing/mask/gas/syndicate(src)
new /obj/item/clothing/suit/space/hardsuit/syndi(src)
new /obj/item/tank/jetpack/oxygen/harness(src)
new /obj/item/tank/internals/oxygen/red(src)
/obj/structure/closet/syndicate/nuclear
desc = "It's a storage unit for a Syndicate boarding party."
@@ -37,6 +37,7 @@
new /obj/item/storage/box/teargas(src)
new /obj/item/storage/box/flashbangs(src)
new /obj/item/storage/backpack/duffel/syndie/med(src)
new /obj/item/tank/jetpack/oxygen/harness(src)
new /obj/item/gun/projectile/automatic/shotgun/bulldog(src)
new /obj/item/gun/projectile/automatic/shotgun/bulldog(src)
new /obj/item/gun/projectile/automatic/shotgun/bulldog(src)
@@ -50,7 +51,7 @@
/obj/structure/closet/syndicate/sst/populate_contents()
new /obj/item/ammo_box/magazine/mm556x45(src)
new /obj/item/gun/projectile/automatic/l6_saw(src)
new /obj/item/tank/jetpack/oxygen/harness(src)
new /obj/item/tank/internals/oxygen/red(src)
new /obj/item/storage/belt/military/sst(src)
new /obj/item/clothing/glasses/thermal(src)
new /obj/item/clothing/shoes/magboots/syndie/advance(src)
+1 -1
View File
@@ -404,7 +404,7 @@
tile.water_act(100, convertHeat(), src)
tile.clean_blood(radiation_clean = TRUE)
for(var/obj/effect/E in tile)
if(is_cleanable(E))
if(E.is_cleanable())
qdel(E)
for(var/A in loc)
wash(A)
+64
View File
@@ -247,6 +247,70 @@ GLOBAL_VAR_INIT(admin_ooc_colour, "#b82e00")
if(send)
to_chat(target, "<span class='ooc'><span class='looc'>LOOC<span class='prefix'>[prefix]: </span><EM>[display_name][admin_stuff]:</EM> <span class='message'>[msg]</span></span></span>")
// Ported from /tg/, full credit to SpaceManiac and Timberpoes.
/client/verb/fit_viewport()
set name = "Fit Viewport"
set desc = "Fit the size of the map window to match the viewport."
set category = "OOC"
// Fetch aspect ratio
var/list/view_size = getviewsize(view)
var/aspect_ratio = view_size[1] / view_size[2]
// Calculate desired pixel width using window size and aspect ratio
var/list/sizes = params2list(winget(src, "mainwindow.mainvsplit;mapwindow", "size"))
// Client closed the window? Some other error? This is unexpected behaviour, let's CRASH with some info.
if(!sizes["mapwindow.size"])
CRASH("sizes does not contain mapwindow.size key. This means a winget() failed to return what we wanted. --- sizes var: [sizes] --- sizes length: [length(sizes)]")
var/list/map_size = splittext(sizes["mapwindow.size"], "x")
// Looks like we didn't expect mapwindow.size to be "ixj" where i and j are numbers.
// If we don't get our expected 2 outputs, let's give some useful error info.
if(length(map_size) != 2)
CRASH("map_size of incorrect length --- map_size var: [map_size] --- map_size length: [length(map_size)]")
var/height = text2num(map_size[2])
var/desired_width = round(height * aspect_ratio)
if(text2num(map_size[1]) == desired_width)
// Nothing to do.
return
var/list/split_size = splittext(sizes["mainwindow.mainvsplit.size"], "x")
var/split_width = text2num(split_size[1])
// Avoid auto-resizing the statpanel and chat into nothing.
desired_width = min(desired_width, split_width - 300)
// Calculate and apply a best estimate
// +4 pixels are for the width of the splitter's handle
var/pct = 100 * (desired_width + 4) / split_width
winset(src, "mainwindow.mainvsplit", "splitter=[pct]")
// Apply an ever-lowering offset until we finish or fail
var/delta
for(var/safety in 1 to 10)
var/after_size = winget(src, "mapwindow", "size")
map_size = splittext(after_size, "x")
var/produced_width = text2num(map_size[1])
if(produced_width == desired_width)
// Success!
return
else if(isnull(delta))
// Calculate a probably delta based on the difference
delta = 100 * (desired_width - produced_width) / split_width
else if((delta > 0 && produced_width > desired_width) || (delta < 0 && produced_width < desired_width))
// If we overshot, halve the delta and reverse direction
delta = -delta / 2
pct += delta
winset(src, "mainwindow.mainvsplit", "splitter=[pct]")
/mob/proc/get_looc_source()
return src
+5
View File
@@ -250,6 +250,11 @@ GLOBAL_LIST_EMPTY(world_topic_handlers)
start_log(GLOB.sql_log)
start_log(GLOB.chat_debug_log)
#ifdef REFERENCE_TRACKING
GLOB.gc_log = "[GLOB.log_directory]/gc_debug.log"
start_log(GLOB.gc_log)
#endif
// This log follows a special format and this path should NOT be used for anything else
GLOB.runtime_summary_log = "data/logs/runtime_summary.log"
if(fexists(GLOB.runtime_summary_log))