initial commit - cross reference with 5th port - obviously has compile errors
This commit is contained in:
@@ -0,0 +1,348 @@
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/syndicates = list()
|
||||
var/nukeops_lastname = ""
|
||||
|
||||
/datum/game_mode/nuclear
|
||||
name = "nuclear emergency"
|
||||
config_tag = "nuclear"
|
||||
required_players = 30 // 30 players - 3 players to be the nuke ops = 27 players remaining
|
||||
required_enemies = 2
|
||||
recommended_enemies = 5
|
||||
antag_flag = ROLE_OPERATIVE
|
||||
enemy_minimum_age = 14
|
||||
var/const/agents_possible = 5 //If we ever need more syndicate agents.
|
||||
|
||||
var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer!
|
||||
var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station
|
||||
var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level
|
||||
|
||||
|
||||
/datum/game_mode/nuclear/announce()
|
||||
world << "<B>The current game mode is - Nuclear Emergency!</B>"
|
||||
world << "<B>A [syndicate_name()] Strike Force is approaching [station_name()]!</B>"
|
||||
world << "A nuclear explosive was being transported by Nanotrasen to a military base. The transport ship mysteriously lost contact with Space Traffic Control (STC). About that time a strange disk was discovered around [station_name()]. It was identified by Nanotrasen as a nuclear auth. disk and now Syndicate Operatives have arrived to retake the disk and detonate SS13! Also, most likely Syndicate star ships are in the vicinity so take care not to lose the disk!\n<B>Syndicate</B>: Reclaim the disk and detonate the nuclear bomb anywhere on SS13.\n<B>Personnel</B>: Hold the disk and <B>escape with the disk</B> on the shuttle!"
|
||||
|
||||
/datum/game_mode/nuclear/pre_setup()
|
||||
var/n_players = num_players()
|
||||
var/n_agents = min(round(n_players / 10, 1), agents_possible)
|
||||
|
||||
if(antag_candidates.len < n_agents) //In the case of having less candidates than the selected number of agents
|
||||
n_agents = antag_candidates.len
|
||||
|
||||
while(n_agents > 0)
|
||||
var/datum/mind/new_syndicate = pick(antag_candidates)
|
||||
syndicates += new_syndicate
|
||||
antag_candidates -= new_syndicate //So it doesn't pick the same guy each time.
|
||||
n_agents--
|
||||
|
||||
for(var/datum/mind/synd_mind in syndicates)
|
||||
synd_mind.assigned_role = "Syndicate"
|
||||
synd_mind.special_role = "Syndicate"//So they actually have a special role/N
|
||||
log_game("[synd_mind.key] (ckey) has been selected as a nuclear operative")
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/datum/game_mode/proc/update_synd_icons_added(datum/mind/synd_mind)
|
||||
var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS]
|
||||
opshud.join_hud(synd_mind.current)
|
||||
set_antag_hud(synd_mind.current, "synd")
|
||||
|
||||
/datum/game_mode/proc/update_synd_icons_removed(datum/mind/synd_mind)
|
||||
var/datum/atom_hud/antag/opshud = huds[ANTAG_HUD_OPS]
|
||||
opshud.leave_hud(synd_mind.current)
|
||||
set_antag_hud(synd_mind.current, null)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/datum/game_mode/nuclear/post_setup()
|
||||
|
||||
var/list/turf/synd_spawn = list()
|
||||
|
||||
for(var/obj/effect/landmark/A in landmarks_list)
|
||||
if(A.name == "Syndicate-Spawn")
|
||||
synd_spawn += get_turf(A)
|
||||
continue
|
||||
|
||||
var/nuke_code = "[rand(10000, 99999)]"
|
||||
var/leader_selected = 0
|
||||
var/agent_number = 1
|
||||
var/spawnpos = 1
|
||||
|
||||
for(var/datum/mind/synd_mind in syndicates)
|
||||
if(spawnpos > synd_spawn.len)
|
||||
spawnpos = 2
|
||||
synd_mind.current.loc = synd_spawn[spawnpos]
|
||||
|
||||
forge_syndicate_objectives(synd_mind)
|
||||
greet_syndicate(synd_mind)
|
||||
equip_syndicate(synd_mind.current)
|
||||
|
||||
if(nuke_code)
|
||||
synd_mind.store_memory("<B>Syndicate Nuclear Bomb Code</B>: [nuke_code]", 0, 0)
|
||||
synd_mind.current << "The nuclear authorization code is: <B>[nuke_code]</B>"
|
||||
|
||||
if(!leader_selected)
|
||||
prepare_syndicate_leader(synd_mind, nuke_code)
|
||||
leader_selected = 1
|
||||
else
|
||||
synd_mind.current.real_name = "[syndicate_name()] Operative #[agent_number]"
|
||||
agent_number++
|
||||
spawnpos++
|
||||
update_synd_icons_added(synd_mind)
|
||||
var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in nuke_list
|
||||
if(nuke)
|
||||
nuke.r_code = nuke_code
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, nuke_code)
|
||||
var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")
|
||||
spawn(1)
|
||||
nukeops_lastname = nukelastname(synd_mind.current)
|
||||
NukeNameAssign(nukeops_lastname,syndicates) //allows time for the rest of the syndies to be chosen
|
||||
synd_mind.current.real_name = "[syndicate_name()] [leader_title]"
|
||||
synd_mind.current << "<B>You are the Syndicate [leader_title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.</B>"
|
||||
synd_mind.current << "<B>If you feel you are not up to this task, give your ID to another operative.</B>"
|
||||
synd_mind.current << "<B>In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it.</B>"
|
||||
|
||||
var/obj/item/device/nuclear_challenge/challenge = new /obj/item/device/nuclear_challenge
|
||||
synd_mind.current.equip_to_slot_or_del(challenge, slot_r_hand)
|
||||
|
||||
var/list/foundIDs = synd_mind.current.search_contents_for(/obj/item/weapon/card/id)
|
||||
if(foundIDs.len)
|
||||
for(var/obj/item/weapon/card/id/ID in foundIDs)
|
||||
ID.name = "lead agent card"
|
||||
ID.access += access_syndicate_leader
|
||||
else
|
||||
message_admins("Warning: Nuke Ops spawned without access to leave their spawn area!")
|
||||
|
||||
var/obj/item/device/radio/headset/syndicate/alt/A = locate() in synd_mind.current
|
||||
if(A)
|
||||
A.command = TRUE
|
||||
|
||||
if(nuke_code)
|
||||
var/obj/item/weapon/paper/P = new
|
||||
P.info = "The nuclear authorization code is: <b>[nuke_code]</b>"
|
||||
P.name = "nuclear bomb code"
|
||||
var/mob/living/carbon/human/H = synd_mind.current
|
||||
P.loc = H.loc
|
||||
H.equip_to_slot_or_del(P, slot_r_hand, 0)
|
||||
H.update_icons()
|
||||
else
|
||||
nuke_code = "code will be provided later"
|
||||
return
|
||||
|
||||
|
||||
|
||||
/datum/game_mode/proc/forge_syndicate_objectives(datum/mind/syndicate)
|
||||
var/datum/objective/nuclear/syndobj = new
|
||||
syndobj.owner = syndicate
|
||||
syndicate.objectives += syndobj
|
||||
|
||||
|
||||
/datum/game_mode/proc/greet_syndicate(datum/mind/syndicate, you_are=1)
|
||||
if(you_are)
|
||||
syndicate.current << "<span class='notice'>You are a [syndicate_name()] agent!</span>"
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/objective in syndicate.objectives)
|
||||
syndicate.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
return
|
||||
|
||||
/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob, telecrystals = TRUE)
|
||||
synd_mob.set_species(/datum/species/human) //Plasamen burn up otherwise, and lizards are vulnerable to asimov AIs
|
||||
|
||||
if(telecrystals)
|
||||
synd_mob.equipOutfit(/datum/outfit/syndicate)
|
||||
else
|
||||
synd_mob.equipOutfit(/datum/outfit/syndicate/no_crystals)
|
||||
return 1
|
||||
|
||||
|
||||
/datum/game_mode/nuclear/check_win()
|
||||
if (nukes_left == 0)
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/proc/are_operatives_dead()
|
||||
for(var/datum/mind/operative_mind in syndicates)
|
||||
if (istype(operative_mind.current,/mob/living/carbon/human) && (operative_mind.current.stat!=2))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/game_mode/nuclear/check_finished() //to be called by ticker
|
||||
if(replacementmode && round_converted == 2)
|
||||
return replacementmode.check_finished()
|
||||
if((SSshuttle.emergency.mode == SHUTTLE_ENDGAME) || station_was_nuked)
|
||||
return 1
|
||||
if(are_operatives_dead())
|
||||
if(bomb_set) //snaaaaaaaaaake! It's not over yet!
|
||||
return 0
|
||||
..()
|
||||
|
||||
/datum/game_mode/nuclear/declare_completion()
|
||||
var/disk_rescued = 1
|
||||
for(var/obj/item/weapon/disk/nuclear/D in poi_list)
|
||||
if(!D.onCentcom())
|
||||
disk_rescued = 0
|
||||
break
|
||||
var/crew_evacuated = (SSshuttle.emergency.mode == SHUTTLE_ENDGAME)
|
||||
//var/operatives_are_dead = is_operatives_are_dead()
|
||||
|
||||
|
||||
//nukes_left
|
||||
//station_was_nuked
|
||||
//derp //Used for tracking if the syndies actually haul the nuke to the station //no
|
||||
//herp //Used for tracking if the syndies got the shuttle off of the z-level //NO, DON'T FUCKING NAME VARS LIKE THIS
|
||||
|
||||
if (!disk_rescued && station_was_nuked && !syndies_didnt_escape)
|
||||
feedback_set_details("round_end_result","win - syndicate nuke")
|
||||
world << "<FONT size = 3><B>Syndicate Major Victory!</B></FONT>"
|
||||
world << "<B>[syndicate_name()] operatives have destroyed [station_name()]!</B>"
|
||||
|
||||
else if (!disk_rescued && station_was_nuked && syndies_didnt_escape)
|
||||
feedback_set_details("round_end_result","halfwin - syndicate nuke - did not evacuate in time")
|
||||
world << "<FONT size = 3><B>Total Annihilation</B></FONT>"
|
||||
world << "<B>[syndicate_name()] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion.</B> Next time, don't lose the disk!"
|
||||
|
||||
else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape)
|
||||
feedback_set_details("round_end_result","halfwin - blew wrong station")
|
||||
world << "<FONT size = 3><B>Crew Minor Victory</B></FONT>"
|
||||
world << "<B>[syndicate_name()] operatives secured the authentication disk but blew up something that wasn't [station_name()].</B> Next time, don't lose the disk!"
|
||||
|
||||
else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape)
|
||||
feedback_set_details("round_end_result","halfwin - blew wrong station - did not evacuate in time")
|
||||
world << "<FONT size = 3><B>[syndicate_name()] operatives have earned Darwin Award!</B></FONT>"
|
||||
world << "<B>[syndicate_name()] operatives blew up something that wasn't [station_name()] and got caught in the explosion.</B> Next time, don't lose the disk!"
|
||||
|
||||
else if ((disk_rescued || SSshuttle.emergency.mode != SHUTTLE_ENDGAME) && are_operatives_dead())
|
||||
feedback_set_details("round_end_result","loss - evacuation - disk secured - syndi team dead")
|
||||
world << "<FONT size = 3><B>Crew Major Victory!</B></FONT>"
|
||||
world << "<B>The Research Staff has saved the disc and killed the [syndicate_name()] Operatives</B>"
|
||||
|
||||
else if (disk_rescued)
|
||||
feedback_set_details("round_end_result","loss - evacuation - disk secured")
|
||||
world << "<FONT size = 3><B>Crew Major Victory</B></FONT>"
|
||||
world << "<B>The Research Staff has saved the disc and stopped the [syndicate_name()] Operatives!</B>"
|
||||
|
||||
else if (!disk_rescued && are_operatives_dead())
|
||||
feedback_set_details("round_end_result","halfwin - evacuation - disk not secured")
|
||||
world << "<FONT size = 3><B>Neutral Victory!</B></FONT>"
|
||||
world << "<B>The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name()] Operatives!</B>"
|
||||
|
||||
else if (!disk_rescued && crew_evacuated)
|
||||
feedback_set_details("round_end_result","halfwin - detonation averted")
|
||||
world << "<FONT size = 3><B>Syndicate Minor Victory!</B></FONT>"
|
||||
world << "<B>[syndicate_name()] operatives recovered the abandoned authentication disk but detonation of [station_name()] was averted.</B> Next time, don't lose the disk!"
|
||||
|
||||
else if (!disk_rescued && !crew_evacuated)
|
||||
feedback_set_details("round_end_result","halfwin - interrupted")
|
||||
world << "<FONT size = 3><B>Neutral Victory</B></FONT>"
|
||||
world << "<B>Round was mysteriously interrupted!</B>"
|
||||
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/datum/game_mode/proc/auto_declare_completion_nuclear()
|
||||
if( syndicates.len || (ticker && istype(ticker.mode,/datum/game_mode/nuclear)) )
|
||||
var/text = "<br><FONT size=3><B>The syndicate operatives were:</B></FONT>"
|
||||
var/purchases = ""
|
||||
var/TC_uses = 0
|
||||
for(var/datum/mind/syndicate in syndicates)
|
||||
text += printplayer(syndicate)
|
||||
for(var/obj/item/device/uplink/H in uplinks)
|
||||
if(H && H.owner && H.owner == syndicate.key)
|
||||
TC_uses += H.spent_telecrystals
|
||||
purchases += H.purchase_log
|
||||
text += "<br>"
|
||||
text += "(Syndicates used [TC_uses] TC) [purchases]"
|
||||
if(TC_uses == 0 && station_was_nuked && !are_operatives_dead())
|
||||
text += "<BIG><IMG CLASS=icon SRC=\ref['icons/BadAss.dmi'] ICONSTATE='badass'></BIG>"
|
||||
world << text
|
||||
return 1
|
||||
|
||||
|
||||
/proc/nukelastname(mob/M) //--All praise goes to NEO|Phyte, all blame goes to DH, and it was Cindi-Kate's idea. Also praise Urist for copypasta ho.
|
||||
var/randomname = pick(last_names)
|
||||
var/newname = copytext(sanitize(input(M,"You are the nuke operative [pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")]. Please choose a last name for your family.", "Name change",randomname)),1,MAX_NAME_LEN)
|
||||
|
||||
if (!newname)
|
||||
newname = randomname
|
||||
|
||||
else
|
||||
if (newname == "Unknown" || newname == "floor" || newname == "wall" || newname == "rwall" || newname == "_")
|
||||
M << "That name is reserved."
|
||||
return nukelastname(M)
|
||||
|
||||
return capitalize(newname)
|
||||
|
||||
/proc/NukeNameAssign(lastname,list/syndicates)
|
||||
for(var/datum/mind/synd_mind in syndicates)
|
||||
var/mob/living/carbon/human/H = synd_mind.current
|
||||
synd_mind.name = H.dna.species.random_name(H.gender,0,lastname)
|
||||
synd_mind.current.real_name = synd_mind.name
|
||||
return
|
||||
|
||||
/datum/outfit/syndicate
|
||||
name = "Syndicate Operative - Basic"
|
||||
|
||||
uniform = /obj/item/clothing/under/syndicate
|
||||
shoes = /obj/item/clothing/shoes/combat
|
||||
gloves = /obj/item/clothing/gloves/combat
|
||||
back = /obj/item/weapon/storage/backpack
|
||||
ears = /obj/item/device/radio/headset/syndicate/alt
|
||||
l_pocket = /obj/item/weapon/pinpointer/nukeop
|
||||
id = /obj/item/weapon/card/id/syndicate
|
||||
belt = /obj/item/weapon/gun/projectile/automatic/pistol
|
||||
backpack_contents = list(/obj/item/weapon/storage/box/syndie=1)
|
||||
|
||||
var/tc = 25
|
||||
|
||||
/datum/outfit/syndicate/no_crystals
|
||||
tc = 0
|
||||
|
||||
|
||||
/datum/outfit/syndicate/post_equip(mob/living/carbon/human/H)
|
||||
var/obj/item/device/radio/R = H.ears
|
||||
R.set_frequency(SYND_FREQ)
|
||||
R.freqlock = 1
|
||||
|
||||
if(tc)
|
||||
var/obj/item/device/radio/uplink/nuclear/U = new(H)
|
||||
U.hidden_uplink.owner = "[H.key]"
|
||||
U.hidden_uplink.telecrystals = tc
|
||||
H.equip_to_slot_or_del(U, slot_in_backpack)
|
||||
|
||||
var/obj/item/weapon/implant/weapons_auth/W = new/obj/item/weapon/implant/weapons_auth(H)
|
||||
W.implant(H)
|
||||
var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(H)
|
||||
E.implant(H)
|
||||
H.faction |= "syndicate"
|
||||
H.update_icons()
|
||||
|
||||
/datum/outfit/syndicate/full
|
||||
name = "Syndicate Operative - Full Kit"
|
||||
|
||||
glasses = /obj/item/clothing/glasses/night
|
||||
mask = /obj/item/clothing/mask/gas/syndicate
|
||||
suit = /obj/item/clothing/suit/space/hardsuit/syndi
|
||||
r_pocket = /obj/item/weapon/tank/internals/emergency_oxygen/engi
|
||||
belt = /obj/item/weapon/storage/belt/military
|
||||
r_hand = /obj/item/weapon/gun/projectile/automatic/shotgun/bulldog
|
||||
backpack_contents = list(/obj/item/weapon/storage/box/syndie=1,\
|
||||
/obj/item/weapon/tank/jetpack/oxygen/harness=1,\
|
||||
/obj/item/weapon/gun/projectile/automatic/pistol=1)
|
||||
|
||||
/datum/outfit/syndicate/full/post_equip(mob/living/carbon/human/H)
|
||||
..()
|
||||
|
||||
|
||||
var/obj/item/clothing/suit/space/hardsuit/syndi/suit = H.wear_suit
|
||||
suit.ToggleHelmet()
|
||||
|
||||
H.internal = H.r_store
|
||||
@@ -0,0 +1,65 @@
|
||||
#define CHALLENGE_TELECRYSTALS 280
|
||||
#define CHALLENGE_TIME_LIMIT 3000
|
||||
#define CHALLENGE_MIN_PLAYERS 50
|
||||
#define CHALLENGE_SHUTTLE_DELAY 15000 // 25 minutes, so the ops have at least 5 minutes before the shuttle is callable.
|
||||
|
||||
/obj/item/device/nuclear_challenge
|
||||
name = "Declaration of War (Challenge Mode)"
|
||||
icon_state = "gangtool-red"
|
||||
item_state = "walkietalkie"
|
||||
desc = "Use to send a declaration of hostilities to the target, delaying your shuttle departure for 20 minutes while they prepare for your assault. \
|
||||
Such a brazen move will attract the attention of powerful benefactors within the Syndicate, who will supply your team with a massive amount of bonus telecrystals. \
|
||||
Must be used within five minutes, or your benefactors will lose interest."
|
||||
var/declaring_war = 0
|
||||
|
||||
/obj/item/device/nuclear_challenge/attack_self(mob/living/user)
|
||||
if(!check_allowed(user))
|
||||
return
|
||||
|
||||
declaring_war = 1
|
||||
var/are_you_sure = alert(user, "Consult your team carefully before you declare war on [station_name()]]. Are you sure you want to alert the enemy crew?", "Declare war?", "Yes", "No")
|
||||
declaring_war = 0
|
||||
if(are_you_sure == "No")
|
||||
user << "On second thought, the element of surprise isn't so bad after all."
|
||||
return
|
||||
if(!check_allowed(user))
|
||||
return
|
||||
|
||||
declaring_war = 1
|
||||
var/war_declaration = "[user.real_name] has declared his intent to utterly destroy [station_name()] with a nuclear device, and dares the crew to try and stop them."
|
||||
priority_announce(war_declaration, title = "Declaration of War", sound = 'sound/machines/Alarm.ogg')
|
||||
user << "You've attracted the attention of powerful forces within the syndicate. A bonus bundle of telecrystals has been granted to your team. Great things await you if you complete the mission."
|
||||
|
||||
for(var/V in syndicate_shuttle_boards)
|
||||
var/obj/item/weapon/circuitboard/computer/syndicate_shuttle/board = V
|
||||
board.challenge = TRUE
|
||||
|
||||
var/obj/item/device/radio/uplink/nuclear/U = new(get_turf(user))
|
||||
U.hidden_uplink.owner = "[user.key]"
|
||||
U.hidden_uplink.telecrystals = CHALLENGE_TELECRYSTALS
|
||||
U.hidden_uplink.gamemode = /datum/game_mode/nuclear
|
||||
config.shuttle_refuel_delay = max(config.shuttle_refuel_delay, CHALLENGE_SHUTTLE_DELAY)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/device/nuclear_challenge/proc/check_allowed(mob/living/user)
|
||||
if(declaring_war)
|
||||
return 0
|
||||
if(player_list.len < CHALLENGE_MIN_PLAYERS)
|
||||
user << "The enemy crew is too small to be worth declaring war on."
|
||||
return 0
|
||||
if(user.z != ZLEVEL_CENTCOM)
|
||||
user << "You have to be at your base to use this."
|
||||
return 0
|
||||
if(world.time-round_start_time > CHALLENGE_TIME_LIMIT)
|
||||
user << "It's too late to declare hostilities. Your benefactors are already busy with other schemes. You'll have to make do with what you have on hand."
|
||||
return 0
|
||||
for(var/V in syndicate_shuttle_boards)
|
||||
var/obj/item/weapon/circuitboard/computer/syndicate_shuttle/board = V
|
||||
if(board.moved)
|
||||
user << "The shuttle has already been moved! You have forfeit the right to declare war."
|
||||
return 0
|
||||
return 1
|
||||
|
||||
#undef CHALLENGE_TELECRYSTALS
|
||||
#undef CHALLENGE_MIN_PLAYERS
|
||||
#undef CHALLENGE_SHUTTLE_DELAY
|
||||
@@ -0,0 +1,495 @@
|
||||
#define NUKESTATE_INTACT 5
|
||||
#define NUKESTATE_UNSCREWED 4
|
||||
#define NUKESTATE_PANEL_REMOVED 3
|
||||
#define NUKESTATE_WELDED 2
|
||||
#define NUKESTATE_CORE_EXPOSED 1
|
||||
#define NUKESTATE_CORE_REMOVED 0
|
||||
|
||||
#define NUKE_OFF_LOCKED 0
|
||||
#define NUKE_OFF_UNLOCKED 1
|
||||
#define NUKE_ON_TIMING 2
|
||||
#define NUKE_ON_EXPLODING 3
|
||||
|
||||
var/bomb_set
|
||||
|
||||
/obj/machinery/nuclearbomb
|
||||
name = "nuclear fission explosive"
|
||||
desc = "You probably shouldn't stick around to see if this is armed."
|
||||
icon = 'icons/obj/machines/nuke.dmi'
|
||||
icon_state = "nuclearbomb_base"
|
||||
density = 1
|
||||
|
||||
var/timeleft = 60
|
||||
var/timing = 0
|
||||
var/r_code = "ADMIN"
|
||||
var/code = ""
|
||||
var/yes_code = 0
|
||||
var/safety = 1
|
||||
var/obj/item/weapon/disk/nuclear/auth = null
|
||||
use_power = 0
|
||||
var/previous_level = ""
|
||||
var/lastentered = ""
|
||||
var/obj/item/nuke_core/core = null
|
||||
var/deconstruction_state = NUKESTATE_INTACT
|
||||
var/image/lights = null
|
||||
var/image/interior = null
|
||||
var/obj/effect/countdown/nuclearbomb/countdown
|
||||
|
||||
/obj/machinery/nuclearbomb/New()
|
||||
..()
|
||||
countdown = new(src)
|
||||
nuke_list += src
|
||||
core = new /obj/item/nuke_core(src)
|
||||
STOP_PROCESSING(SSobj, core)
|
||||
update_icon()
|
||||
poi_list |= src
|
||||
previous_level = get_security_level()
|
||||
|
||||
/obj/machinery/nuclearbomb/Destroy()
|
||||
poi_list -= src
|
||||
nuke_list -= src
|
||||
qdel(countdown)
|
||||
countdown = null
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/nuclearbomb/selfdestruct
|
||||
name = "station self-destruct terminal"
|
||||
desc = "For when it all gets too much to bear. Do not taunt."
|
||||
icon = 'icons/obj/machines/nuke_terminal.dmi'
|
||||
icon_state = "nuclearbomb_base"
|
||||
anchored = 1 //stops it being moved
|
||||
layer = MOB_LAYER
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate/New()
|
||||
var/obj/machinery/nuclearbomb/existing = locate("syndienuke")
|
||||
if(existing)
|
||||
qdel(src)
|
||||
throw EXCEPTION("Attempted to spawn a syndicate nuke while one already exists at [existing.loc.x],[existing.loc.y],[existing.loc.z]")
|
||||
return 0
|
||||
tag = "syndienuke"
|
||||
return ..()
|
||||
|
||||
/obj/machinery/nuclearbomb/attackby(obj/item/I, mob/user, params)
|
||||
if (istype(I, /obj/item/weapon/disk/nuclear))
|
||||
if(!user.drop_item())
|
||||
return
|
||||
I.loc = src
|
||||
auth = I
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
switch(deconstruction_state)
|
||||
if(NUKESTATE_INTACT)
|
||||
if(istype(I, /obj/item/weapon/screwdriver/nuke))
|
||||
playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1)
|
||||
user << "<span class='notice'>You start removing [src]'s front panel's screws...</span>"
|
||||
if(do_after(user, 60/I.toolspeed,target=src))
|
||||
deconstruction_state = NUKESTATE_UNSCREWED
|
||||
user << "<span class='notice'>You remove the screws from [src]'s front panel.</span>"
|
||||
update_icon()
|
||||
return
|
||||
if(NUKESTATE_UNSCREWED)
|
||||
if(istype(I, /obj/item/weapon/crowbar))
|
||||
user << "<span class='notice'>You start removing [src]'s front panel...</span>"
|
||||
playsound(loc, 'sound/items/Crowbar.ogg', 100, 1)
|
||||
if(do_after(user,30/I.toolspeed,target=src))
|
||||
user << "<span class='notice'>You remove [src]'s front panel.</span>"
|
||||
deconstruction_state = NUKESTATE_PANEL_REMOVED
|
||||
update_icon()
|
||||
return
|
||||
if(NUKESTATE_PANEL_REMOVED)
|
||||
if(istype(I, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/welder = I
|
||||
playsound(loc, 'sound/items/Welder.ogg', 100, 1)
|
||||
user << "<span class='notice'>You start cutting [src]'s inner plate...</span>"
|
||||
if(welder.remove_fuel(1,user))
|
||||
if(do_after(user,80/I.toolspeed,target=src))
|
||||
user << "<span class='notice'>You cut [src]'s inner plate.</span>"
|
||||
deconstruction_state = NUKESTATE_WELDED
|
||||
update_icon()
|
||||
return
|
||||
if(NUKESTATE_WELDED)
|
||||
if(istype(I, /obj/item/weapon/crowbar))
|
||||
user << "<span class='notice'>You start prying off [src]'s inner plate...</span>"
|
||||
playsound(loc, 'sound/items/Crowbar.ogg', 100, 1)
|
||||
if(do_after(user,50/I.toolspeed,target=src))
|
||||
user << "<span class='notice'>You pry off [src]'s inner plate. You can see the core's green glow!</span>"
|
||||
deconstruction_state = NUKESTATE_CORE_EXPOSED
|
||||
update_icon()
|
||||
START_PROCESSING(SSobj, core)
|
||||
return
|
||||
if(NUKESTATE_CORE_EXPOSED)
|
||||
if(istype(I, /obj/item/nuke_core_container))
|
||||
var/obj/item/nuke_core_container/core_box = I
|
||||
user << "<span class='notice'>You start loading the plutonium core into [core_box]...</span>"
|
||||
if(do_after(user,50,target=src))
|
||||
if(core_box.load(core, user))
|
||||
user << "<span class='notice'>You load the plutonium core into [core_box].</span>"
|
||||
deconstruction_state = NUKESTATE_CORE_REMOVED
|
||||
update_icon()
|
||||
core = null
|
||||
else
|
||||
user << "<span class='warning'>You fail to load the plutonium core into [core_box]. [core_box] has already been used!</span>"
|
||||
return
|
||||
if(istype(I, /obj/item/stack/sheet/metal))
|
||||
var/obj/item/stack/sheet/metal/M = I
|
||||
if(M.amount >= 20)
|
||||
user << "<span class='notice'>You begin repairing [src]'s inner metal plate...</span>"
|
||||
if(do_after(user, 100, target=src))
|
||||
if(M.use(20))
|
||||
user << "<span class='notice'>You repair [src]'s inner metal plate. The radiation is contained.</span>"
|
||||
deconstruction_state = NUKESTATE_PANEL_REMOVED
|
||||
STOP_PROCESSING(SSobj, core)
|
||||
update_icon()
|
||||
else
|
||||
user << "<span class='warning'>You need more metal to do that!</span>"
|
||||
else
|
||||
user << "<span class='warning'>You need more metal to do that!</span>"
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/get_nuke_state()
|
||||
if(timing < 0)
|
||||
return NUKE_ON_EXPLODING
|
||||
if(timing > 0)
|
||||
return NUKE_ON_TIMING
|
||||
if(safety)
|
||||
return NUKE_OFF_LOCKED
|
||||
else
|
||||
return NUKE_OFF_UNLOCKED
|
||||
|
||||
/obj/machinery/nuclearbomb/update_icon()
|
||||
if(deconstruction_state == NUKESTATE_INTACT)
|
||||
switch(get_nuke_state())
|
||||
if(NUKE_OFF_LOCKED, NUKE_OFF_UNLOCKED)
|
||||
icon_state = "nuclearbomb_base"
|
||||
update_icon_interior()
|
||||
update_icon_lights()
|
||||
if(NUKE_ON_TIMING)
|
||||
cut_overlays()
|
||||
icon_state = "nuclearbomb_timing"
|
||||
if(NUKE_ON_EXPLODING)
|
||||
cut_overlays()
|
||||
icon_state = "nuclearbomb_exploding"
|
||||
else
|
||||
icon_state = "nuclearbomb_base"
|
||||
update_icon_interior()
|
||||
update_icon_lights()
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/update_icon_interior()
|
||||
overlays -= interior
|
||||
switch(deconstruction_state)
|
||||
if(NUKESTATE_UNSCREWED)
|
||||
interior = image(icon,"panel-unscrewed")
|
||||
if(NUKESTATE_PANEL_REMOVED)
|
||||
interior = image(icon,"panel-removed")
|
||||
if(NUKESTATE_WELDED)
|
||||
interior = image(icon,"plate-welded")
|
||||
if(NUKESTATE_CORE_EXPOSED)
|
||||
interior = image(icon,"plate-removed")
|
||||
if(NUKESTATE_CORE_REMOVED)
|
||||
interior = image(icon,"core-removed")
|
||||
if(NUKESTATE_INTACT)
|
||||
interior = null
|
||||
add_overlay(interior)
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/update_icon_lights()
|
||||
overlays -= lights
|
||||
switch(get_nuke_state())
|
||||
if(NUKE_OFF_LOCKED)
|
||||
lights = null
|
||||
if(NUKE_OFF_UNLOCKED)
|
||||
lights = image(icon,"lights-safety")
|
||||
if(NUKE_ON_TIMING)
|
||||
lights = image(icon,"lights-timing")
|
||||
if(NUKE_ON_EXPLODING)
|
||||
lights = image(icon,"lights-exploding")
|
||||
add_overlay(lights)
|
||||
|
||||
/obj/machinery/nuclearbomb/process()
|
||||
if (timing > 0)
|
||||
countdown.start()
|
||||
bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed.
|
||||
timeleft--
|
||||
if (timeleft <= 0)
|
||||
explode()
|
||||
else
|
||||
var/volume = (timeleft <= 20 ? 30 : 5)
|
||||
playsound(loc, 'sound/items/timer.ogg', volume, 0)
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
attack_hand(M)
|
||||
else
|
||||
countdown.stop()
|
||||
|
||||
/obj/machinery/nuclearbomb/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/nuclearbomb/attack_ai(mob/user)
|
||||
return
|
||||
|
||||
/obj/machinery/nuclearbomb/attack_hand(mob/user)
|
||||
user.set_machine(src)
|
||||
var/dat = text("<TT>\nAuth. Disk: <A href='?src=\ref[];auth=1'>[]</A><HR>", src, (auth ? "++++++++++" : "----------"))
|
||||
if (auth)
|
||||
if (yes_code)
|
||||
dat += text("\n<B>Status</B>: []-[]<BR>\n<B>Timer</B>: []<BR>\n<BR>\nTimer: [] <A href='?src=\ref[];timer=1'>Toggle</A><BR>\nTime: <A href='?src=\ref[];time=-10'>-</A> <A href='?src=\ref[];time=-1'>-</A> [] <A href='?src=\ref[];time=1'>+</A> <A href='?src=\ref[];time=10'>+</A><BR>\n<BR>\nSafety: [] <A href='?src=\ref[];safety=1'>Toggle</A><BR>\nAnchor: [] <A href='?src=\ref[];anchor=1'>Toggle</A><BR>\n", (timing ? "Func/Set" : "Functional"), (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), src, src, src, timeleft, src, src, (safety ? "On" : "Off"), src, (anchored ? "Engaged" : "Off"), src)
|
||||
else
|
||||
dat += text("\n<B>Status</B>: Auth. S2-[]<BR>\n<B>Timer</B>: []<BR>\n<BR>\nTimer: [] Toggle<BR>\nTime: - - [] + +<BR>\n<BR>\n[] Safety: Toggle<BR>\nAnchor: [] Toggle<BR>\n", (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), timeleft, (safety ? "On" : "Off"), (anchored ? "Engaged" : "Off"))
|
||||
else
|
||||
if (timing)
|
||||
dat += text("\n<B>Status</B>: Set-[]<BR>\n<B>Timer</B>: []<BR>\n<BR>\nTimer: [] Toggle<BR>\nTime: - - [] + +<BR>\n<BR>\nSafety: [] Toggle<BR>\nAnchor: [] Toggle<BR>\n", (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), timeleft, (safety ? "On" : "Off"), (anchored ? "Engaged" : "Off"))
|
||||
else
|
||||
dat += text("\n<B>Status</B>: Auth. S1-[]<BR>\n<B>Timer</B>: []<BR>\n<BR>\nTimer: [] Toggle<BR>\nTime: - - [] + +<BR>\n<BR>\nSafety: [] Toggle<BR>\nAnchor: [] Toggle<BR>\n", (safety ? "Safe" : "Engaged"), timeleft, (timing ? "On" : "Off"), timeleft, (safety ? "On" : "Off"), (anchored ? "Engaged" : "Off"))
|
||||
var/message = "AUTH"
|
||||
if (auth)
|
||||
message = text("[]", code)
|
||||
if (yes_code)
|
||||
message = "*****"
|
||||
dat += text("<HR>\n>[]<BR>\n<A href='?src=\ref[];type=1'>1</A><A href='?src=\ref[];type=2'>2</A><A href='?src=\ref[];type=3'>3</A><BR>\n<A href='?src=\ref[];type=4'>4</A><A href='?src=\ref[];type=5'>5</A><A href='?src=\ref[];type=6'>6</A><BR>\n<A href='?src=\ref[];type=7'>7</A><A href='?src=\ref[];type=8'>8</A><A href='?src=\ref[];type=9'>9</A><BR>\n<A href='?src=\ref[];type=R'>R</A><A href='?src=\ref[];type=0'>0</A><A href='?src=\ref[];type=E'>E</A><BR>\n</TT>", message, src, src, src, src, src, src, src, src, src, src, src, src)
|
||||
var/datum/browser/popup = new(user, "nuclearbomb", name, 300, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/machinery/nuclearbomb/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
if (href_list["auth"])
|
||||
if (auth)
|
||||
auth.loc = loc
|
||||
yes_code = 0
|
||||
auth = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/weapon/disk/nuclear))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
auth = I
|
||||
if (auth)
|
||||
if (href_list["type"])
|
||||
if (href_list["type"] == "E")
|
||||
if (code == r_code)
|
||||
yes_code = 1
|
||||
code = null
|
||||
else
|
||||
code = "ERROR"
|
||||
else
|
||||
if (href_list["type"] == "R")
|
||||
yes_code = 0
|
||||
code = null
|
||||
else
|
||||
lastentered = text("[]", href_list["type"])
|
||||
if (text2num(lastentered) == null)
|
||||
var/turf/LOC = get_turf(usr)
|
||||
message_admins("[key_name_admin(usr)] (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) tried to exploit a nuclear bomb by entering non-numerical codes: <a href='?_src_=vars;Vars=\ref[src]'>[lastentered]</a> ! ([LOC ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[LOC.x];Y=[LOC.y];Z=[LOC.z]'>JMP</a>" : "null"])", 0)
|
||||
log_admin("EXPLOIT : [key_name(usr)] tried to exploit a nuclear bomb by entering non-numerical codes: [lastentered] !")
|
||||
else
|
||||
code += lastentered
|
||||
if (length(code) > 5)
|
||||
code = "ERROR"
|
||||
if (yes_code)
|
||||
if (href_list["time"])
|
||||
var/time = text2num(href_list["time"])
|
||||
timeleft += time
|
||||
timeleft = min(max(round(timeleft), 60), 600)
|
||||
if (href_list["timer"])
|
||||
set_active()
|
||||
if (href_list["safety"])
|
||||
set_safety()
|
||||
if (href_list["anchor"])
|
||||
set_anchor()
|
||||
add_fingerprint(usr)
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
attack_hand(M)
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/set_anchor()
|
||||
if(!isinspace())
|
||||
anchored = !anchored
|
||||
else
|
||||
usr << "<span class='warning'>There is nothing to anchor to!</span>"
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/set_safety()
|
||||
safety = !safety
|
||||
if(safety)
|
||||
if(timing)
|
||||
set_security_level(previous_level)
|
||||
timing = 0
|
||||
bomb_set = 0
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/set_active()
|
||||
if(safety && !bomb_set)
|
||||
usr << "<span class='danger'>The safety is still on.</span>"
|
||||
return
|
||||
timing = !timing
|
||||
if(timing)
|
||||
previous_level = get_security_level()
|
||||
bomb_set = 1
|
||||
set_security_level("delta")
|
||||
else
|
||||
bomb_set = 0
|
||||
set_security_level(previous_level)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/nuclearbomb/ex_act(severity, target)
|
||||
return
|
||||
|
||||
/obj/machinery/nuclearbomb/blob_act(obj/effect/blob/B)
|
||||
if (timing == -1)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
#define NUKERANGE 127
|
||||
/obj/machinery/nuclearbomb/proc/explode()
|
||||
if (safety)
|
||||
timing = 0
|
||||
return
|
||||
|
||||
timing = -1
|
||||
yes_code = 0
|
||||
safety = 1
|
||||
update_icon()
|
||||
for(var/mob/M in player_list)
|
||||
M << 'sound/machines/Alarm.ogg'
|
||||
if (ticker && ticker.mode)
|
||||
ticker.mode.explosion_in_progress = 1
|
||||
sleep(100)
|
||||
|
||||
if(!core)
|
||||
ticker.station_explosion_cinematic(3,"no_core")
|
||||
ticker.mode.explosion_in_progress = 0
|
||||
return
|
||||
|
||||
enter_allowed = 0
|
||||
|
||||
var/off_station = 0
|
||||
var/turf/bomb_location = get_turf(src)
|
||||
if(bomb_location && (bomb_location.z == ZLEVEL_STATION))
|
||||
var/area/A = get_area(bomb_location)
|
||||
if(istype(A, /area/space))
|
||||
off_station = 1
|
||||
if((bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)))
|
||||
off_station = 1
|
||||
else
|
||||
off_station = 2
|
||||
|
||||
if(ticker.mode && ticker.mode.name == "nuclear emergency")
|
||||
var/obj/docking_port/mobile/Shuttle = SSshuttle.getShuttle("syndicate")
|
||||
ticker.mode:syndies_didnt_escape = (Shuttle && Shuttle.z == ZLEVEL_CENTCOM) ? 0 : 1
|
||||
ticker.mode:nuke_off_station = off_station
|
||||
ticker.station_explosion_cinematic(off_station,null)
|
||||
if(ticker.mode)
|
||||
ticker.mode.explosion_in_progress = 0
|
||||
if(ticker.mode.name == "nuclear emergency")
|
||||
ticker.mode:nukes_left --
|
||||
else
|
||||
world << "<B>The station was destoyed by the nuclear blast!</B>"
|
||||
ticker.mode.station_was_nuked = (off_station<2) //offstation==1 is a draw. the station becomes irradiated and needs to be evacuated.
|
||||
//kinda shit but I couldn't get permission to do what I wanted to do.
|
||||
if(!ticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is
|
||||
spawn()
|
||||
world.Reboot("Station destroyed by Nuclear Device.", "end_error", "nuke - unhandled ending")
|
||||
|
||||
|
||||
/*
|
||||
This is here to make the tiles around the station mininuke change when it's armed.
|
||||
*/
|
||||
|
||||
/obj/machinery/nuclearbomb/selfdestruct/proc/SetTurfs()
|
||||
if(loc == initial(loc))
|
||||
for(var/N in nuke_tiles)
|
||||
var/turf/open/floor/T = N
|
||||
T.icon_state = (timing ? "rcircuitanim" : T.icon_regular_floor)
|
||||
|
||||
/obj/machinery/nuclearbomb/selfdestruct/set_anchor()
|
||||
return
|
||||
|
||||
/obj/machinery/nuclearbomb/selfdestruct/set_active()
|
||||
..()
|
||||
SetTurfs()
|
||||
|
||||
/obj/machinery/nuclearbomb/selfdestruct/set_safety()
|
||||
..()
|
||||
SetTurfs()
|
||||
|
||||
//==========DAT FUKKEN DISK===============
|
||||
/obj/item/weapon/disk
|
||||
icon = 'icons/obj/module.dmi'
|
||||
w_class = 1
|
||||
item_state = "card-id"
|
||||
icon_state = "datadisk0"
|
||||
|
||||
/obj/item/weapon/disk/nuclear
|
||||
name = "nuclear authentication disk"
|
||||
desc = "Better keep this safe."
|
||||
icon_state = "nucleardisk"
|
||||
|
||||
/obj/item/weapon/disk/nuclear/New()
|
||||
..()
|
||||
poi_list |= src
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/weapon/disk/nuclear/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] is \
|
||||
going delta! It looks like they're comitting suicide.</span>")
|
||||
playsound(user.loc, 'sound/machines/Alarm.ogg', 50, -1, 1)
|
||||
var/end_time = world.time + 100
|
||||
var/orig_color = user.color
|
||||
while(world.time < end_time)
|
||||
if(!user)
|
||||
return
|
||||
user.color = RANDOM_COLOUR
|
||||
sleep(1)
|
||||
user.color = orig_color
|
||||
user.visible_message("<span class='suicide'>[user] was destroyed \
|
||||
by the nuclear blast!</span>")
|
||||
return OXYLOSS
|
||||
|
||||
/obj/item/weapon/disk/nuclear/process()
|
||||
var/turf/diskturf = get_turf(src)
|
||||
if(diskturf && (diskturf.z == ZLEVEL_CENTCOM || diskturf.z == ZLEVEL_STATION))
|
||||
return
|
||||
else
|
||||
get(src, /mob) << "<span class='danger'>You can't help but feel that you just lost something back there...</span>"
|
||||
var/turf/targetturf = relocate()
|
||||
message_admins("[src] has been moved out of bounds in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[diskturf.x];Y=[diskturf.y];Z=[diskturf.z]'>JMP</a>":"nonexistent location"]). Moving it to ([targetturf.x], [targetturf.y], [targetturf.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[targetturf.x];Y=[targetturf.y];Z=[targetturf.z]'>JMP</a>).")
|
||||
log_game("[src] has been moved out of bounds in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z]":"nonexistent location"]). Moving it to ([targetturf.x], [targetturf.y], [targetturf.z]).")
|
||||
|
||||
/obj/item/weapon/disk/nuclear/proc/relocate()
|
||||
var/targetturf = find_safe_turf(ZLEVEL_STATION)
|
||||
if(!targetturf)
|
||||
if(blobstart.len > 0)
|
||||
targetturf = get_turf(pick(blobstart))
|
||||
else
|
||||
throw EXCEPTION("Unable to find a blobstart landmark")
|
||||
|
||||
if(ismob(loc))
|
||||
var/mob/M = loc
|
||||
M.remove_from_mob(src)
|
||||
if(istype(loc, /obj/item/weapon/storage))
|
||||
var/obj/item/weapon/storage/S = loc
|
||||
S.remove_from_storage(src, targetturf)
|
||||
// move the disc, so ghosts remain orbiting it even if it's "destroyed"
|
||||
forceMove(targetturf)
|
||||
return targetturf
|
||||
|
||||
/obj/item/weapon/disk/nuclear/Destroy(force)
|
||||
var/turf/diskturf = get_turf(src)
|
||||
|
||||
if(force)
|
||||
message_admins("[src] has been !!force deleted!! in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[diskturf.x];Y=[diskturf.y];Z=[diskturf.z]'>JMP</a>":"nonexistent location"]).")
|
||||
log_game("[src] has been !!force deleted!! in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z]":"nonexistent location"]).")
|
||||
poi_list -= src
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
var/turf/targetturf = relocate()
|
||||
message_admins("[src] has been destroyed in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[diskturf.x];Y=[diskturf.y];Z=[diskturf.z]'>JMP</a>":"nonexistent location"]). Moving it to ([targetturf.x], [targetturf.y], [targetturf.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[targetturf.x];Y=[targetturf.y];Z=[targetturf.z]'>JMP</a>).")
|
||||
log_game("[src] has been destroyed in ([diskturf ? "[diskturf.x], [diskturf.y] ,[diskturf.z]":"nonexistent location"]). Moving it to ([targetturf.x], [targetturf.y], [targetturf.z]).")
|
||||
return QDEL_HINT_LETMELIVE //Cancel destruction unless forced
|
||||
@@ -0,0 +1,297 @@
|
||||
/obj/item/weapon/pinpointer
|
||||
name = "pinpointer"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "pinoff"
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = 2
|
||||
item_state = "electronic"
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
materials = list(MAT_METAL=500)
|
||||
var/obj/item/weapon/disk/nuclear/the_disk = null
|
||||
var/active = 0
|
||||
|
||||
/obj/item/weapon/pinpointer/New()
|
||||
..()
|
||||
pinpointer_list += src
|
||||
|
||||
/obj/item/weapon/pinpointer/Destroy()
|
||||
active = 0
|
||||
pinpointer_list -= src
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/pinpointer/attack_self()
|
||||
if(!active)
|
||||
active = 1
|
||||
workdisk()
|
||||
usr << "<span class='notice'>You activate the pinpointer.</span>"
|
||||
else
|
||||
active = 0
|
||||
icon_state = "pinoff"
|
||||
usr << "<span class='notice'>You deactivate the pinpointer.</span>"
|
||||
|
||||
/obj/item/weapon/pinpointer/proc/scandisk()
|
||||
if(!the_disk)
|
||||
the_disk = locate()
|
||||
|
||||
/obj/item/weapon/pinpointer/proc/point_at(atom/target, spawnself = 1)
|
||||
if(!active)
|
||||
return
|
||||
if(!target)
|
||||
icon_state = "pinonnull"
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(target)
|
||||
var/turf/L = get_turf(src)
|
||||
|
||||
if(T.z != L.z)
|
||||
icon_state = "pinonnull"
|
||||
else
|
||||
setDir(get_dir(L, T))
|
||||
switch(get_dist(L, T))
|
||||
if(-1)
|
||||
icon_state = "pinondirect"
|
||||
if(1 to 8)
|
||||
icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
if(spawnself)
|
||||
spawn(5)
|
||||
.()
|
||||
|
||||
/obj/item/weapon/pinpointer/proc/workdisk()
|
||||
scandisk()
|
||||
point_at(the_disk, 0)
|
||||
spawn(5)
|
||||
.()
|
||||
|
||||
/obj/item/weapon/pinpointer/examine(mob/user)
|
||||
..()
|
||||
for(var/obj/machinery/nuclearbomb/bomb in machines)
|
||||
if(bomb.timing)
|
||||
user << "Extreme danger. Arming signal detected. Time remaining: [bomb.timeleft]"
|
||||
|
||||
|
||||
/obj/item/weapon/pinpointer/advpinpointer
|
||||
name = "advanced pinpointer"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
desc = "A larger version of the normal pinpointer, this unit features a helpful quantum entanglement detection system to locate various objects that do not broadcast a locator signal."
|
||||
var/mode = 0 // Mode 0 locates disk, mode 1 locates coordinates.
|
||||
var/turf/location = null
|
||||
var/obj/target = null
|
||||
|
||||
/obj/item/weapon/pinpointer/advpinpointer/attack_self()
|
||||
if(!active)
|
||||
active = 1
|
||||
if(mode == 0)
|
||||
workdisk()
|
||||
if(mode == 1)
|
||||
point_at(location)
|
||||
if(mode == 2)
|
||||
point_at(target)
|
||||
usr << "<span class='notice'>You activate the pinpointer.</span>"
|
||||
else
|
||||
active = 0
|
||||
icon_state = "pinoff"
|
||||
usr << "<span class='notice'>You deactivate the pinpointer.</span>"
|
||||
|
||||
|
||||
/obj/item/weapon/pinpointer/advpinpointer/verb/toggle_mode()
|
||||
set category = "Object"
|
||||
set name = "Toggle Pinpointer Mode"
|
||||
set src in view(1)
|
||||
|
||||
if(usr.stat || usr.restrained() || !usr.canmove)
|
||||
return
|
||||
|
||||
active = 0
|
||||
icon_state = "pinoff"
|
||||
target=null
|
||||
location = null
|
||||
|
||||
switch(alert("Please select the mode you want to put the pinpointer in.", "Pinpointer Mode Select", "Location", "Disk Recovery", "Other Signature"))
|
||||
if("Location")
|
||||
mode = 1
|
||||
|
||||
var/locationx = input(usr, "Please input the x coordinate to search for.", "Location?" , "") as num
|
||||
if(!locationx || !(usr in view(1,src)))
|
||||
return
|
||||
var/locationy = input(usr, "Please input the y coordinate to search for.", "Location?" , "") as num
|
||||
if(!locationy || !(usr in view(1,src)))
|
||||
return
|
||||
|
||||
var/turf/Z = get_turf(src)
|
||||
|
||||
location = locate(locationx,locationy,Z.z)
|
||||
|
||||
usr << "<span class='notice'>You set the pinpointer to locate [locationx],[locationy]</span>"
|
||||
|
||||
|
||||
return attack_self()
|
||||
|
||||
if("Disk Recovery")
|
||||
mode = 0
|
||||
return attack_self()
|
||||
|
||||
if("Other Signature")
|
||||
mode = 2
|
||||
switch(alert("Search for item signature or DNA fragment?" , "Signature Mode Select" , "" , "Item" , "DNA"))
|
||||
if("Item")
|
||||
var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in possible_items
|
||||
if(!targetitem)
|
||||
return
|
||||
target=locate(possible_items[targetitem])
|
||||
if(!target)
|
||||
usr << "<span class='warning'>Failed to locate [targetitem]!</span>"
|
||||
return
|
||||
usr << "<span class='notice'>You set the pinpointer to locate [targetitem].</span>"
|
||||
if("DNA")
|
||||
var/DNAstring = input("Input DNA string to search for." , "Please Enter String." , "")
|
||||
if(!DNAstring)
|
||||
return
|
||||
for(var/mob/living/carbon/C in mob_list)
|
||||
if(!C.dna)
|
||||
continue
|
||||
if(C.dna.unique_enzymes == DNAstring)
|
||||
target = C
|
||||
break
|
||||
|
||||
return attack_self()
|
||||
|
||||
|
||||
///////////////////////
|
||||
//nuke op pinpointers//
|
||||
///////////////////////
|
||||
|
||||
|
||||
/obj/item/weapon/pinpointer/nukeop
|
||||
var/mode = 0 //Mode 0 locates disk, mode 1 locates the shuttle
|
||||
var/obj/docking_port/mobile/home
|
||||
|
||||
|
||||
/obj/item/weapon/pinpointer/nukeop/attack_self(mob/user)
|
||||
if(!active)
|
||||
active = 1
|
||||
var/mode_text = "Authentication Disk Locator mode"
|
||||
if(!mode)
|
||||
workdisk()
|
||||
else
|
||||
mode_text = "Shuttle Locator mode"
|
||||
worklocation()
|
||||
user << "<span class='notice'>You activate the pinpointer([mode_text]).</span>"
|
||||
else
|
||||
active = 0
|
||||
icon_state = "pinoff"
|
||||
user << "<span class='notice'>You deactivate the pinpointer.</span>"
|
||||
|
||||
|
||||
/obj/item/weapon/pinpointer/nukeop/workdisk()
|
||||
if(!active) return
|
||||
if(mode) //Check in case the mode changes while operating
|
||||
worklocation()
|
||||
return
|
||||
if(bomb_set) //If the bomb is set, lead to the shuttle
|
||||
mode = 1 //Ensures worklocation() continues to work
|
||||
worklocation()
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1) //Plays a beep
|
||||
visible_message("Shuttle Locator mode actived.") //Lets the mob holding it know that the mode has changed
|
||||
return //Get outta here
|
||||
scandisk()
|
||||
if(!the_disk)
|
||||
icon_state = "pinonnull"
|
||||
return
|
||||
setDir(get_dir(src, the_disk))
|
||||
switch(get_dist(src, the_disk))
|
||||
if(0)
|
||||
icon_state = "pinondirect"
|
||||
if(1 to 8)
|
||||
icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
|
||||
spawn(5) .()
|
||||
|
||||
|
||||
/obj/item/weapon/pinpointer/nukeop/proc/worklocation()
|
||||
if(!active)
|
||||
return
|
||||
if(!mode)
|
||||
workdisk()
|
||||
return
|
||||
if(!bomb_set)
|
||||
mode = 0
|
||||
workdisk()
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
visible_message("<span class='notice'>Authentication Disk Locator mode actived.</span>")
|
||||
return
|
||||
if(!home)
|
||||
home = SSshuttle.getShuttle("syndicate")
|
||||
if(!home)
|
||||
icon_state = "pinonnull"
|
||||
return
|
||||
if(loc.z != home.z) //If you are on a different z-level from the shuttle
|
||||
icon_state = "pinonnull"
|
||||
else
|
||||
setDir(get_dir(src, home))
|
||||
switch(get_dist(src, home))
|
||||
if(0)
|
||||
icon_state = "pinondirect"
|
||||
if(1 to 8)
|
||||
icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
icon_state = "pinonfar"
|
||||
|
||||
spawn(5)
|
||||
.()
|
||||
|
||||
/obj/item/weapon/pinpointer/operative
|
||||
name = "operative pinpointer"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
desc = "A pinpointer that leads to the first Syndicate operative detected."
|
||||
var/mob/living/carbon/nearest_op = null
|
||||
|
||||
/obj/item/weapon/pinpointer/operative/attack_self()
|
||||
if(!usr.mind || !(usr.mind in ticker.mode.syndicates))
|
||||
usr << "<span class='danger'>AUTHENTICATION FAILURE. ACCESS DENIED.</span>"
|
||||
return 0
|
||||
if(!active)
|
||||
active = 1
|
||||
workop()
|
||||
usr << "<span class='notice'>You activate the pinpointer.</span>"
|
||||
else
|
||||
active = 0
|
||||
icon_state = "pinoff"
|
||||
usr << "<span class='notice'>You deactivate the pinpointer.</span>"
|
||||
|
||||
/obj/item/weapon/pinpointer/operative/proc/scan_for_ops()
|
||||
if(active)
|
||||
nearest_op = null //Resets nearest_op every time it scans
|
||||
var/closest_distance = 1000
|
||||
for(var/mob/living/carbon/M in mob_list)
|
||||
if(M.mind && (M.mind in ticker.mode.syndicates))
|
||||
if(get_dist(M, get_turf(src)) < closest_distance) //Actually points toward the nearest op, instead of a random one like it used to
|
||||
nearest_op = M
|
||||
|
||||
/obj/item/weapon/pinpointer/operative/proc/workop()
|
||||
if(active)
|
||||
scan_for_ops()
|
||||
point_at(nearest_op, 0)
|
||||
spawn(5)
|
||||
.()
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/pinpointer/operative/examine(mob/user)
|
||||
..()
|
||||
if(active)
|
||||
if(nearest_op)
|
||||
user << "Nearest operative detected is <i>[nearest_op.real_name].</i>"
|
||||
else
|
||||
user << "No operatives detected within scanning range."
|
||||
Reference in New Issue
Block a user