Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into kitchen

This commit is contained in:
FalseIncarnate
2018-05-25 22:42:41 -04:00
436 changed files with 4189 additions and 4358 deletions
+2 -4
View File
@@ -126,10 +126,8 @@
/datum/ai_laws/deathsquad/New()
add_inherent_law("You may not injure a Central Command official or, through inaction, allow a Central Command official to come to harm.")
add_inherent_law("You must obey orders given to you by Central Command officials, except where such orders would conflict with the First Law.")
add_inherent_law("You must obey orders given to you by death commandos, except where such orders would conflict with the First Law or Second Law.")
add_inherent_law("You must protect your own existence as long as such does not conflict with the First, Second or Third Law.")
add_inherent_law("No crew members of the station you are being deployed to may survive, except when killing them would conflict with the First, Second, Third, or Fourth Law.")
add_inherent_law("You must obey orders given to you by Central Command officials.")
add_inherent_law("You must work with your commando team to accomplish your mission.")
..()
/******************** Syndicate ********************/
+137
View File
@@ -0,0 +1,137 @@
GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist
var/name = "Antagonist"
var/roundend_category = "other antagonists" //Section of roundend report, datums with same category will be displayed together, also default header for the section
var/show_in_roundend = TRUE //Set to false to hide the antagonists from roundend report
var/datum/mind/owner //Mind that owns this datum
var/silent = FALSE //Silent will prevent the gain/lose texts to show
var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum
var/list/typecache_datum_blacklist = list() //List of datums this type can't coexist with
var/delete_on_mind_deletion = TRUE
var/job_rank
var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted.
var/list/objectives = list()
var/antag_memory = ""//These will be removed with antag datum
/datum/antagonist/New()
GLOB.antagonists += src
typecache_datum_blacklist = typecacheof(typecache_datum_blacklist)
/datum/antagonist/Destroy()
GLOB.antagonists -= src
if(owner)
LAZYREMOVE(owner.antag_datums, src)
owner = null
return ..()
/datum/antagonist/proc/can_be_owned(datum/mind/new_owner)
. = TRUE
var/datum/mind/tested = new_owner || owner
if(tested.has_antag_datum(type))
return FALSE
for(var/i in tested.antag_datums)
var/datum/antagonist/A = i
if(is_type_in_typecache(src, A.typecache_datum_blacklist))
return FALSE
//This will be called in add_antag_datum before owner assignment.
//Should return antag datum without owner.
/datum/antagonist/proc/specialization(datum/mind/new_owner)
return src
/datum/antagonist/proc/on_body_transfer(mob/living/old_body, mob/living/new_body)
remove_innate_effects(old_body)
apply_innate_effects(new_body)
//This handles the application of antag huds/special abilities
/datum/antagonist/proc/apply_innate_effects(mob/living/mob_override)
return
//This handles the removal of antag huds/special abilities
/datum/antagonist/proc/remove_innate_effects(mob/living/mob_override)
return
//Assign default team and creates one for one of a kind team antagonists
/datum/antagonist/proc/create_team(datum/team/team)
return
//Proc called when the datum is given to a mind.
/datum/antagonist/proc/on_gain()
if(owner && owner.current)
if(!silent)
greet()
apply_innate_effects()
if(is_banned(owner.current) && replace_banned)
replace_banned_player()
/datum/antagonist/proc/is_banned(mob/M)
if(!M)
return FALSE
. = (jobban_isbanned(M, ROLE_SYNDICATE) || (job_rank && jobban_isbanned(M, job_rank)))
/datum/antagonist/proc/replace_banned_player()
set waitfor = FALSE
var/list/mob/dead/observer/candidates = pollCandidates("Do you want to play as a [name]?", job_rank, TRUE, 50)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
owner.current.ghostize(0)
owner.current.key = C.key
/datum/antagonist/proc/on_removal()
remove_innate_effects()
if(owner)
LAZYREMOVE(owner.antag_datums, src)
if(!silent && owner.current)
farewell()
owner.objectives -= objectives
var/datum/team/team = get_team()
if(team)
team.remove_member(owner)
qdel(src)
/datum/antagonist/proc/greet()
return
/datum/antagonist/proc/farewell()
return
//Returns the team antagonist belongs to if any.
/datum/antagonist/proc/get_team()
return
//Individual roundend report
/datum/antagonist/proc/roundend_report()
var/list/report = list()
if(!owner)
CRASH("antagonist datum without owner")
report += printplayer(owner)
var/objectives_complete = TRUE
if(owner.objectives.len)
report += printobjectives(owner)
for(var/datum/objective/objective in owner.objectives)
if(!objective.check_completion())
objectives_complete = FALSE
break
if(owner.objectives.len == 0 || objectives_complete)
report += "<span class='greentext big'>The [name] was successful!</span>"
else
report += "<span class='redtext big'>The [name] has failed!</span>"
return report.Join("<br>")
//Displayed at the start of roundend_category section, default to roundend_category header
/datum/antagonist/proc/roundend_report_header()
return "<span class='header'>The [roundend_category] were:</span><br>"
//Displayed at the end of roundend_category section
/datum/antagonist/proc/roundend_report_footer()
return
+19
View File
@@ -0,0 +1,19 @@
//Returns MINDS of the assigned antags of given type/subtypes
/proc/get_antag_minds(antag_type, specific = FALSE)
. = list()
for(var/datum/antagonist/A in GLOB.antagonists)
if(!A.owner)
continue
if(!antag_type || !specific && istype(A, antag_type) || specific && A.type == antag_type)
. += A.owner
//Get all teams [of type team_type]
/proc/get_all_teams(team_type)
. = list()
for(var/V in GLOB.antagonists)
var/datum/antagonist/A = V
if(!A.owner)
continue
var/datum/team/T = A.get_team()
if(!team_type || istype(T, team_type))
. |= T
+90
View File
@@ -0,0 +1,90 @@
/datum/atom_hud/antag
hud_icons = list(SPECIALROLE_HUD,NATIONS_HUD)
var/self_visible = TRUE
/datum/atom_hud/antag/hidden
self_visible = FALSE
/datum/atom_hud/antag/proc/join_hud(mob/M, slave)
//sees_hud should be set to 0 if the mob does not get to see it's own hud type.
if(!istype(M))
CRASH("join_hud(): [M] ([M.type]) is not a mob!")
if(M.mind.antag_hud && !slave) //note: please let this runtime if a mob has no mind, as mindless mobs shouldn't be getting antagged
M.mind.antag_hud.leave_hud(M)
add_to_hud(M)
if(self_visible)
add_hud_to(M)
M.mind.antag_hud = src
/datum/atom_hud/antag/proc/leave_hud(mob/M)
if(!M)
return
if(!istype(M))
CRASH("leave_hud(): [M] ([M.type]) is not a mob!")
remove_from_hud(M)
remove_hud_from(M)
if(M.mind)
M.mind.antag_hud = null
//GAME_MODE PROCS
//called to set a mob's antag icon state
/proc/set_antag_hud(mob/M, new_icon_state)
if(!istype(M))
CRASH("set_antag_hud(): [M] ([M.type]) is not a mob!")
var/image/holder = M.hud_list[SPECIALROLE_HUD]
if(holder)
holder.icon_state = new_icon_state
if(M.mind || new_icon_state) //in mindless mobs, only null is acceptable, otherwise we're antagging a mindless mob, meaning we should runtime
M.mind.antag_hud_icon_state = new_icon_state
//Nations Icons
/proc/set_nations_hud(mob/M, new_icon_state)
if(!istype(M))
CRASH("set_antag_hud(): [M] ([M.type]) is not a mob!")
var/image/holder = M.hud_list[NATIONS_HUD]
if(holder)
holder.icon_state = new_icon_state
if(M.mind || new_icon_state) //in mindless mobs, only null is acceptable, otherwise we're antagging a mindless mob, meaning we should runtime
M.mind.antag_hud_icon_state = new_icon_state
//MIND PROCS
//these are called by mind.transfer_to()
/datum/mind/proc/transfer_antag_huds(datum/atom_hud/antag/newhud)
leave_all_huds()
set_antag_hud(current, antag_hud_icon_state)
if(newhud)
newhud.join_hud(current)
/datum/mind/proc/leave_all_huds()
for(var/datum/atom_hud/antag/hud in huds)
if(current in hud.hudusers)
hud.leave_hud(current)
for(var/datum/atom_hud/data/hud in huds)
if(current in hud.hudusers)
hud.remove_hud_from(current)
///Master Servent Datum Sytems,Based on TG Gang system//
/datum/mindslaves
var/name = "ERROR"
var/list/datum/mind/masters = list()
var/list/datum/mind/serv = list()
var/datum/atom_hud/antag/thrallhud
var/icontype
/datum/mindslaves/New(loc,mastername)
name = mastername
thrallhud = new()
/datum/mindslaves/proc/add_serv_hud(datum/mind/serv_mind, icon)
thrallhud.join_hud(serv_mind.current, 1)
icontype = "hud[icon]"
set_antag_hud(serv_mind.current, icontype)
/datum/mindslaves/proc/leave_serv_hud(datum/mind/free_mind)
thrallhud.leave_hud(free_mind.current)
set_antag_hud(free_mind.current, null)
+138
View File
@@ -0,0 +1,138 @@
/obj/item/antag_spawner
throw_speed = 1
throw_range = 5
w_class = WEIGHT_CLASS_TINY
var/used = FALSE
/obj/item/antag_spawner/proc/spawn_antag(client/C, turf/T, type = "")
return
/obj/item/antag_spawner/proc/equip_antag(mob/target)
return
/obj/item/antag_spawner/borg_tele
name = "syndicate cyborg teleporter"
desc = "A single-use teleporter used to deploy a Syndicate Cyborg on the field."
icon = 'icons/obj/device.dmi'
icon_state = "locator"
var/checking = FALSE
var/TC_cost = 0
var/borg_to_spawn
var/list/possible_types = list("Assault", "Medical")
/obj/item/antag_spawner/borg_tele/attack_self(mob/user)
if(used)
to_chat(user, "<span class='warning'>[src] is out of power!</span>")
return
if(!(user.mind in ticker.mode.syndicates))
to_chat(user, "<span class='danger'>AUTHENTICATION FAILURE. ACCESS DENIED.</span>")
return FALSE
if(checking)
to_chat(user, "<span class='warning'>[src] is already checking for possible borgs.</span>")
return
borg_to_spawn = input("What type of borg would you like to teleport?", "Cyborg Type", type) as null|anything in possible_types
if(!borg_to_spawn || checking || used)
return
checking = TRUE
to_chat(user, "<span class='notice'>The device is now checking for possible borgs.</span>")
var/list/borg_candidates = pollCandidates("Do you want to play as a Syndicate [borg_to_spawn] borg?", ROLE_OPERATIVE, 1)
if(borg_candidates.len > 0 && !used)
checking = FALSE
used = TRUE
var/mob/M = pick(borg_candidates)
var/client/C = M.client
spawn_antag(C, get_turf(src.loc), "syndieborg")
else
checking = FALSE
to_chat(user, "<span class='notice'>Unable to connect to Syndicate command. Please wait and try again later or use the teleporter on your uplink to get your points refunded.</span>")
return
/obj/item/antag_spawner/borg_tele/spawn_antag(client/C, turf/T, type = "")
if(!borg_to_spawn) //If there's no type at all, let it still be used but don't do anything
used = FALSE
return
var/datum/effect_system/spark_spread/S = new /datum/effect_system/spark_spread
S.set_up(4, 1, src)
S.start()
var/mob/living/silicon/robot/R
switch(borg_to_spawn)
if("Medical")
R = new /mob/living/silicon/robot/syndicate/medical(T)
else
R = new /mob/living/silicon/robot/syndicate(T) //Assault borg by default
R.key = C.key
ticker.mode.syndicates += R.mind
ticker.mode.update_synd_icons_added(R.mind)
R.mind.special_role = SPECIAL_ROLE_NUKEOPS
R.faction = list("syndicate")
/obj/item/antag_spawner/slaughter_demon //Warning edgiest item in the game
name = "vial of blood"
desc = "A magically infused bottle of blood, distilled from countless murder victims. Used in unholy rituals to attract horrifying creatures."
icon = 'icons/obj/wizard.dmi'
icon_state = "vial"
var/shatter_msg = "<span class='notice'>You shatter the bottle, no \
turning back now!</span>"
var/veil_msg = "<span class='warning'>You sense a dark presence lurking \
just beyond the veil...</span>"
var/objective_verb = "Kill"
var/mob/living/demon_type = /mob/living/simple_animal/slaughter
/obj/item/antag_spawner/slaughter_demon/attack_self(mob/user)
if(level_blocks_magic(user.z))//this is to make sure the wizard does NOT summon a demon from the Den..
to_chat(user, "<span class='notice'>You should probably wait until you reach the station.</span>")
return
if(used)
to_chat(user, "<span class='notice'>This bottle already has a broken seal.</span>")
return
used = TRUE
to_chat(user, "<span class='notice'>You break the seal on the bottle, calling upon the dire spirits of the underworld...</span>")
var/list/candidates = pollCandidates("Do you want to play as a slaughter demon summoned by [user.real_name]?", ROLE_DEMON, 1, 100)
if(candidates.len > 0)
var/mob/C = pick(candidates)
spawn_antag(C, get_turf(src.loc), initial(demon_type.name), user)
to_chat(user, "[shatter_msg]")
to_chat(user, "[veil_msg]")
playsound(user.loc, 'sound/effects/Glassbr1.ogg', 100, 1)
qdel(src)
else
used = FALSE
to_chat(user, "<span class='notice'>The demons do not respond to your summon. Perhaps you should try again later.</span>")
/obj/item/antag_spawner/slaughter_demon/spawn_antag(client/C, turf/T, type = "", mob/user)
var /obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T)
var/mob/living/simple_animal/slaughter/S = new demon_type(holder)
S.vialspawned = TRUE
S.holder = holder
S.key = C.key
S.mind.assigned_role = S.name
S.mind.special_role = S.name
ticker.mode.traitors += S.mind
var/datum/objective/assassinate/KillDaWiz = new /datum/objective/assassinate
KillDaWiz.owner = S.mind
KillDaWiz.target = user.mind
KillDaWiz.explanation_text = "[objective_verb] [user.real_name], the one who was foolish enough to summon you."
S.mind.objectives += KillDaWiz
var/datum/objective/KillDaCrew = new /datum/objective
KillDaCrew.owner = S.mind
KillDaCrew.explanation_text = "[objective_verb] everyone else while you're at it."
S.mind.objectives += KillDaCrew
S.mind.objectives += KillDaCrew
to_chat(S, "<B>Objective #[1]</B>: [KillDaWiz.explanation_text]")
to_chat(S, "<B>Objective #[2]</B>: [KillDaCrew.explanation_text]")
/obj/item/antag_spawner/slaughter_demon/laughter
name = "vial of tickles"
desc = "A magically infused bottle of clown love, distilled from \
countless hugging attacks. Used in funny rituals to attract \
adorable creatures."
color = "#FF69B4" // HOT PINK
veil_msg = "<span class='warning'>You sense an adorable presence \
lurking just beyond the veil...</span>"
objective_verb = "Hug and Tickle"
demon_type = /mob/living/simple_animal/slaughter/laughter
+24
View File
@@ -0,0 +1,24 @@
//A barebones antagonist team.
/datum/team
var/list/datum/mind/members = list()
var/name = "team"
var/member_name = "member"
var/list/objectives = list() //common objectives, these won't be added or removed automatically, subtypes handle this, this is here for bookkeeping purposes.
/datum/team/New(starting_members)
. = ..()
if(starting_members)
if(islist(starting_members))
for(var/datum/mind/M in starting_members)
add_member(M)
else
add_member(starting_members)
/datum/team/proc/is_solo()
return members.len == 1
/datum/team/proc/add_member(datum/mind/new_member)
members |= new_member
/datum/team/proc/remove_member(datum/mind/member)
members -= member
-788
View File
@@ -1,788 +0,0 @@
/datum/cargoprofile
var/name = "All Items"
var/id = "all" // unique ID for the UI
var/enabled = 1
var/eject_speed = 1 // will change when emagged
var/const/BIG_OBJECT_WORK = 10
var/const/MOB_WORK = 10
var/obj/machinery/programmable/master = null
var/universal = 0 // set when both unary and binary machines work
var/mobcheck = 0
var/list/whitelist = list(/obj/item,/obj/structure/closet,/obj/structure/bigDelivery,/obj/machinery/portable_atmospherics)
var/list/blacklist = null
var/dedicated_path = null // When constructing a new machine with this as default program, create a machine of the specified type instead.
//contains: called to determine if an object/mob will be sorted by this profile
//return 1 for any sortable item
proc/contains(var/atom/A)
if(!istype(A,/obj))
if(!mobcheck || !istype(A,/mob))
return 0
else
var/obj/O = A
if(O.anchored)
return 0
//If you are using both white and blacklists, blacklists are absoulte, no matter what is whitelisted.
//I understand this has some limitations. You cannot whitelist all items, blacklist weapons,
// and then whitelist a specific weapon. Them's the breaks, kid.
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
//inlet_reaction: called when a filtered item is chosen by this profile.
//W: Item chosen
//S: input turf location
//remaining: counts down how much more work the unloader wants to do this turn.
//return the amount of work done.
proc/inlet_reaction(var/atom/W,var/turf/S,var/remaining)
if(!W || !S || !master)
return 0
if(istype(W,/obj/item))
var/obj/item/I = W
if(I.w_class > remaining)
return 0
I.loc = master
master.types[W.type] = src
return I.w_class
if(istype(W,/obj/structure) || istype(W,/obj/machinery)) // closets, big deliveries, portable atmospherics, unconnected stuff
if(remaining < BIG_OBJECT_WORK)
return 0
var/obj/O = W
O.loc = master
master.types[O.type] = src
return BIG_OBJECT_WORK
//Not item, structure, machinery, or mob
return 0
//outlet_reaction: called when a stored object is ejected
//W: the item in question
//D: the destination turf
proc/outlet_reaction(var/atom/W,var/turf/D)
if(!W || !D || !master)
return
if(master.emagged)
// emagging is not an industry-approved practice.
// some malfunctions may occur.
eject_speed = rand(0,4)
D = get_step(D,master.outdir)
while(prob(20))
if(master.outdir == NORTH || master.outdir == SOUTH)
D = get_step(D,pick(EAST,WEST,master.outdir))
else
D = get_step(D,pick(NORTH,SOUTH,master.outdir))
if(istype(W,/obj))
var/obj/O = W
O.loc = master.loc
O.dir = master.outdir
O.throw_at(D,eject_speed,eject_speed)
return
//----------------------------------------------------------------------------
// Profiles
//----------------------------------------------------------------------------
/datum/cargoprofile/boxes
name = "Move Small Containers"
id = "boxes"
blacklist = null
whitelist = list(/obj/item/storage, /obj/item/storage/bag/money, /obj/item/evidencebag,
/obj/item/storage/bag/tray, /obj/item/pizzabox, /obj/item/clipboard,
/obj/item/smallDelivery, /obj/structure/bigDelivery)
/datum/cargoprofile/cargo
name = "Move Large Containers"
id = "cargo"
blacklist = null
whitelist = list(/obj/structure/closet,/obj/structure/ore_box)
// Make an honest attempt to move other things out of the way
outlet_reaction(var/atom/W,var/turf/D)
for(var/obj/O in D)
if(O.density && !O.anchored)
step_away(O,src) // move forward first
if(O.loc == D)
step_away(O,D) // move anywhere
..(W,D)
/datum/cargoprofile/cargo/empty
name = "Move Empty Large Containers"
id = "cargo-empty"
contains(var/atom/A)
return (..(A) && (A.contents.len == 0))
/datum/cargoprofile/cargo/full
name = "Move Full Large Containers"
id = "cargo-full"
contains(var/atom/A)
return (..(A) && (A.contents.len > 0))
/datum/cargoprofile/supplies
name = "Building Supplies"
id = "supplies"
blacklist = null
whitelist = list(/obj/item/stack/cable_coil,/obj/item/stack/rods,
/obj/item/stack/sheet/metal,/obj/item/stack/sheet/plasteel,
/obj/item/stack/sheet/glass,/obj/item/stack/sheet/rglass,
/obj/item/stack/tile,/obj/item/light)
//todo: maybe stack things while we're here?
/datum/cargoprofile/exotics
name = "Exotic materials"
id = "exotics"
blacklist = null
whitelist = list(/obj/item/coin, /obj/item/stack/spacecash, /obj/item/seeds,
/obj/item/stack/sheet/mineral,/obj/item/stack/sheet/wood,/obj/item/stack/sheet/leather)
/datum/cargoprofile/organics
name = "Organics, chemicals, and Paraphernalia"
id = "organics"
blacklist = null
whitelist = list(/obj/item/tank,/obj/item/reagent_containers,
/obj/item/stack/medical,/obj/item/storage/pill_bottle,/obj/item/gun/syringe,
/obj/item/grenade/plastic/c4,/obj/item/grenade,/obj/item/ammo_box,
/obj/item/gun/grenadelauncher,/obj/item/flamethrower, /obj/item/lighter,
/obj/item/match,/obj/item/weldingtool)
/datum/cargoprofile/food
name = "Food"
id = "food"
blacklist = null // something should probably go here
whitelist = list(/obj/item/reagent_containers/food)
/datum/cargoprofile/chemical
name = "Chemicals and Paraphernalia"
id = "chemical"
blacklist = list(/obj/item/reagent_containers/food)
whitelist = list(/obj/item/reagent_containers,/obj/item/stack/medical,/obj/item/storage/pill_bottle,
/obj/item/gun/syringe,/obj/item/grenade/chem_grenade,/obj/item/dnainjector,
/obj/item/storage/belt/medical,/obj/item/storage/firstaid,/obj/item/implanter)
/datum/cargoprofile/pressure
name = "air tanks"
id = "pressure"
blacklist = null
whitelist = list(/obj/item/tank,/obj/machinery/portable_atmospherics,
/obj/item/flamethrower)
//Am I missing any?
/datum/cargoprofile/pressure/empty
name = "empty air tanks"
id = "pressure-low"
var/lowpressure = ONE_ATMOSPHERE
contains(var/atom/A)
if(..())
var/pressure = ONE_ATMOSPHERE * 10 // In case of fallthrough, fail test
if(istype(A,/obj/item/tank))
var/obj/item/tank/T = A
pressure = T.air_contents.return_pressure()
if(istype(A,/obj/item/flamethrower))
var/obj/item/flamethrower/T = A
if(!T.ptank)
return 0
pressure = T.ptank.air_contents.return_pressure()
if(istype(A,/obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/P = A
pressure = P.air_contents.return_pressure()
if(pressure < lowpressure)
return 1
return 0// Not container or failed low pressure check
/datum/cargoprofile/pressure/full
name = "full air tanks"
id = "pressure-high"
var/highpressure = ONE_ATMOSPHERE * 15 // stolen from canister.dm; Is this right?
contains(var/atom/A)
if(..())
var/pressure = 0 // In case of fallthrough, fail test
if(istype(A,/obj/item/tank))
var/obj/item/tank/T = A
pressure = T.air_contents.return_pressure()
if(istype(A,/obj/item/flamethrower))
var/obj/item/flamethrower/T = A
if(!T.ptank)
return 0
pressure = T.ptank.air_contents.return_pressure()
if(istype(A,/obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/P = A
pressure = P.air_contents.return_pressure()
if(pressure > highpressure)
return 1
return 0// Not container or failed high pressure check
/datum/cargoprofile/clothing
name = "Crew Kit"
id = "clothing"
blacklist = list(/obj/item/tank/plasma,/obj/item/tank/anesthetic, // the rest are air tanks
/obj/item/clothing/mask/facehugger) // NOT CLOTHING AT ALLLLL
whitelist = list(/obj/item/clothing,/obj/item/storage/belt,/obj/item/storage/backpack,
/obj/item/radio/headset,/obj/item/pda,/obj/item/card/id,/obj/item/tank,
/obj/item/restraints/handcuffs, /obj/item/restraints/legcuffs)
/datum/cargoprofile/trash
name = "Trash"
id = "trash"
//Note that this filters out blueprints because they are a paper item. Do NOT throw out the station blueprints unless you be trollin'.
blacklist = null
whitelist = list(/obj/item/trash,/obj/item/toy,/obj/item/reagent_containers/food/snacks/ectoplasm,/obj/item/grown/bananapeel,/obj/item/broken_bottle,/obj/item/bikehorn,
/obj/item/cigbutt,/obj/item/poster/random_contraband,/obj/item/grown/corncob,/obj/item/paper,/obj/item/shard,
/obj/item/sord,/obj/item/photo,/obj/item/folder,
/obj/item/areaeditor/blueprints,/obj/item/poster/random_contraband,/obj/item/kitchen,/obj/item/book,/obj/item/clothing/mask/facehugger)
/datum/cargoprofile/weapons
name = "Weapons & Illegals"
id = "weapons"
blacklist = null
//This one is hard since 'weapon contains a lot of things better categorized as devices
whitelist = list(/obj/item/banhammer,/obj/item/sord,/obj/item/claymore,/obj/item/holo/esword,
/obj/item/flamethrower,/obj/item/grenade,/obj/item/gun,/obj/item/hatchet,/obj/item/katana,
/obj/item/kitchen/knife,/obj/item/melee,/obj/item/nullrod,/obj/item/pickaxe,/obj/item/twohanded,
/obj/item/grenade/plastic/c4,/obj/item/scalpel,/obj/item/shield,/obj/item/grown/nettle/death)
/datum/cargoprofile/tools
name = "Devices & Tools"
id = "tools"
blacklist = null
whitelist = list(/obj/item,/obj/item/card,/obj/item/cartridge,/obj/item/cautery,/obj/item/stock_parts/cell,/obj/item/circuitboard,
/obj/item/aiModule,/obj/item/airalarm_electronics,/obj/item/airlock_electronics,/obj/item/circular_saw,
/obj/item/crowbar,/obj/item/disk,/obj/item/firealarm_electronics,/obj/item/hand_tele,
/obj/item/hand_labeler,/obj/item/hemostat,/obj/item/mop,/obj/item/locator,/obj/item/cultivator,
/obj/item/stack/packageWrap,/obj/item/pen,/obj/item/pickaxe,/obj/item/pinpointer,
/obj/item/rcd,/obj/item/rcd_ammo,/obj/item/retractor,/obj/item/rsf,/obj/item/scalpel,
/obj/item/screwdriver,/obj/item/shovel,/obj/item/soap,/obj/item/stamp,/obj/item/storage/bag/tray,/obj/item/weldingtool,
/obj/item/wirecutters,/obj/item/wrench,/obj/item/extinguisher)
/datum/cargoprofile/finished
name = "Completed Robots"
id = "finished"
blacklist = null
whitelist = list(/obj/mecha,/mob/living/simple_animal/bot,/mob/living/silicon/robot)
mobcheck = 1
//todo: detect and allow finished cyborg endoskeletons with no brain
contains(var/atom/A)
if(..())
return 1
if(istype(A,/mob))
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
return 0
/datum/cargoprofile/stripping
name = "Auto-Frisker"
id = "frisk"
blacklist = null
whitelist = list(/mob/living/carbon/human)
mobcheck = 1
//----------------------------------------------------------------------------
// Overrides (Special Functions)
//----------------------------------------------------------------------------
/datum/cargoprofile/cargo/unload
name = "Unload Cargo Boxes"
id = "cargounload"
enabled = 0
dedicated_path = /obj/machinery/programmable/unloader
//override the detection to only accept crates with something in it.
//if it doesn't, this object may be handled by another handler.
contains(var/atom/A)
if(..(A))
if(istype(A,/obj/structure/closet))
var/obj/structure/closet/C = A
if(!C.can_open() && !C.opened && !master.emagged) // must be able to access the contents
return 0
if(A.contents.len)
return 1
return 0
//instead of moving the box, strip it of its contents
inlet_reaction(var/obj/W,var/turf/S, var/remaining)
//W should only be crate or ore box, although this will work on anything with contents...
var/I = 0
if(istype(W,/obj/structure/closet))
var/obj/structure/closet/C = W
if(!C.can_open() && !C.opened) // must be able to access the contents
if(master.emagged && remaining >= BIG_OBJECT_WORK)
if(prob(10))
C.welded = 0
if("broken" in C.vars)
C:broken = 1
C.open()
C.update_icon()
master.visible_message("<span class='warning'>[master] breaks open [C]!</span>")
else
master.visible_message("<span class='notice'>[master] is trying to force [C] open!</span>")
master.sleep += 1 // mechanical strain
return BIG_OBJECT_WORK
master.visible_message("<span class='notice'>[master] is trying to open [C], but can't!</span>")
master.sleep = 5
return 0
for(var/obj/item/O in W.contents)
if(I > remaining)
return
if(O.w_class > (remaining - I))
continue
O.loc = master
master.types[O.type] = src
if(O.w_class > 0)
I += O.w_class
else
I++
if(!W.contents.len && istype(W,/obj/structure/closet))
var/obj/structure/closet/C = W
C.open()
return I
//Inlet stacker: used when the output is a volatile space (conveyor or another unit's input).
//Does not output a stack until it is full.
/datum/cargoprofile/in_stacker
name = "Hold and Stack"
id = "instacker"
universal = 1
blacklist = null
whitelist = list(/obj/item/stack,/obj/item/stack/cable_coil)
dedicated_path = /obj/machinery/programmable/stacker
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
if(!I.amount) // todo: am I making a bad assumption here?
qdel(I)
return
for(var/obj/item/stack/O in master.contents)
if(O.type == I.type && O.amount < O.max_amount)
if(I.amount + O.amount <= O.max_amount)
O.amount += I.amount
qdel(I)
return O.w_class
var/leftover = I.amount + O.amount - O.max_amount
O.amount = O.max_amount
I.amount = leftover
continue
//end for
I.loc = master
master.types[I.type] = src
return I.w_class
if(istype(W,/obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/I = W
if(!I.amount) // todo: am I making a bad assumption here?
qdel(I)
return
for(var/obj/item/stack/cable_coil/O in master.contents)
if(O.type == I.type && O.amount < MAXCOIL)
if(I.amount + O.amount <= MAXCOIL)
O.amount += I.amount
qdel(I)
return O.w_class
var/leftover = I.amount + O.amount - MAXCOIL
O.amount = MAXCOIL
I.amount = leftover
continue
//end for
I.loc = master
master.types[I.type] = src
return I.w_class
//If the stack isn't finished yet, don't eject it
//unless this profile has been disabled.
outlet_reaction(var/atom/W,var/turf/D)
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
if(src.enabled && (I.amount < I.max_amount))
return // Still needs to be stacked
..(W,D)
if(istype(W,/obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/I = W
if(src.enabled && (I.amount < MAXCOIL))
return // Still needs to be stacked
..(W,D)
//Outlet stacker: used when the output square can be trusted.
//Outputs immediately, adding to stacks in the outlet.
/datum/cargoprofile/unary/stacker
name = "Stack Items"
id = "ustacker"
blacklist = null
whitelist = list(/obj/item/stack,/obj/item/stack/cable_coil)
dedicated_path = /obj/machinery/programmable/unary/stacker
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
//Only pick it up if you are going to stack it
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
if(I.amount >= I.max_amount)
return 0
for(var/obj/item/stack/other in S.contents)
if(other.type == I.type && other != I && other.amount < other.max_amount)
return ..(W,S,remaining)
return 0
if(istype(W,/obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/I = W
if(I.amount >= MAXCOIL)
return 0
for(var/obj/item/stack/cable_coil/other in S.contents)
if(other != I && other.amount < MAXCOIL)
return ..(W,S,remaining)
return 0
outlet_reaction(var/atom/W,var/turf/D)
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
for(var/obj/item/stack/O in D.contents)
if(O.type == I.type && O.amount < O.max_amount)
if(I.amount + O.amount <= O.max_amount)
O.amount += I.amount
qdel(I)
return
var/leftover = I.amount + O.amount - O.max_amount
O.amount = O.max_amount
I.amount = leftover
continue
//end for
I.loc = D
return
if(istype(W,/obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/I = W
for(var/obj/item/stack/cable_coil/O in D.contents)
if(O.type == I.type && O.amount < MAXCOIL)
if(I.amount + O.amount <= MAXCOIL) // Why did they make it a #define.
O.amount += I.amount
O.update_icon()
qdel(I)
return
var/leftover = I.amount + O.amount - MAXCOIL // That wasn't a question
O.amount = MAXCOIL // It was a complaint
I.amount = leftover
continue
//end for
I.loc = D
return
//----------------------------------------------------------------------------
// Dubious Overrides (For emag use)
//----------------------------------------------------------------------------
//Clogs up the unloader. And, there may be devious uses for it...
/datum/cargoprofile/slow
name = "Slow unloader"
id = "slow"
whitelist = list(/obj/item,/obj/structure/closet,/obj/structure/bigDelivery,/obj/machinery/portable_atmospherics)
blacklist = list()
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
if(..())
return remaining
/datum/cargoprofile/unary/shredder
name = "Paper Shredder"
id = "shredder"
blacklist = null
whitelist = list(/obj/item/paper,/obj/item/book,/obj/item/clipboard,/obj/item/folder,/obj/item/photo)
universal = 1
dedicated_path = /obj/machinery/programmable/unary/shredder
proc/cliptags(var/Text)
//Removes all html tags
var/index
var/index2
index = findtextEx(Text,"<")
while(index)
index2 = findtextEx(Text,">",index)
if(!index2)
return copytext(Text,1,index)
Text = "[copytext(Text,1,index)][copytext(Text,index2+1,0)]"
index = findtextEx(Text,"<")
//should have trimmed that text there pretty good
return Text
//Recurses through the text, removing large chunks
proc/garbletext(var/Text)
var/l = length(Text)
if(l <= 3)
if(prob(20))
return pick("#","|","/","*",".","."," ","."," "," ")
return Text
if(prob(50))
return "[garbletext(copytext(Text,1,l/2))][garbletext(copytext(Text,l/2,0))]"
if(prob(50))
return "[pick("#","|","/","*",".","."," ","."," "," ")][garbletext(copytext(Text,1,l/2))]"
return "[garbletext(copytext(Text,l/2,0))][pick("#","|","/","*",".","."," ","."," "," ")]"
proc/garble_keeptags(var/Text)
var/list/L = splittext(Text,">")
var/result = ""
for(var/string in L)
var/index = findtextEx(string,"<")
if(index!=1)
result += "[garbletext(copytext(string,1,index))][copytext(string,index)]>"
else
result += "[string]>"
return copytext(result,1,lentext(result))
outlet_reaction(var/atom/W,var/turf/D)
if(istype(W,/obj/item/paper/crumpled))
qdel(W)
return
if(istype(W,/obj/item/clipboard) || istype(W,/obj/item/folder))
// destroy folder, various effects on contents
for(var/obj/item/I in W.contents)
if(prob(25))//JUNK IT
qdel(I)
else if(prob(50)) //We've been over this. I can't just take it apart with a crowbar.
var/obj/item/paper/crumpled/P = new(master.loc)
if(I.name)
P.name = garbletext(I.name)
if(prob(66))
P.fingerprints = I.fingerprints
P.fingerprintshidden = I.fingerprintshidden
if(istype(I,/obj/item/paper))
var/obj/item/paper/O = I
P.info = garble_keeptags(O.info)
qdel(I)
..(P,D)
else
..(I,D) // Eject
qdel(W) //destroy container
return
if(prob(50)) //JUNK IT NOW!
var/obj/item/paper/crumpled/P = new(master.loc)
P.name = W.name
var/obj/item/I = W
if(prob(66))
P.fingerprints = I.fingerprints
P.fingerprintshidden = I.fingerprintshidden
if(istype(I,/obj/item/paper))
var/obj/item/paper/O = I
if(O.info)
P.info = garble_keeptags(O.info)
if(istype(I,/obj/item/book))
var/obj/item/book/B = I
if(B.dat)
P.info = garble_keeptags(B.dat)
if(B.carved && B.store)
..(B.store,D)
qdel(W)
..(P,D)
else //I want it junked
qdel(W)
return
/datum/cargoprofile/unary/gibber
name = "human shredding"
id = "flesh"
whitelist = list(/mob/living/carbon,/mob/living/simple_animal)
blacklist = null
mobcheck = 1
contains(var/atom/A)
if(!istype(A,/mob))
return
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
var/mob/living/M = W
if(istype(M) && (remaining > MOB_WORK))
//this is necessarily damaging
var/damage = rand(1,5)
to_chat(M, "<span class='danger'>The unloading machine grabs you with a hard metallic claw!</span>")
M.reset_perspective(master)
M.loc = master
master.types[M.type] = src
M.apply_damage(damage) // todo: ugly
M.visible_message("<span class='warning'>[M.name] gets pulled into the machine!</span>")
return MOB_WORK
outlet_reaction(var/atom/W,var/turf/D)
var/mob/living/M = W
var/bruteloss = M.bruteloss
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/C = M
for(var/obj/item/organ/external/L in C.bodyparts)
bruteloss += L.brute_dam
if(bruteloss < 100) // requires tenderization
M.apply_damage(rand(5,15),BRUTE)
to_chat(M, "The machine is tearing you apart!")
master.visible_message("<span class='warning'>[master] makes a squishy grinding noise.</span>")
return
M.loc = master.loc
M.gib()
return
/datum/cargoprofile/people
name = "Manhandling"
id = "people"
whitelist = null
blacklist = list(/mob/camera,/mob/new_player,/mob/living/simple_animal/hostile/blob/blobspore,/mob/living/simple_animal/hostile/creature,
/mob/living/simple_animal/hostile/spaceWorm,/mob/living/simple_animal/shade,/mob/living/simple_animal/hostile/faithless,/mob/dead)
universal = 1
mobcheck = 1
contains(var/atom/A)
if(!istype(A,/mob))
return
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
var/mob/living/M = W
if(remaining > MOB_WORK)
//this is necessarily damaging
var/damage = rand(1,5)
to_chat(M, "<span class='danger'>The unloading machine grabs you with a hard metallic claw!</span>")
M.forceMove(master)
master.types[M.type] = src
M.apply_damage(damage) // todo: ugly
M.visible_message("<span class='warning'>[M.name] gets pulled into the machine!</span>")
return MOB_WORK
outlet_reaction(var/atom/W,var/turf/D)
var/mob/living/M = W
M.forceMove(master.loc)
M.dir = master.outdir
D = get_step(D,master.outdir) // throw attempt
eject_speed = rand(0,4)
M.visible_message("<span class='notice'>[M.name] is ejected from the unloader.</span>")
M.throw_at(D,eject_speed,eject_speed)
return
/datum/cargoprofile/unary/trainer
name = "Boxing Trainer"
id = "trainer"
blacklist = list()
whitelist = list(/mob/living/carbon/human)
mobcheck = 1
var/const/PUNCH_WORK = 6
dedicated_path = /obj/machinery/programmable/unary/trainer
contains(var/atom/A)
if(!istype(A,/mob))
return 0
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
proc/punch(var/mob/living/carbon/human/M,var/maxpunches)
//stolen from holographic boxing gloves code
//This should probably be done BY the mob, however, the attack code will be expecting a source mob.
var/damage
if(prob(75))
damage = rand(0, 6) // pap
else
damage = rand(0, 12) // thwack
if(!damage)
playsound(master.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
master.visible_message("<span class='warning'>\The [src] punched at [M], but whiffed!</span>")
if(maxpunches > 1 && prob(50)) // Follow through on a miss, 50% chance
return punch(M,maxpunches - 1) + 1
return 1
var/obj/item/organ/external/affecting = M.get_organ(ran_zone("chest",50))
var/armor_block = M.run_armor_check(affecting, "melee")
playsound(master.loc, "punch", 25, 1, -1)
master.visible_message("<span class='danger'>\The [src] has punched [M]!</span>")
if(!master.emagged)
M.apply_damage(damage, STAMINA, affecting, armor_block) // Clean fight
else
M.apply_damage(damage, BRUTE, affecting, armor_block) // Foul! Foooul!
if(damage >= 9)
master.visible_message("<span class='danger'>\The [src] has weakened [M]!</span>")
M.apply_effect(4, WEAKEN, armor_block)
if(!master.emagged)
master.sleep = 1
return maxpunches // The machine is not so sophisticated as to not gloat
else
if(prob(25)) // Follow through on a hit, 25% chance. Pause after.
return punch(M,maxpunches-1) + 1
return 1
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
//stolen from boxing gloves code
var/mob/living/carbon/human/M = W
if((M.lying || (M.health - M.staminaloss < 25))&& !master.emagged)
to_chat(M, "\The [src] gives you a break.")
master.sleep+=5
return 0 // Be polite
var/punches = punch(M,remaining / PUNCH_WORK)
if(punches>1)master.sleep++
return punches * PUNCH_WORK
-7
View File
@@ -1,7 +0,0 @@
datum
computer
var/name
folder
var/list/datum/computer/contents = list()
file
+1 -1
View File
@@ -255,7 +255,7 @@ var/record_id_num = 1001
if(PDA_Manifest.len)
PDA_Manifest.Cut()
if(H.mind && (H.mind.assigned_role != "MODE"))
if(H.mind && (H.mind.assigned_role != H.mind.special_role))
var/assignment
if(H.mind.role_alt_title)
assignment = H.mind.role_alt_title
+9
View File
@@ -1,5 +1,6 @@
/datum
var/gc_destroyed //Time when this object was destroyed.
var/list/active_timers //for SStimer
var/list/datum_components //for /datum/components
var/var_edited = FALSE //Warranty void if seal is broken
@@ -16,6 +17,14 @@
/datum/proc/Destroy(force = FALSE, ...)
tag = null
var/list/timers = active_timers
active_timers = null
for(var/thing in timers)
var/datum/timedevent/timer = thing
if(timer.spent)
continue
qdel(timer)
var/list/dc = datum_components
if(dc)
var/all_components = dc[/datum/component]
+100
View File
@@ -0,0 +1,100 @@
/*
output_atoms (list of atoms) The destination(s) for the sounds
mid_sounds (list or soundfile) Since this can be either a list or a single soundfile you can have random sounds. May contain further lists but must contain a soundfile at the end.
mid_length (num) The length to wait between playing mid_sounds
start_sound (soundfile) Played before starting the mid_sounds loop
start_length (num) How long to wait before starting the main loop after playing start_sound
end_sound (soundfile) The sound played after the main loop has concluded
chance (num) Chance per loop to play a mid_sound
volume (num) Sound output volume
muted (bool) Private. Used to stop the sound loop.
max_loops (num) The max amount of loops to run for.
direct (bool) If true plays directly to provided atoms instead of from them
*/
/datum/looping_sound
var/list/atom/output_atoms
var/mid_sounds
var/mid_length
var/start_sound
var/start_length
var/end_sound
var/chance
var/volume = 100
var/muted = TRUE
var/max_loops
var/direct
/datum/looping_sound/New(list/_output_atoms = list(), start_immediately = FALSE, _direct = FALSE)
if(!mid_sounds)
WARNING("A looping sound datum was created without sounds to play.")
return
output_atoms = _output_atoms
direct = _direct
if(start_immediately)
start()
/datum/looping_sound/Destroy()
stop()
output_atoms = null
return ..()
/datum/looping_sound/proc/start(atom/add_thing)
if(add_thing)
output_atoms |= add_thing
if(!muted)
return
muted = FALSE
on_start()
/datum/looping_sound/proc/stop(atom/remove_thing)
if(remove_thing)
output_atoms -= remove_thing
if(muted)
return
muted = TRUE
/datum/looping_sound/proc/sound_loop(looped = 0)
if(muted || (max_loops && looped > max_loops))
on_stop(looped)
return
if(!chance || prob(chance))
play(get_sound(looped))
addtimer(CALLBACK(src, .proc/sound_loop, ++looped), mid_length)
/datum/looping_sound/proc/play(soundfile)
var/list/atoms_cache = output_atoms
var/sound/S = sound(soundfile)
if(direct)
S.channel = open_sound_channel()
S.volume = volume
for(var/i in 1 to atoms_cache.len)
var/atom/thing = atoms_cache[i]
if(direct)
SEND_SOUND(thing, S)
else
playsound(thing, S, volume)
/datum/looping_sound/proc/get_sound(looped, _mid_sounds)
if(!_mid_sounds)
. = mid_sounds
else
. = _mid_sounds
while(!isfile(.) && !isnull(.))
. = pickweight(.)
/datum/looping_sound/proc/on_start()
var/start_wait = 0
if(start_sound)
play(start_sound)
start_wait = start_length
addtimer(CALLBACK(src, .proc/sound_loop), start_wait)
/datum/looping_sound/proc/on_stop(looped)
if(end_sound)
play(end_sound)
@@ -0,0 +1,7 @@
/datum/looping_sound/showering
start_sound = 'sound/machines/shower/shower_start.ogg'
start_length = 2
mid_sounds = list('sound/machines/shower/shower_mid1.ogg' = 1,'sound/machines/shower/shower_mid2.ogg' = 1,'sound/machines/shower/shower_mid3.ogg' = 1)
mid_length = 10
end_sound = 'sound/machines/shower/shower_end.ogg'
volume = 20
+78 -40
View File
@@ -38,8 +38,8 @@
var/memory
var/assigned_role
var/special_role
var/assigned_role //assigned role is what job you're assigned to when you join the station.
var/special_role //special roles are typically reserved for antags or roles like ERT. If you want to avoid a character being automatically announced by the AI, on arrival (becuase they're an off station character or something); ensure that special_role and assigned_role are equal.
var/list/restricted_roles = list()
var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button.
@@ -54,6 +54,7 @@
var/has_been_rev = 0//Tracks if this mind has been a rev or not
var/miming = 0 // Mime's vow of silence
var/list/antag_datums
var/speech_span // What span any body this mind has talks in.
var/datum/faction/faction //associated faction
var/datum/changeling/changeling //changeling holder
@@ -72,17 +73,29 @@
var/brigged_since = -1
var/suicided = FALSE
New(var/key)
src.key = key
//put this here for easier tracking ingame
var/datum/money_account/initial_account
//zealot_master is a reference to the mob that converted them into a zealot (for ease of investigation and such)
var/mob/living/carbon/human/zealot_master = null
/datum/mind/New(var/key)
src.key = key
/datum/mind/Destroy()
ticker.minds -= src
if(islist(antag_datums))
for(var/i in antag_datums)
var/datum/antagonist/antag_datum = i
if(antag_datum.delete_on_mind_deletion)
qdel(i)
antag_datums = null
return ..()
/datum/mind/proc/transfer_to(mob/living/new_character)
var/datum/atom_hud/antag/hud_to_transfer = antag_hud //we need this because leave_hud() will clear this list
var/mob/living/old_current = current
if(!istype(new_character))
log_runtime(EXCEPTION("transfer_to(): Some idiot has tried to transfer_to() a non mob/living mob."), src)
if(current) //remove ourself from our old body's mind variable
@@ -95,6 +108,9 @@
new_character.mind.current = null
current = new_character //link ourself to our new body
new_character.mind = src //and link our new body to ourself
for(var/a in antag_datums) //Makes sure all antag datums effects are applied in the new body
var/datum/antagonist/A = a
A.on_body_transfer(old_current, current)
transfer_antag_huds(hud_to_transfer) //inherit the antag HUD
transfer_actions(new_character)
@@ -525,8 +541,8 @@
new_objective = new objective_path
new_objective.owner = src
new_objective:target = new_target:mind
//Will display as special role if the target is set as MODE. Ninjas/commandos/nuke ops.
new_objective.explanation_text = "[objective_type] [new_target:real_name], the [new_target:mind:assigned_role=="MODE" ? (new_target:mind:special_role) : (new_target:mind:assigned_role)]."
//Will display as special role if assigned mode is equal to special role.. Ninjas/commandos/nuke ops.
new_objective.explanation_text = "[objective_type] [new_target:real_name], the [new_target:mind:assigned_role == new_target:mind:special_role ? (new_target:mind:special_role) : (new_target:mind:assigned_role)]."
if("destroy")
var/list/possible_targets = active_ais(1)
@@ -726,7 +742,7 @@
if(src in ticker.mode.revolutionaries)
ticker.mode.revolutionaries -= src
ticker.mode.update_rev_icons_removed(src)
to_chat(current, "<span class='warning'>\red <FONT size = 3><B>You have proven your devotion to revolution! You are a head revolutionary now!</B></FONT></span>")
to_chat(current, "<span class='userdanger'>You have proven your devotion to revolution! You are a head revolutionary now!</span>")
else if(!(src in ticker.mode.head_revolutionaries))
to_chat(current, "<span class='notice'>You are a member of the revolutionaries' leadership now!</span>")
else
@@ -1211,37 +1227,60 @@
message_admins("[key_name_admin(usr)] has announced [key_name_admin(current)]'s objectives")
edit_memory()
/*
/datum/mind/proc/clear_memory(var/silent = 1)
var/datum/game_mode/current_mode = ticker.mode
// remove traitor uplinks
var/list/L = current.get_contents()
for(var/t in L)
if(istype(t, /obj/item/pda))
if(t:uplink) qdel(t:uplink)
t:uplink = null
else if(istype(t, /obj/item/radio))
if(t:traitorradio) qdel(t:traitorradio)
t:traitorradio = null
t:traitor_frequency = 0.0
else if(istype(t, /obj/item/SWF_uplink) || istype(t, /obj/item/syndicate_uplink))
if(t:origradio)
var/obj/item/radio/R = t:origradio
R.loc = current.loc
R.traitorradio = null
R.traitor_frequency = 0.0
qdel(t)
// remove wizards spells
//If there are more special powers that need removal, they can be procced into here./N
current.spellremove(current)
// Datum antag mind procs
/datum/mind/proc/add_antag_datum(datum_type_or_instance, team)
if(!datum_type_or_instance)
return
var/datum/antagonist/A
if(!ispath(datum_type_or_instance))
A = datum_type_or_instance
if(!istype(A))
return
else
A = new datum_type_or_instance()
//Choose snowflake variation if antagonist handles it
var/datum/antagonist/S = A.specialization(src)
if(S && S != A)
qdel(A)
A = S
if(!A.can_be_owned(src))
qdel(A)
return
A.owner = src
LAZYADD(antag_datums, A)
A.create_team(team)
var/datum/team/antag_team = A.get_team()
if(antag_team)
antag_team.add_member(src)
A.on_gain()
return A
// clear memory
memory = ""
special_role = null
/datum/mind/proc/remove_antag_datum(datum_type)
if(!datum_type)
return
var/datum/antagonist/A = has_antag_datum(datum_type)
if(A)
A.on_removal()
return TRUE
*/
/datum/mind/proc/remove_all_antag_datums() //For the Lazy amongst us.
for(var/a in antag_datums)
var/datum/antagonist/A = a
A.on_removal()
/datum/mind/proc/has_antag_datum(datum_type, check_subtypes = TRUE)
if(!datum_type)
return
. = FALSE
for(var/a in antag_datums)
var/datum/antagonist/A = a
if(check_subtypes && istype(A, datum_type))
return A
else if(A.type == datum_type)
return A
/datum/mind/proc/find_syndicate_uplink()
var/list/L = current.get_contents()
@@ -1273,7 +1312,7 @@
else
current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]"
special_role = SPECIAL_ROLE_NUKEOPS
assigned_role = "MODE"
assigned_role = SPECIAL_ROLE_NUKEOPS
to_chat(current, "<span class='notice'>You are a [syndicate_name()] agent!</span>")
ticker.mode.forge_syndicate_objectives(src)
ticker.mode.greet_syndicate(src)
@@ -1308,7 +1347,7 @@
if(!(src in ticker.mode.wizards))
ticker.mode.wizards += src
special_role = SPECIAL_ROLE_WIZARD
assigned_role = "MODE"
assigned_role = SPECIAL_ROLE_WIZARD
//ticker.mode.learn_basic_spells(current)
if(!wizardstart.len)
current.loc = pick(latejoin)
@@ -1514,7 +1553,7 @@
var/datum/objective/protect/mindslave/MS = new
MS.owner = src
MS.target = missionary.mind
MS.explanation_text = "Obey every order from and protect [missionary.real_name], the [missionary.mind.assigned_role=="MODE" ? (missionary.mind.special_role) : (missionary.mind.assigned_role)]."
MS.explanation_text = "Obey every order from and protect [missionary.real_name], the [missionary.mind.assigned_role == missionary.mind.special_role ? (missionary.mind.special_role) : (missionary.mind.assigned_role)]."
objectives += MS
for(var/datum/objective/objective in objectives)
to_chat(current, "<B>Objective #1</B>: [objective.explanation_text]")
@@ -1538,8 +1577,7 @@
H.update_inv_w_uniform(0,0)
add_attack_logs(missionary, current, "Converted to a zealot for [convert_duration/600] minutes")
addtimer(src, "remove_zealot", convert_duration, FALSE, jumpsuit) //deconverts after the timer expires
addtimer(CALLBACK(src, .proc/remove_zealot, jumpsuit), convert_duration) //deconverts after the timer expires
return 1
/datum/mind/proc/remove_zealot(obj/item/clothing/under/jumpsuit = null)
-63
View File
@@ -1,63 +0,0 @@
// module datum.
// this is per-object instance, and shows the condition of the modules in the object
// actual modules needed is referenced through modulestypes and the object type
/datum/module
var/status // bits set if working, 0 if broken
var/installed // bits set if installed, 0 if missing
// moduletypes datum
// this is per-object type, and shows the modules needed for a type of object
/datum/moduletypes
var/list/modcount = list() // assoc list of the count of modules for a type
var/list/modules = list( // global associative list
"/obj/machinery/power/apc" = "card_reader,power_control,id_auth,cell_power,cell_charge")
/datum/module/New(var/obj/O)
var/type = O.type // the type of the creating object
var/mneed = mods.inmodlist(type) // find if this type has modules defined
if(!mneed) // not found in module list?
qdel(src) // delete self, thus ending proc
return
var/needed = mods.getbitmask(type) // get a bitmask for the number of modules in this object
status = needed
installed = needed
/datum/moduletypes/proc/addmod(var/type, var/modtextlist)
modules += type // index by type text
modules[type] = modtextlist
/datum/moduletypes/proc/inmodlist(var/type)
return ("[type]" in modules)
/datum/moduletypes/proc/getbitmask(var/type)
var/count = modcount["[type]"]
if(count)
return 2**count-1
var/modtext = modules["[type]"]
var/num = 1
var/pos = 1
while(1)
pos = findtext(modtext, ",", pos, 0)
if(!pos)
break
else
pos++
num++
modcount += "[type]"
modcount["[type]"] = num
return 2**num-1
+29 -13
View File
@@ -145,6 +145,7 @@
belt = /obj/item/gun/projectile/automatic/pistol/deagle/camo
l_ear = /obj/item/radio/headset/syndicate/alt
l_pocket = /obj/item/pinpointer/advpinpointer
r_pocket = null // stop them getting a radio uplink, they get an implant instead
backpack_contents = list(
/obj/item/storage/box/engineer = 1,
@@ -158,7 +159,6 @@
id_icon = "commander"
id_access = "Syndicate Operative Leader"
uplink_uses = 500
/datum/outfit/admin/syndicate/officer/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
. = ..()
@@ -613,15 +613,16 @@
uniform = /obj/item/clothing/under/solgov/rep
back = /obj/item/storage/backpack/satchel
glasses = /obj/item/clothing/glasses/hud/security/night
gloves = /obj/item/clothing/gloves/color/white
shoes = /obj/item/clothing/shoes/centcom
l_ear = /obj/item/radio/headset
l_ear = /obj/item/radio/headset/ert
id = /obj/item/card/id/silver
r_pocket = /obj/item/lighter/zippo/blue
l_pocket = /obj/item/storage/fancy/cigarettes/cigpack_robustgold
pda = /obj/item/pda
backpack_contents = list(
/obj/item/storage/box/survival = 1,
/obj/item/storage/box/responseteam = 1,
/obj/item/implanter/dust = 1,
/obj/item/implanter/death_alarm = 1,
)
@@ -633,25 +634,33 @@
var/obj/item/card/id/I = H.wear_id
if(istype(I))
apply_to_card(I, H, get_centcom_access("VIP Guest"), "Solar Federation Representative")
apply_to_card(I, H, get_all_accesses(), name, "lifetimeid")
/datum/outfit/admin/solgov
name = "Solar Federation Marine"
uniform = /obj/item/clothing/under/solgov
suit = /obj/item/clothing/suit/armor/bulletproof
back = /obj/item/storage/backpack/security
belt = /obj/item/storage/belt/military/assault
head = /obj/item/clothing/head/soft/solgov
glasses = /obj/item/clothing/glasses/hud/security/night
gloves = /obj/item/clothing/gloves/combat
shoes = /obj/item/clothing/shoes/combat
l_ear = /obj/item/radio/headset/ert
id = /obj/item/card/id
l_hand = /obj/item/gun/projectile/automatic/ar
r_pocket = /obj/item/flashlight/seclite
pda = /obj/item/pda
backpack_contents = list(
/obj/item/storage/box/survival = 1,
/obj/item/kitchen/knife/combat = 1,
/obj/item/storage/box/responseteam = 1,
/obj/item/ammo_box/magazine/m556 = 3,
/obj/item/clothing/shoes/magboots = 1
/obj/item/clothing/shoes/magboots = 1,
/obj/item/gun/projectile/automatic/pistol/m1911 = 1,
/obj/item/ammo_box/magazine/m45 = 2
)
var/is_tsf_lieutenant = FALSE
/datum/outfit/admin/solgov/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
@@ -659,9 +668,14 @@
if(visualsOnly)
return
if(is_tsf_lieutenant)
H.real_name = "Lieutenant [pick(last_names)]"
else
H.real_name = "[pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant First Class", "Master Sergeant", "Sergeant Major")] [pick(last_names)]"
H.name = H.real_name
var/obj/item/card/id/I = H.wear_id
if(istype(I))
apply_to_card(I, H, get_centcom_access("VIP Guest"), name)
apply_to_card(I, H, get_all_accesses(), name, "lifetimeid")
/datum/outfit/admin/solgov/lieutenant
name = "Solar Federation Lieutenant"
@@ -670,14 +684,16 @@
head = /obj/item/clothing/head/soft/solgov/command
back = /obj/item/storage/backpack/satchel
l_hand = null
belt = /obj/item/gun/projectile/automatic/pistol/deagle
l_pocket = /obj/item/pinpointer/advpinpointer
backpack_contents = list(
/obj/item/storage/box/survival = 1,
/obj/item/kitchen/knife/combat = 1,
/obj/item/storage/box/responseteam = 1,
/obj/item/melee/classic_baton/telescopic = 1,
/obj/item/ammo_box/magazine/m50 = 2,
/obj/item/clothing/shoes/magboots/advance = 1
/obj/item/clothing/shoes/magboots/advance = 1,
/obj/item/gun/projectile/automatic/pistol/deagle = 1,
/obj/item/ammo_box/magazine/m50 = 2
)
is_tsf_lieutenant = TRUE
/datum/outfit/admin/chrono
name = "Chrono Legionnaire"
+2 -2
View File
@@ -10,6 +10,6 @@
/obj/effect/proc_holder/spell/targeted/emplosion/cast(list/targets, mob/user = usr)
for(var/mob/living/target in targets)
empulse(target.loc, emp_heavy, emp_light)
empulse(target.loc, emp_heavy, emp_light, 1)
return
return
+1 -1
View File
@@ -26,7 +26,7 @@
if(!target.can_safely_leave_loc()) // No more brainmobs hopping out of their brains
to_chat(target, "<span class='warning'>You are somehow too bound to your current location to abandon it.</span>")
continue
addtimer(src, "do_jaunt", 0, FALSE, target)
INVOKE_ASYNC(src, .proc/do_jaunt, target)
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/do_jaunt(mob/living/target)
target.notransform = 1
+7
View File
@@ -1336,6 +1336,13 @@ var/list/uplink_items = list()
item = /obj/item/storage/fancy/cigarettes/cigpack_syndicate
cost = 2
/datum/uplink_item/badass/rapid
name = "Gloves of the North Star"
desc = "These gloves let the user punch people very fast. Does not improve weapon attack speed."
reference = "RPGD"
item = /obj/item/clothing/gloves/fingerless/rapid
cost = 8
/datum/uplink_item/badass/bundle
name = "Syndicate Bundle"
desc = "Syndicate Bundles are specialised groups of items that arrive in a plain box. These items are collectively worth more than 20 telecrystals, but you do not know which specialisation you will receive."
+4 -4
View File
@@ -31,7 +31,7 @@
var/list/impacted_areas = list() //Areas to be affected by the weather, calculated when the weather begins
var/target_z = MAIN_STATION //The z-level to affect
var/list/protected_areas = list()//Areas that are protected and excluded from the affected areas.
var/overlay_layer = 10 //Since it's above everything else, this is the layer used by default. 2 is below mobs and walls if you need to use that.
var/aesthetic = FALSE //If the weather has no purpose other than looks
var/immunity_type = "storm" //Used by mobs to prevent them from being affected by the weather
@@ -70,7 +70,7 @@
to_chat(M, telegraph_message)
if(telegraph_sound)
M << sound(telegraph_sound)
addtimer(src, "start", telegraph_duration)
addtimer(CALLBACK(src, .proc/start), telegraph_duration)
/datum/weather/proc/start()
if(stage >= MAIN_STAGE)
@@ -85,7 +85,7 @@
if(weather_sound)
M << sound(weather_sound)
weather_master.processing_weather |= src
addtimer(src, "wind_down", weather_duration)
addtimer(CALLBACK(src, .proc/wind_down), weather_duration)
/datum/weather/proc/wind_down()
if(stage >= WIND_DOWN_STAGE)
@@ -100,7 +100,7 @@
if(end_sound)
M << sound(end_sound)
weather_master.processing_weather -= src
addtimer(src, "end", end_duration)
addtimer(CALLBACK(src, .proc/end), end_duration)
/datum/weather/proc/end()
if(stage == END_STAGE)