Merge remote-tracking branch 'refs/remotes/Citadel-Station-13/master' into crewobjectivesandmiscreants
This commit is contained in:
@@ -132,5 +132,6 @@
|
||||
#define NOLIVER 29
|
||||
#define NOSTOMACH 30
|
||||
//citadel code
|
||||
#define NOAROUSAL 29//Stops all arousal effects
|
||||
#define NOGENITALS 30//Cannot create, use, or otherwise have genitals
|
||||
#define NOAROUSAL 29 //Stops all arousal effects
|
||||
#define NOGENITALS 30 //Cannot create, use, or otherwise have genitals
|
||||
#define NO_DNA_COPY 31
|
||||
|
||||
@@ -18,3 +18,7 @@
|
||||
#define ANTAG_DATUM_IAA_HUMAN_CUSTOM /datum/antagonist/traitor/human/internal_affairs/custom
|
||||
#define ANTAG_DATUM_IAA_AI_CUSTOM /datum/antagonist/traitor/AI/internal_affairs/custom
|
||||
#define ANTAG_DATUM_IAA_AI /datum/antagonist/traitor/AI/internal_affairs
|
||||
#define ANTAG_DATUM_BROTHER /datum/antagonist/brother
|
||||
#define ANTAG_DATUM_ABDUCTOR /datum/antagonist/abductor
|
||||
#define ANTAG_DATUM_ABDUCTOR_SCIENTIST /datum/antagonist/abductor/scientist
|
||||
#define ANTAG_DATUM_ABDUCTOR_AGENT /datum/antagonist/abductor/agent
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#define ANTAG_HUD_SOULLESS 17
|
||||
#define ANTAG_HUD_CLOCKWORK 18
|
||||
#define ANTAG_HUD_BORER 19
|
||||
#define ANTAG_HUD_BROTHER 20
|
||||
|
||||
// Notification action types
|
||||
#define NOTIFY_JUMP "jump"
|
||||
|
||||
@@ -11,14 +11,56 @@
|
||||
// All signals. Format:
|
||||
// When the signal is called: (signal arguments)
|
||||
|
||||
#define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (datum/component)
|
||||
#define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (datum/component)
|
||||
// /datum signals
|
||||
#define COMSIG_COMPONENT_ADDED "component_added" //when a component is added to a datum: (/datum/component)
|
||||
#define COMSIG_COMPONENT_REMOVING "component_removing" //before a component is removed from a datum because of RemoveComponent: (/datum/component)
|
||||
#define COMSIG_PARENT_QDELETED "parent_qdeleted" //before a datum's Destroy() is called: ()
|
||||
#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable, atom)
|
||||
#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (atom/movable)
|
||||
#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from the base of atom/attackby: (obj/item, mob/living, params)
|
||||
#define COMSIG_PARENT_EXAMINE "atom_examine" //from the base of atom/examine: (mob)
|
||||
#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable, atom)
|
||||
|
||||
// /atom signals
|
||||
#define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params)
|
||||
#define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human)
|
||||
#define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (/mob)
|
||||
#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (/atom/movable, /atom)
|
||||
#define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target)
|
||||
#define COMSIG_ATOM_EMP_ACT "atom_emp_act" //from base of atom/emp_act(): (severity)
|
||||
#define COMSIG_ATOM_FIRE_ACT "atom_fire_act" //from base of atom/fire_act(): (exposed_temperature, exposed_volume)
|
||||
#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" //from base of atom/bullet_act(): (/obj/item/projectile, def_zone)
|
||||
#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" //from base of atom/blob_act(): (/obj/structure/blob)
|
||||
#define COMSIG_ATOM_ACID_ACT "atom_acid_act" //from base of atom/acid_act(): (acidpwr, acid_volume)
|
||||
#define COMSIG_ATOM_EMAG_ACT "atom_emag_act" //from base of atom/emag_act(): ()
|
||||
#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act" //from base of atom/narsie_act(): ()
|
||||
#define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act" //from base of atom/ratvar_act(): ()
|
||||
#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" //from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode)
|
||||
#define COMSIG_ATOM_SING_PULL "atom_sing_pull" //from base of atom/singularity_pull(): (S, current_size)
|
||||
#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (atom/movable)
|
||||
|
||||
#define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params)
|
||||
#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob)
|
||||
#define COMSIG_CLICK_CTRL "ctrl_click" //from base of atom/CtrlClickOn(): (/mob)
|
||||
#define COMSIG_CLICK_ALT "alt_click" //from base of atom/AltClick(): (/mob)
|
||||
#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click" //from base of atom/CtrlShiftClick(/mob)
|
||||
|
||||
// /atom/movable signals
|
||||
#define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir)
|
||||
#define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable)
|
||||
#define COMSIG_MOVABLE_COLLIDE "movable_collide" //from base of atom/movable/Collide(): (/atom)
|
||||
#define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (/atom, throwingdatum)
|
||||
|
||||
// /obj/item signals
|
||||
#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
|
||||
#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob)
|
||||
#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob)
|
||||
|
||||
// /obj/item/clothing signals
|
||||
#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): ()
|
||||
|
||||
// /obj/item signals
|
||||
#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (mob/living/target, mob/living/user)
|
||||
#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (mob)
|
||||
#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (obj, mob)
|
||||
|
||||
// /obj/item/clothing signals
|
||||
#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): ()
|
||||
|
||||
// /obj/machinery signals
|
||||
#define COMSIG_MACHINE_PROCESS "machine_process" //from machinery subsystem fire(): ()
|
||||
#define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): ()
|
||||
|
||||
@@ -162,3 +162,11 @@ GLOBAL_LIST_INIT(pointed_types, typecacheof(list(
|
||||
#define issignaler(O) (istype(O, /obj/item/device/assembly/signaler))
|
||||
|
||||
#define istimer(O) (istype(O, /obj/item/device/assembly/timer))
|
||||
|
||||
GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
|
||||
/obj/item/stack/sheet/glass,
|
||||
/obj/item/stack/sheet/rglass,
|
||||
/obj/item/stack/sheet/plasmaglass,
|
||||
/obj/item/stack/sheet/plasmarglass)))
|
||||
|
||||
#define is_glass_sheet(O) (is_type_in_typecache(O, GLOB.glass_sheet_types))
|
||||
|
||||
@@ -456,3 +456,7 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
|
||||
#define SECURITY_SAFE 1
|
||||
#define SECURITY_ULTRASAFE 2
|
||||
#define SECURITY_TRUSTED 3
|
||||
|
||||
//Dummy mob reserve slots
|
||||
#define DUMMY_HUMAN_SLOT_PREFERENCES "dummy_preference_preview"
|
||||
#define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation"
|
||||
|
||||
@@ -12,6 +12,7 @@ Construction breaks otherwise
|
||||
#define PIPE_HE_MANIFOLD /obj/machinery/atmospherics/pipe/heat_exchanging/manifold
|
||||
#define PIPE_HE_4WAYMANIFOLD /obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w
|
||||
#define PIPE_JUNCTION /obj/machinery/atmospherics/pipe/heat_exchanging/junction
|
||||
#define PIPE_BLUESPACE /obj/machinery/atmospherics/pipe/bluespace
|
||||
//Unary
|
||||
#define PIPE_CONNECTOR /obj/machinery/atmospherics/components/unary/portables_connector
|
||||
#define PIPE_UVENT /obj/machinery/atmospherics/components/unary/vent_pump
|
||||
@@ -56,4 +57,4 @@ Construction breaks otherwise
|
||||
#define STATION_TUBE_OPEN 0
|
||||
#define STATION_TUBE_OPENING 1
|
||||
#define STATION_TUBE_CLOSED 2
|
||||
#define STATION_TUBE_CLOSING 3
|
||||
#define STATION_TUBE_CLOSING 3
|
||||
|
||||
@@ -23,12 +23,14 @@
|
||||
#define ROLE_DEVIL "devil"
|
||||
#define ROLE_SERVANT_OF_RATVAR "servant of Ratvar"
|
||||
#define ROLE_BORER "borer"
|
||||
#define ROLE_BROTHER "blood brother"
|
||||
|
||||
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
|
||||
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
|
||||
//(in game days played) to play that role
|
||||
GLOBAL_LIST_INIT(special_roles, list(
|
||||
ROLE_TRAITOR = /datum/game_mode/traitor,
|
||||
ROLE_BROTHER = /datum/game_mode/traitor/bros,
|
||||
ROLE_OPERATIVE = /datum/game_mode/nuclear,
|
||||
ROLE_CHANGELING = /datum/game_mode/changeling,
|
||||
ROLE_WIZARD = /datum/game_mode/wizard,
|
||||
@@ -50,4 +52,4 @@ GLOBAL_LIST_INIT(special_roles, list(
|
||||
//Job defines for what happens when you fail to qualify for any job during job selection
|
||||
#define BEASSISTANT 1
|
||||
#define BERANDOMJOB 2
|
||||
#define RETURNTOLOBBY 3
|
||||
#define RETURNTOLOBBY 3
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#define DM_DIGEST "Digest"
|
||||
#define DM_HEAL "Heal"
|
||||
#define DM_NOISY "Noisy"
|
||||
#define DM_DRAGON "Dragon"
|
||||
|
||||
#define VORE_STRUGGLE_EMOTE_CHANCE 40
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
|
||||
/proc/log_pda(text)
|
||||
if (config.log_pda)
|
||||
WRITE_FILE(GLOB.world_game_log, "\[[time_stamp()]]PDA: [text]")
|
||||
WRITE_FILE(GLOB.world_pda_log, "\[[time_stamp()]]PDA: [text]")
|
||||
|
||||
/proc/log_comment(text)
|
||||
if (config.log_pda)
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
/client/proc/file_spam_check()
|
||||
var/time_to_wait = GLOB.fileaccess_timer - world.time
|
||||
if(time_to_wait > 0)
|
||||
to_chat(src, "<font color='red'>Error: file_spam_check(): Spam. Please wait [round(time_to_wait/10)] seconds.</font>")
|
||||
to_chat(src, "<font color='red'>Error: file_spam_check(): Spam. Please wait [DisplayTimeText(time_to_wait)].</font>")
|
||||
return 1
|
||||
GLOB.fileaccess_timer = world.time + FTPDELAY
|
||||
return 0
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
SEND_SOUND(M, 'sound/misc/notice2.ogg') //Alerting them to their consideration
|
||||
if(flashwindow)
|
||||
window_flash(M.client)
|
||||
switch(ignore_category ? askuser(M,Question,"Please answer in [poll_time/10] seconds!","Yes","No","Never for this round", StealFocus=0, Timeout=poll_time) : askuser(M,Question,"Please answer in [poll_time/10] seconds!","Yes","No", StealFocus=0, Timeout=poll_time))
|
||||
switch(ignore_category ? askuser(M,Question,"Please answer in [DisplayTimeText(poll_time)]!","Yes","No","Never for this round", StealFocus=0, Timeout=poll_time) : askuser(M,Question,"Please answer in [DisplayTimeText(poll_time)]!","Yes","No", StealFocus=0, Timeout=poll_time))
|
||||
if(1)
|
||||
to_chat(M, "<span class='notice'>Choice registered: Yes.</span>")
|
||||
if(time_passed + poll_time <= world.time)
|
||||
|
||||
@@ -926,10 +926,10 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)
|
||||
return 0
|
||||
|
||||
//For creating consistent icons for human looking simple animals
|
||||
/proc/get_flat_human_icon(icon_id, datum/job/J, datum/preferences/prefs)
|
||||
/proc/get_flat_human_icon(icon_id, datum/job/J, datum/preferences/prefs, dummy_key)
|
||||
var/static/list/humanoid_icon_cache = list()
|
||||
if(!icon_id || !humanoid_icon_cache[icon_id])
|
||||
var/mob/living/carbon/human/dummy/body = new()
|
||||
var/mob/living/carbon/human/dummy/body = generate_or_wait_for_human_dummy(dummy_key)
|
||||
|
||||
if(prefs)
|
||||
prefs.copy_to(body)
|
||||
@@ -956,14 +956,12 @@ GLOBAL_LIST_EMPTY(friendly_animal_types)
|
||||
partial = getFlatIcon(body)
|
||||
out_icon.Insert(partial,dir=EAST)
|
||||
|
||||
qdel(body)
|
||||
|
||||
humanoid_icon_cache[icon_id] = out_icon
|
||||
dummy_key? unset_busy_human_dummy(dummy_key) : qdel(body)
|
||||
return out_icon
|
||||
else
|
||||
return humanoid_icon_cache[icon_id]
|
||||
|
||||
|
||||
//Hook, override to run code on- wait this is images
|
||||
//Images have dir without being an atom, so they get their own definition.
|
||||
//Lame.
|
||||
|
||||
@@ -155,7 +155,6 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,
|
||||
var/size_factor = ((-cos(inputToDegrees) +1) /2) //returns a value from 0 to 1
|
||||
|
||||
return size_factor + scaling_modifier //scale mod of 0 results in a number from 0 to 1. A scale modifier of +0.5 returns 0.5 to 1.5
|
||||
//to_chat(world, "Transform multiplier of [src] is [size_factor + scaling_modifer]")
|
||||
|
||||
//converts a uniform distributed random number into a normal distributed one
|
||||
//since this method produces two random numbers, one is saved for subsequent calls
|
||||
@@ -220,3 +219,8 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,
|
||||
new_x = Clamp(new_x, 0, world.maxx)
|
||||
new_y = Clamp(new_y, 0, world.maxy)
|
||||
return locate(new_x, new_y, starting.z)
|
||||
|
||||
/proc/round_down(num)
|
||||
if(round(num) != num)
|
||||
return round(num--)
|
||||
else return num
|
||||
|
||||
@@ -465,13 +465,17 @@ Proc for attack log creation, because really why not
|
||||
if(H.dna && istype(H.dna.species, species_datum))
|
||||
. = TRUE
|
||||
|
||||
/proc/spawn_atom_to_turf(spawn_type, target, amount, admin_spawn=FALSE)
|
||||
/proc/spawn_atom_to_turf(spawn_type, target, amount, admin_spawn=FALSE, list/extra_args)
|
||||
var/turf/T = get_turf(target)
|
||||
if(!T)
|
||||
CRASH("attempt to spawn atom type: [spawn_type] in nullspace")
|
||||
|
||||
for(var/j in 1 to amount)
|
||||
var/atom/X = new spawn_type(T)
|
||||
var/list/new_args = list(T)
|
||||
if(extra_args)
|
||||
new_args += extra_args
|
||||
|
||||
for(var/j in 1 to amount)
|
||||
var/atom/X = new spawn_type(arglist(new_args))
|
||||
X.admin_spawned = admin_spawn
|
||||
|
||||
/proc/spawn_and_random_walk(spawn_type, target, amount, walk_chance=100, max_walk=3, always_max_walk=FALSE, admin_spawn=FALSE)
|
||||
|
||||
+148
-52
@@ -1,52 +1,148 @@
|
||||
//Returns the world time in english
|
||||
/proc/worldtime2text()
|
||||
return gameTimestamp("hh:mm:ss", world.time)
|
||||
|
||||
/proc/time_stamp(format = "hh:mm:ss", show_ds)
|
||||
var/time_string = time2text(world.timeofday, format)
|
||||
return show_ds ? "[time_string]:[world.timeofday % 10]" : time_string
|
||||
|
||||
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
|
||||
if(!wtime)
|
||||
wtime = world.time
|
||||
return time2text(wtime - GLOB.timezoneOffset + SSticker.gametime_offset - SSticker.round_start_time, format)
|
||||
|
||||
/* Returns 1 if it is the selected month and day */
|
||||
/proc/isDay(month, day)
|
||||
if(isnum(month) && isnum(day))
|
||||
var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
|
||||
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
|
||||
if(month == MM && day == DD)
|
||||
return 1
|
||||
|
||||
// Uncomment this out when debugging!
|
||||
//else
|
||||
//return 1
|
||||
|
||||
//returns timestamp in a sql and ISO 8601 friendly format
|
||||
/proc/SQLtime(timevar)
|
||||
if(!timevar)
|
||||
timevar = world.realtime
|
||||
return time2text(timevar, "YYYY-MM-DD hh:mm:ss")
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(midnight_rollovers, 0)
|
||||
GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
|
||||
/proc/update_midnight_rollover()
|
||||
if (world.timeofday < GLOB.rollovercheck_last_timeofday) //TIME IS GOING BACKWARDS!
|
||||
return GLOB.midnight_rollovers++
|
||||
return GLOB.midnight_rollovers
|
||||
|
||||
/proc/weekdayofthemonth()
|
||||
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
|
||||
switch(DD)
|
||||
if(8 to 13)
|
||||
return 2
|
||||
if(14 to 20)
|
||||
return 3
|
||||
if(21 to 27)
|
||||
return 4
|
||||
if(28 to INFINITY)
|
||||
return 5
|
||||
else
|
||||
return 1
|
||||
//Returns the world time in english
|
||||
/proc/worldtime2text()
|
||||
return gameTimestamp("hh:mm:ss", world.time)
|
||||
|
||||
/proc/time_stamp(format = "hh:mm:ss", show_ds)
|
||||
var/time_string = time2text(world.timeofday, format)
|
||||
return show_ds ? "[time_string]:[world.timeofday % 10]" : time_string
|
||||
|
||||
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
|
||||
if(!wtime)
|
||||
wtime = world.time
|
||||
return time2text(wtime - GLOB.timezoneOffset + SSticker.gametime_offset - SSticker.round_start_time, format)
|
||||
|
||||
/* Returns 1 if it is the selected month and day */
|
||||
/proc/isDay(month, day)
|
||||
if(isnum(month) && isnum(day))
|
||||
var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
|
||||
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
|
||||
if(month == MM && day == DD)
|
||||
return 1
|
||||
|
||||
// Uncomment this out when debugging!
|
||||
//else
|
||||
//return 1
|
||||
|
||||
//returns timestamp in a sql and ISO 8601 friendly format
|
||||
/proc/SQLtime(timevar)
|
||||
if(!timevar)
|
||||
timevar = world.realtime
|
||||
return time2text(timevar, "YYYY-MM-DD hh:mm:ss")
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(midnight_rollovers, 0)
|
||||
GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
|
||||
/proc/update_midnight_rollover()
|
||||
if (world.timeofday < GLOB.rollovercheck_last_timeofday) //TIME IS GOING BACKWARDS!
|
||||
return GLOB.midnight_rollovers++
|
||||
return GLOB.midnight_rollovers
|
||||
|
||||
/proc/weekdayofthemonth()
|
||||
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
|
||||
switch(DD)
|
||||
if(8 to 13)
|
||||
return 2
|
||||
if(14 to 20)
|
||||
return 3
|
||||
if(21 to 27)
|
||||
return 4
|
||||
if(28 to INFINITY)
|
||||
return 5
|
||||
else
|
||||
return 1
|
||||
|
||||
//Takes a value of time in deciseconds.
|
||||
//Returns a text value of that number in hours, minutes, or seconds.
|
||||
/proc/DisplayTimeText(time_value)
|
||||
var/second = time_value*0.1
|
||||
var/second_adjusted = null
|
||||
var/second_rounded = FALSE
|
||||
var/minute = null
|
||||
var/hour = null
|
||||
var/day = null
|
||||
|
||||
if(!second)
|
||||
return "0 seconds"
|
||||
if(second >= 60)
|
||||
minute = round_down(second/60)
|
||||
second = round(second - (minute*60), 0.1)
|
||||
second_rounded = TRUE
|
||||
if(second) //check if we still have seconds remaining to format, or if everything went into minute.
|
||||
second_adjusted = round(second) //used to prevent '1 seconds' being shown
|
||||
if(day || hour || minute)
|
||||
if(second_adjusted == 1 && second >= 1)
|
||||
second = " and 1 second"
|
||||
else if(second > 1)
|
||||
second = " and [second_adjusted] seconds"
|
||||
else //shows a fraction if seconds is < 1
|
||||
if(second_rounded) //no sense rounding again if it's already done
|
||||
second = " and [second] seconds"
|
||||
else
|
||||
second = " and [round(second, 0.1)] seconds"
|
||||
else
|
||||
if(second_adjusted == 1 && second >= 1)
|
||||
second = "1 second"
|
||||
else if(second > 1)
|
||||
second = "[second_adjusted] seconds"
|
||||
else
|
||||
if(second_rounded)
|
||||
second = "[second] seconds"
|
||||
else
|
||||
second = "[round(second, 0.1)] seconds"
|
||||
else
|
||||
second = null
|
||||
|
||||
if(!minute)
|
||||
return "[second]"
|
||||
if(minute >= 60)
|
||||
hour = round_down(minute/60,1)
|
||||
minute = (minute - (hour*60))
|
||||
if(minute) //alot simpler from here since you don't have to worry about fractions
|
||||
if(minute != 1)
|
||||
if((day || hour) && second)
|
||||
minute = ", [minute] minutes"
|
||||
else if((day || hour) && !second)
|
||||
minute = " and [minute] minutes"
|
||||
else
|
||||
minute = "[minute] minutes"
|
||||
else
|
||||
if((day || hour) && second)
|
||||
minute = ", 1 minute"
|
||||
else if((day || hour) && !second)
|
||||
minute = " and 1 minute"
|
||||
else
|
||||
minute = "1 minute"
|
||||
else
|
||||
minute = null
|
||||
|
||||
if(!hour)
|
||||
return "[minute][second]"
|
||||
if(hour >= 24)
|
||||
day = round_down(hour/24,1)
|
||||
hour = (hour - (day*24))
|
||||
if(hour)
|
||||
if(hour != 1)
|
||||
if(day && (minute || second))
|
||||
hour = ", [hour] hours"
|
||||
else if(day && (!minute || !second))
|
||||
hour = " and [hour] hours"
|
||||
else
|
||||
hour = "[hour] hours"
|
||||
else
|
||||
if(day && (minute || second))
|
||||
hour = ", 1 hour"
|
||||
else if(day && (!minute || !second))
|
||||
hour = " and 1 hour"
|
||||
else
|
||||
hour = "1 hour"
|
||||
else
|
||||
hour = null
|
||||
|
||||
if(!day)
|
||||
return "[hour][minute][second]"
|
||||
if(day > 1)
|
||||
day = "[day] days"
|
||||
else
|
||||
day = "1 day"
|
||||
|
||||
return "[day][hour][minute][second]"
|
||||
|
||||
@@ -812,7 +812,7 @@ GLOBAL_LIST_INIT(can_embed_types, typecacheof(list(
|
||||
|
||||
|
||||
/*
|
||||
Checks if that loc and dir has a item on the wall
|
||||
Checks if that loc and dir has an item on the wall
|
||||
*/
|
||||
GLOBAL_LIST_INIT(WALLITEMS, typecacheof(list(
|
||||
/obj/machinery/power/apc, /obj/machinery/airalarm, /obj/item/device/radio/intercom,
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
diff a/code/_compile_options.dm b/code/_compile_options.dm (rejected hunks)
|
||||
@@ -69,7 +69,7 @@
|
||||
#error You need version 511 or higher
|
||||
#endif
|
||||
|
||||
-//Update this whenever the db schema changes
|
||||
+//Update this whenever the db schema changes
|
||||
//make sure you add an update to the schema_version stable in the db changelog
|
||||
#define DB_MAJOR_VERSION 3
|
||||
-#define DB_MINOR_VERSION 2
|
||||
+#define DB_MINOR_VERSION 3
|
||||
@@ -20,6 +20,7 @@ GLOBAL_LIST_EMPTY(ai_list)
|
||||
GLOBAL_LIST_EMPTY(pai_list)
|
||||
GLOBAL_LIST_EMPTY(available_ai_shells)
|
||||
GLOBAL_LIST_EMPTY(simple_animals)
|
||||
GLOBAL_LIST_EMPTY(spidermobs) //all sentient spider mobs
|
||||
|
||||
GLOBAL_LIST_EMPTY(language_datum_instances)
|
||||
GLOBAL_LIST_EMPTY(all_languages)
|
||||
|
||||
@@ -16,6 +16,8 @@ GLOBAL_VAR(config_error_log)
|
||||
GLOBAL_PROTECT(config_error_log)
|
||||
GLOBAL_VAR(sql_error_log)
|
||||
GLOBAL_PROTECT(sql_error_log)
|
||||
GLOBAL_VAR(world_pda_log)
|
||||
GLOBAL_PROTECT(world_pda_log)
|
||||
|
||||
GLOBAL_LIST_EMPTY(bombers)
|
||||
GLOBAL_PROTECT(bombers)
|
||||
|
||||
+3
-2
@@ -14,7 +14,8 @@
|
||||
if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
|
||||
return
|
||||
|
||||
if(control_disabled || stat) return
|
||||
if(control_disabled || incapacitated())
|
||||
return
|
||||
|
||||
if(ismob(A))
|
||||
ai_actual_track(A)
|
||||
@@ -31,7 +32,7 @@
|
||||
if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
|
||||
return
|
||||
|
||||
if(control_disabled || stat)
|
||||
if(control_disabled || incapacitated())
|
||||
return
|
||||
|
||||
var/turf/pixel_turf = get_turf_pixel(A)
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
*/
|
||||
/atom/Click(location,control,params)
|
||||
if(initialized)
|
||||
SendSignal(COMSIG_CLICK, location, control, params)
|
||||
usr.ClickOn(src, params)
|
||||
|
||||
/atom/DblClick(location,control,params)
|
||||
@@ -305,6 +306,7 @@
|
||||
A.ShiftClick(src)
|
||||
return
|
||||
/atom/proc/ShiftClick(mob/user)
|
||||
SendSignal(COMSIG_CLICK_SHIFT, user)
|
||||
if(user.client && user.client.eye == user || user.client.eye == user.loc)
|
||||
user.examinate(src)
|
||||
return
|
||||
@@ -319,6 +321,7 @@
|
||||
return
|
||||
|
||||
/atom/proc/CtrlClick(mob/user)
|
||||
SendSignal(COMSIG_CLICK_CTRL, user)
|
||||
var/mob/living/ML = user
|
||||
if(istype(ML))
|
||||
ML.pulled(src)
|
||||
@@ -348,6 +351,7 @@
|
||||
..()
|
||||
|
||||
/atom/proc/AltClick(mob/user)
|
||||
SendSignal(COMSIG_CLICK_ALT, user)
|
||||
var/turf/T = get_turf(src)
|
||||
if(T && user.TurfAdjacent(T))
|
||||
if(user.listed_turf == T)
|
||||
@@ -373,6 +377,7 @@
|
||||
return
|
||||
|
||||
/atom/proc/CtrlShiftClick(mob/user)
|
||||
SendSignal(COMSIG_CLICK_CTRL_SHIFT)
|
||||
return
|
||||
|
||||
/*
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
|
||||
|
||||
/obj/screen/movable/action_button/hide_toggle/proc/InitialiseIcon(datum/hud/owner_hud)
|
||||
var settings = owner_hud.get_action_buttons_icons()
|
||||
var/settings = owner_hud.get_action_buttons_icons()
|
||||
icon = settings["bg_icon"]
|
||||
icon_state = settings["bg_state"]
|
||||
hide_icon = settings["toggle_icon"]
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
icon = 'icons/mob/screen_ai.dmi'
|
||||
|
||||
/obj/screen/ai/Click()
|
||||
if(isobserver(usr))
|
||||
return 1
|
||||
if(isobserver(usr) || usr.incapacitated())
|
||||
return TRUE
|
||||
|
||||
/obj/screen/ai/aicore
|
||||
name = "AI core"
|
||||
@@ -20,6 +20,8 @@
|
||||
icon_state = "camera"
|
||||
|
||||
/obj/screen/ai/camera_list/Click()
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
var/camera = input(AI, "Choose which camera you want to view", "Cameras") as null|anything in AI.get_camera_list()
|
||||
AI.ai_camera_list(camera)
|
||||
@@ -130,6 +132,8 @@
|
||||
icon_state = "take_picture"
|
||||
|
||||
/obj/screen/ai/image_take/Click()
|
||||
if(..())
|
||||
return
|
||||
if(isAI(usr))
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
AI.aicamera.toggle_camera_mode()
|
||||
@@ -142,6 +146,8 @@
|
||||
icon_state = "view_images"
|
||||
|
||||
/obj/screen/ai/image_view/Click()
|
||||
if(..())
|
||||
return
|
||||
if(isAI(usr))
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
AI.aicamera.viewpictures()
|
||||
|
||||
@@ -242,9 +242,12 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
|
||||
icon_state = "fire"
|
||||
|
||||
/obj/screen/alert/fire/Click()
|
||||
if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
return L.resist()
|
||||
var/mob/living/L = usr
|
||||
if(!L.can_resist())
|
||||
return
|
||||
L.changeNext_move(CLICK_CD_RESIST)
|
||||
if(L.canmove)
|
||||
return L.resist_fire() //I just want to start a flame in your hearrrrrrtttttt.
|
||||
|
||||
|
||||
//ALIENS
|
||||
@@ -644,9 +647,20 @@ so as to remain in compliance with the most up-to-date laws."
|
||||
desc = "You're legcuffed, which slows you down considerably. Click the alert to free yourself."
|
||||
|
||||
/obj/screen/alert/restrained/Click()
|
||||
if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
return L.resist()
|
||||
var/mob/living/L = usr
|
||||
if(!L.can_resist())
|
||||
return
|
||||
L.changeNext_move(CLICK_CD_RESIST)
|
||||
if((L.canmove) && (L.last_special <= world.time))
|
||||
return L.resist_restraints()
|
||||
|
||||
/obj/screen/alert/restrained/buckled/Click()
|
||||
var/mob/living/L = usr
|
||||
if(!L.can_resist())
|
||||
return
|
||||
L.changeNext_move(CLICK_CD_RESIST)
|
||||
if(L.last_special <= world.time)
|
||||
return L.resist_buckle()
|
||||
|
||||
// PRIVATE = only edit, use, or override these if you're editing the system as a whole
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
/obj/screen/swarmer/Replicate
|
||||
icon_state = "ui_replicate"
|
||||
name = "Replicate (Costs 50 Resources)"
|
||||
desc = "Creates a another of our kind."
|
||||
desc = "Creates another of our kind."
|
||||
|
||||
/obj/screen/swarmer/Replicate/Click()
|
||||
if(isswarmer(usr))
|
||||
|
||||
@@ -9,17 +9,18 @@
|
||||
|
||||
// Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown.
|
||||
/obj/item/proc/attack_self(mob/user)
|
||||
return
|
||||
SendSignal(COMSIG_ITEM_ATTACK_SELF, user)
|
||||
interact(user)
|
||||
|
||||
/obj/item/proc/pre_attackby(atom/A, mob/living/user, params) //do stuff before attackby!
|
||||
return TRUE //return FALSE to avoid calling attackby after this proc does stuff
|
||||
|
||||
// No comment
|
||||
/atom/proc/attackby(obj/item/W, mob/user, params)
|
||||
return
|
||||
return SendSignal(COMSIG_PARENT_ATTACKBY, W, user, params)
|
||||
|
||||
/obj/attackby(obj/item/I, mob/living/user, params)
|
||||
return I.attack_obj(src, user)
|
||||
return ..() || I.attack_obj(src, user)
|
||||
|
||||
/mob/living/attackby(obj/item/I, mob/living/user, params)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
@@ -35,6 +36,7 @@
|
||||
|
||||
|
||||
/obj/item/proc/attack(mob/living/M, mob/living/user)
|
||||
SendSignal(COMSIG_ITEM_ATTACK, M, user)
|
||||
if(flags_1 & NOBLUDGEON_1)
|
||||
return
|
||||
if(!force)
|
||||
@@ -54,6 +56,7 @@
|
||||
|
||||
//the equivalent of the standard version of attack() but for object targets.
|
||||
/obj/item/proc/attack_obj(obj/O, mob/living/user)
|
||||
SendSignal(COMSIG_ITEM_ATTACK_OBJ, O, user)
|
||||
if(flags_1 & NOBLUDGEON_1)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
|
||||
+313
-1
@@ -26,4 +26,316 @@
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_GOLD = 2500, MAT_METAL = 5000, MAT_GLASS = 5000)
|
||||
build_path = /obj/item/gun/energy/laser/carbine/nopin
|
||||
category = list("Weapons")
|
||||
category = list("Weapons")
|
||||
|
||||
////////////Anti Tank Pistol////////////
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/antitank
|
||||
name = "Anti Tank Pistol"
|
||||
desc = "A massively impractical and silly monstrosity of a pistol that fires .50 calliber rounds. The recoil is likely to dislocate your wrist."
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "atp"
|
||||
item_state = "pistol"
|
||||
recoil = 6
|
||||
mag_type = /obj/item/ammo_box/magazine/sniper_rounds
|
||||
fire_delay = 50
|
||||
burst_size = 1
|
||||
origin_tech = "combat=7"
|
||||
can_suppress = 0
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
actions_types = list()
|
||||
fire_sound = 'sound/weapons/blastcannon.ogg'
|
||||
spread = 30 //damn thing has no rifling.
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/antitank/update_icon()
|
||||
..()
|
||||
if(magazine)
|
||||
cut_overlays()
|
||||
add_overlay("atp-mag")
|
||||
else
|
||||
cut_overlays()
|
||||
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/antitank/syndicate
|
||||
name = "Syndicate Anti Tank Pistol"
|
||||
desc = "A massively impractical and silly monstrosity of a pistol that fires .50 calliber rounds. The recoil is likely to dislocate a variety of joints without proper bracing."
|
||||
pin = /obj/item/device/firing_pin/implant/pindicate
|
||||
origin_tech = "combat=7;syndicate=6"
|
||||
|
||||
/////////////spinfusor stuff////////////////
|
||||
|
||||
/obj/item/projectile/bullet/spinfusor
|
||||
name ="spinfusor disk"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state= "spinner"
|
||||
damage = 30
|
||||
dismemberment = 25
|
||||
|
||||
/obj/item/projectile/bullet/spinfusor/on_hit(atom/target, blocked = FALSE) //explosion to emulate the spinfusor's AOE
|
||||
..()
|
||||
explosion(target, -1, -1, 2, 0, -1)
|
||||
return 1
|
||||
|
||||
/obj/item/ammo_casing/caseless/spinfusor
|
||||
name = "spinfusor disk"
|
||||
desc = "A magnetic disk designed specifically for the Stormhammer magnetic cannon. Warning: extremely volatile!"
|
||||
projectile_type = /obj/item/projectile/bullet/spinfusor
|
||||
caliber = "spinfusor"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "disk"
|
||||
throwforce = 15 //still deadly when thrown
|
||||
throw_speed = 3
|
||||
|
||||
/obj/item/ammo_casing/caseless/spinfusor/throw_impact(atom/target) //disks detonate when thrown
|
||||
if(!..()) // not caught in mid-air
|
||||
visible_message("<span class='notice'>[src] detonates!</span>")
|
||||
playsound(src.loc, "sparks", 50, 1)
|
||||
explosion(target, -1, -1, 1, 1, -1)
|
||||
qdel(src)
|
||||
return 1
|
||||
|
||||
/obj/item/ammo_box/magazine/internal/spinfusor
|
||||
name = "spinfusor internal magazine"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/spinfusor
|
||||
caliber = "spinfusor"
|
||||
max_ammo = 1
|
||||
|
||||
/obj/item/gun/ballistic/automatic/spinfusor
|
||||
name = "Stormhammer Magnetic Cannon"
|
||||
desc = "An innovative weapon utilizing mag-lev technology to spin up a magnetic fusor and launch it at extreme velocities."
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "spinfusor"
|
||||
item_state = "spinfusor"
|
||||
mag_type = /obj/item/ammo_box/magazine/internal/spinfusor
|
||||
fire_sound = 'sound/weapons/rocketlaunch.ogg'
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
can_suppress = 0
|
||||
burst_size = 1
|
||||
fire_delay = 20
|
||||
select = 0
|
||||
actions_types = list()
|
||||
casing_ejector = 0
|
||||
origin_tech = "combat=6;magnets=6"
|
||||
|
||||
/obj/item/gun/ballistic/automatic/spinfusor/attackby(obj/item/A, mob/user, params)
|
||||
var/num_loaded = magazine.attackby(A, user, params, 1)
|
||||
if(num_loaded)
|
||||
to_chat(user, "<span class='notice'>You load [num_loaded] disk\s into \the [src].</span>")
|
||||
update_icon()
|
||||
chamber_round()
|
||||
|
||||
/obj/item/gun/ballistic/automatic/spinfusor/attack_self(mob/living/user)
|
||||
return //caseless rounds are too glitchy to unload properly. Best to make it so that you cannot remove disks from the spinfusor
|
||||
|
||||
/obj/item/gun/ballistic/automatic/spinfusor/update_icon()
|
||||
..()
|
||||
icon_state = "spinfusor[magazine ? "-[get_ammo(1)]" : ""]"
|
||||
|
||||
/obj/item/ammo_box/aspinfusor
|
||||
name = "ammo box (spinfusor disks)"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "spinfusorbox"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/spinfusor
|
||||
max_ammo = 8
|
||||
|
||||
/datum/supply_pack/security/armory/spinfusor
|
||||
name = "Stormhammer Spinfusor Crate"
|
||||
cost = 7000
|
||||
contains = list(/obj/item/gun/ballistic/automatic/spinfusor,
|
||||
/obj/item/gun/ballistic/automatic/spinfusor)
|
||||
crate_name = "spinfusor crate"
|
||||
|
||||
/datum/supply_pack/security/armory/spinfusorammo
|
||||
name = "Spinfusor Disk Crate"
|
||||
cost = 4000
|
||||
contains = list(/obj/item/ammo_box/aspinfusor,
|
||||
/obj/item/ammo_box/aspinfusor,
|
||||
/obj/item/ammo_box/aspinfusor,
|
||||
/obj/item/ammo_box/aspinfusor)
|
||||
crate_name = "spinfusor disk crate"
|
||||
|
||||
///////XCOM X9 AR///////
|
||||
|
||||
/obj/item/gun/ballistic/automatic/x9 //will be adminspawn only so ERT or something can use them
|
||||
name = "\improper X9 Assault Rifle"
|
||||
desc = "A rather old design of a cheap, reliable assault rifle made for combat against unknown enemies. Uses 5.56mm ammo."
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "x9"
|
||||
item_state = "arg"
|
||||
slot_flags = 0
|
||||
origin_tech = "combat=7;engineering=7"
|
||||
mag_type = /obj/item/ammo_box/magazine/m556 //Uses the m90gl's magazine, just like the NT-ARG
|
||||
fire_sound = 'sound/weapons/gunshot_smg.ogg'
|
||||
can_suppress = 0
|
||||
burst_size = 6 //in line with XCOMEU stats. This can fire 5 bursts from a full magazine.
|
||||
fire_delay = 1
|
||||
spread = 30 //should be 40 for XCOM memes, but since its adminspawn only, might as well make it useable
|
||||
recoil = 1
|
||||
|
||||
////////XCOM2 Magpistol/////////
|
||||
|
||||
//////projectiles//////
|
||||
|
||||
/obj/item/projectile/bullet/mags
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "magjectile"
|
||||
damage = 25
|
||||
armour_penetration = 10
|
||||
light_range = 2
|
||||
light_color = LIGHT_COLOR_RED
|
||||
|
||||
/obj/item/projectile/bullet/nlmags //non-lethal boolets
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "magjectile-nl"
|
||||
damage = 2
|
||||
knockdown = 15
|
||||
stamina = 50
|
||||
armour_penetration = -10
|
||||
light_range = 2
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
|
||||
/////actual ammo/////
|
||||
|
||||
/obj/item/ammo_casing/caseless/amags
|
||||
desc = "A ferromagnetic slug intended to be launched out of a compatible weapon."
|
||||
caliber = "mags"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "mag-casing-live"
|
||||
projectile_type = /obj/item/projectile/bullet/mags
|
||||
|
||||
/obj/item/ammo_casing/caseless/anlmags
|
||||
desc = "A specialized ferromagnetic slug designed with a less-than-lethal payload."
|
||||
caliber = "mags"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "mag-casing-live"
|
||||
projectile_type = /obj/item/projectile/bullet/nlmags
|
||||
|
||||
//////magazines/////
|
||||
|
||||
/obj/item/ammo_box/magazine/mmags
|
||||
name = "magpistol magazine (non-lethal disabler)"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "nlmagmag"
|
||||
origin_tech = "magnets=5"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/anlmags
|
||||
caliber = "mags"
|
||||
max_ammo = 7
|
||||
multiple_sprites = 2
|
||||
|
||||
/obj/item/ammo_box/magazine/mmags/lethal
|
||||
name = "magpistol magazine (lethal)"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "smallmagmag"
|
||||
origin_tech = "combat=5"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/amags
|
||||
|
||||
//////the gun itself//////
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/mag
|
||||
name = "magpistol"
|
||||
desc = "A handgun utilizing maglev technologies to propel a ferromagnetic slug to extreme velocities."
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "magpistol"
|
||||
force = 10
|
||||
fire_sound = 'sound/weapons/magpistol.ogg'
|
||||
mag_type = /obj/item/ammo_box/magazine/mmags
|
||||
can_suppress = 0
|
||||
casing_ejector = 0
|
||||
fire_delay = 5
|
||||
origin_tech = "combat=4;magnets=4"
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/mag/update_icon()
|
||||
..()
|
||||
if(magazine)
|
||||
cut_overlays()
|
||||
add_overlay("magpistol-magazine")
|
||||
else
|
||||
cut_overlays()
|
||||
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
|
||||
|
||||
///research memes///
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/mag/nopin
|
||||
pin = null
|
||||
|
||||
/datum/design/magpistol
|
||||
name = "Magpistol"
|
||||
desc = "A weapon which fires ferromagnetic slugs."
|
||||
id = "magpisol"
|
||||
req_tech = list("combat" = 5, "magnets" = 6, "powerstorage" = 5)
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 7500, MAT_GLASS = 1000, MAT_URANIUM = 1000, MAT_TITANIUM = 5000, MAT_SILVER = 2000)
|
||||
build_path = /obj/item/gun/ballistic/automatic/pistol/mag/nopin
|
||||
category = list("Weapons")
|
||||
|
||||
/datum/design/mag_magpistol
|
||||
name = "Magpistol Magazine"
|
||||
desc = "A 7 round magazine for the Magpistol."
|
||||
id = "mag_magpistol"
|
||||
req_tech = list("combat" = 5, "magnets" = 6, "materials" = 5, "syndicate" = 3)
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 4000, MAT_SILVER = 500)
|
||||
build_path = /obj/item/ammo_box/magazine/mmags/lethal
|
||||
category = list("Ammo")
|
||||
|
||||
/datum/design/mag_magpistol/nl
|
||||
name = "Magpistol Magazine (Non-Lethal)"
|
||||
desc = "A 7 round non-lethal magazine for the Magpistol."
|
||||
id = "mag_magpistol_nl"
|
||||
req_tech = list("combat" = 5, "magnets" = 6, "materials" = 5)
|
||||
materials = list(MAT_METAL = 3000, MAT_SILVER = 250, MAT_TITANIUM = 250)
|
||||
build_path = /obj/item/ammo_box/magazine/mmags
|
||||
|
||||
//////toy memes/////
|
||||
|
||||
/obj/item/projectile/bullet/reusable/foam_dart/mag
|
||||
name = "magfoam dart"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "magjectile-toy"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/mag
|
||||
light_range = 2
|
||||
light_color = LIGHT_COLOR_YELLOW
|
||||
|
||||
/obj/item/ammo_casing/caseless/foam_dart/mag
|
||||
name = "magfoam dart"
|
||||
desc = "A foam dart with fun light-up projectiles powered by magnets!"
|
||||
projectile_type = /obj/item/projectile/bullet/reusable/foam_dart/mag
|
||||
|
||||
/obj/item/ammo_box/magazine/internal/shot/toy/mag
|
||||
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/mag
|
||||
max_ammo = 7
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/toy/mag
|
||||
name = "foam force magpistol"
|
||||
desc = "A fancy toy sold alongside light-up foam force darts. Ages 8 and up."
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "toymag"
|
||||
item_state = "gun"
|
||||
mag_type = /obj/item/ammo_box/magazine/internal/shot/toy/mag
|
||||
fire_sound = 'sound/weapons/magpistol.ogg'
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/ammo_box/foambox/mag
|
||||
name = "ammo box (Magnetic Foam Darts)"
|
||||
icon = 'icons/obj/guns/toy.dmi'
|
||||
icon_state = "foambox"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/mag
|
||||
max_ammo = 42
|
||||
|
||||
/datum/design/magfoam_dart
|
||||
name = "Box of MagFoam Darts"
|
||||
id = "magfoam_dart"
|
||||
build_type = AUTOLATHE
|
||||
materials = list(MAT_METAL = 300, MAT_GLASS = 200)
|
||||
build_path = /obj/item/ammo_box/foambox/mag
|
||||
category = list("initial", "Misc")
|
||||
|
||||
/datum/design/foam_magpistol
|
||||
name = "Foam Force Magpistol"
|
||||
id = "magfoam_launcher"
|
||||
build_type = AUTOLATHE
|
||||
materials = list(MAT_METAL = 7500, MAT_GLASS = 1000)
|
||||
build_path = /obj/item/gun/ballistic/shotgun/toy/mag
|
||||
category = list("hacked", "Misc")
|
||||
|
||||
@@ -67,4 +67,54 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
attack_verb = list("slapped")
|
||||
resistance_flags = FLAMMABLE
|
||||
var/bitesound = 'sound/items/bikehorn.ogg'
|
||||
squeak_override = list('sound/items/bikehorn.ogg'= 1)
|
||||
|
||||
/obj/item/clothing/neck/cloak/carrot
|
||||
name = "carrot cloak"
|
||||
desc = "A cloak in the shape and color of a carrot!"
|
||||
icon = 'icons/obj/clothing/cloaks.dmi'
|
||||
icon_override = 'icons/mob/citadel/suit.dmi'
|
||||
icon_state = "carrotcloak"
|
||||
item_state = "carrotcloak"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
|
||||
|
||||
/*Zigfie*/
|
||||
|
||||
/obj/item/clothing/mask/luchador/zigfie
|
||||
name = "Alboroto Rosa mask"
|
||||
icon = 'icons/mob/mask.dmi'
|
||||
icon_state = "lucharzigfie"
|
||||
item_state = "lucharzigfie"
|
||||
|
||||
|
||||
/*PLACEHOLDER*/
|
||||
|
||||
/obj/item/clothing/head/hardhat/reindeer/fluff
|
||||
name = "novelty reindeer hat"
|
||||
desc = "Some fake antlers and a very fake red nose - Sponsored by PWR Game(tm)"
|
||||
icon_state = "hardhat0_reindeer"
|
||||
item_state = "hardhat0_reindeer"
|
||||
item_color = "reindeer"
|
||||
flags_inv = 0
|
||||
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
|
||||
brightness_on = 0 //luminosity when on
|
||||
dynamic_hair_suffix = ""
|
||||
|
||||
/obj/item/clothing/head/santa/fluff
|
||||
name = "santa's hat"
|
||||
desc = "On the first day of christmas my employer gave to me! - From Vlad with Salad"
|
||||
icon_state = "santahatnorm"
|
||||
item_state = "that"
|
||||
dog_fashion = /datum/dog_fashion/head/santa
|
||||
|
||||
|
||||
/*Brian*/
|
||||
|
||||
/obj/item/clothing/suit/trenchcoat/green
|
||||
name = "Reece's Great Coat"
|
||||
desc = "You would swear this was in your nightmares after eating too many veggies."
|
||||
icon_state = "hos-g"
|
||||
item_state = "hos-g"
|
||||
body_parts_covered = CHEST|GROIN|ARMS|LEGS
|
||||
@@ -136,7 +136,7 @@ GLOBAL_PROTECT(config_dir)
|
||||
var/list/probabilities = list() // relative probability of each mode
|
||||
var/list/min_pop = list() // overrides for acceptible player counts in a mode
|
||||
var/list/max_pop = list()
|
||||
|
||||
var/list/repeated_mode_adjust = list() // weight adjustments for recent modes
|
||||
var/humans_need_surnames = 0
|
||||
var/allow_ai = 0 // allow ai job
|
||||
var/forbid_secborg = 0 // disallow secborg module to be chosen.
|
||||
@@ -147,11 +147,13 @@ GLOBAL_PROTECT(config_dir)
|
||||
var/irc_first_connection_alert = 0 // do we notify the irc channel when somebody is connecting for the first time?
|
||||
|
||||
var/traitor_scaling_coeff = 6 //how much does the amount of players get divided by to determine traitors
|
||||
var/brother_scaling_coeff = 25 //how many players per brother team
|
||||
var/changeling_scaling_coeff = 6 //how much does the amount of players get divided by to determine changelings
|
||||
var/security_scaling_coeff = 8 //how much does the amount of players get divided by to determine open security officer positions
|
||||
var/abductor_scaling_coeff = 15 //how many players per abductor team
|
||||
|
||||
var/traitor_objectives_amount = 2
|
||||
var/brother_objectives_amount = 2
|
||||
var/protect_roles_from_antagonist = 0 //If security and such can be traitor/cult/other
|
||||
var/protect_assistant_from_antagonist = 0 //If assistants can be traitor/cult/other
|
||||
var/enforce_human_authority = 0 //If non-human species are barred from joining as a head of staff
|
||||
@@ -276,6 +278,7 @@ GLOBAL_PROTECT(config_dir)
|
||||
var/error_msg_delay = 50 // How long to wait between messaging admins about occurrences of a unique error
|
||||
|
||||
var/arrivals_shuttle_dock_window = 55 //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
|
||||
var/arrivals_shuttle_require_undocked = FALSE //Require the arrivals shuttle to be undocked before latejoiners can join
|
||||
var/arrivals_shuttle_require_safe_latejoin = FALSE //Require the arrivals shuttle to be operational in order for latejoiners to join
|
||||
|
||||
var/mice_roundstart = 10 // how many wire chewing rodents spawn at roundstart.
|
||||
@@ -698,6 +701,8 @@ GLOBAL_PROTECT(config_dir)
|
||||
ghost_interaction = 1
|
||||
if("traitor_scaling_coeff")
|
||||
traitor_scaling_coeff = text2num(value)
|
||||
if("brother_scaling_coeff")
|
||||
brother_scaling_coeff = text2num(value)
|
||||
if("changeling_scaling_coeff")
|
||||
changeling_scaling_coeff = text2num(value)
|
||||
if("security_scaling_coeff")
|
||||
@@ -706,6 +711,8 @@ GLOBAL_PROTECT(config_dir)
|
||||
abductor_scaling_coeff = text2num(value)
|
||||
if("traitor_objectives_amount")
|
||||
traitor_objectives_amount = text2num(value)
|
||||
if("brother_objectives_amount")
|
||||
brother_objectives_amount = text2num(value)
|
||||
if("probability")
|
||||
var/prob_pos = findtext(value, " ")
|
||||
var/prob_name = null
|
||||
@@ -720,7 +727,14 @@ GLOBAL_PROTECT(config_dir)
|
||||
WRITE_FILE(GLOB.config_error_log, "Unknown game mode probability configuration definition: [prob_name].")
|
||||
else
|
||||
WRITE_FILE(GLOB.config_error_log, "Incorrect probability configuration definition: [prob_name] [prob_value].")
|
||||
|
||||
if("repeated_mode_adjust")
|
||||
if(value)
|
||||
repeated_mode_adjust.Cut()
|
||||
var/values = splittext(value," ")
|
||||
for(var/v in values)
|
||||
repeated_mode_adjust += text2num(v)
|
||||
else
|
||||
WRITE_FILE(GLOB.config_error_log, "Incorrect round weight adjustment configuration definition for [value].")
|
||||
if("protect_roles_from_antagonist")
|
||||
protect_roles_from_antagonist = 1
|
||||
if("protect_assistant_from_antagonist")
|
||||
@@ -816,6 +830,8 @@ GLOBAL_PROTECT(config_dir)
|
||||
GLOB.MAX_EX_FLAME_RANGE = BombCap
|
||||
if("arrivals_shuttle_dock_window")
|
||||
arrivals_shuttle_dock_window = max(PARALLAX_LOOP_TIME, text2num(value))
|
||||
if("arrivals_shuttle_require_undocked")
|
||||
arrivals_shuttle_require_undocked = TRUE
|
||||
if("arrivals_shuttle_require_safe_latejoin")
|
||||
arrivals_shuttle_require_safe_latejoin = TRUE
|
||||
if("mice_roundstart")
|
||||
@@ -954,18 +970,18 @@ GLOBAL_PROTECT(config_dir)
|
||||
/datum/configuration/proc/pick_mode(mode_name)
|
||||
// I wish I didn't have to instance the game modes in order to look up
|
||||
// their information, but it is the only way (at least that I know of).
|
||||
// ^ This guy didn't try hard enough
|
||||
for(var/T in gamemode_cache)
|
||||
var/datum/game_mode/M = new T()
|
||||
if(M.config_tag && M.config_tag == mode_name)
|
||||
return M
|
||||
qdel(M)
|
||||
var/datum/game_mode/M = T
|
||||
var/ct = initial(M.config_tag)
|
||||
if(ct && ct == mode_name)
|
||||
return new T
|
||||
return new /datum/game_mode/extended()
|
||||
|
||||
/datum/configuration/proc/get_runnable_modes()
|
||||
var/list/datum/game_mode/runnable_modes = new
|
||||
for(var/T in gamemode_cache)
|
||||
var/datum/game_mode/M = new T()
|
||||
//to_chat(world, "DEBUG: [T], tag=[M.config_tag], prob=[probabilities[M.config_tag]]")
|
||||
if(!(M.config_tag in modes))
|
||||
qdel(M)
|
||||
continue
|
||||
@@ -977,8 +993,15 @@ GLOBAL_PROTECT(config_dir)
|
||||
if(max_pop[M.config_tag])
|
||||
M.maximum_players = max_pop[M.config_tag]
|
||||
if(M.can_start())
|
||||
runnable_modes[M] = probabilities[M.config_tag]
|
||||
//to_chat(world, "DEBUG: runnable_mode\[[runnable_modes.len]\] = [M.config_tag]")
|
||||
var/final_weight = probabilities[M.config_tag]
|
||||
if(SSpersistence.saved_modes.len == 3 && repeated_mode_adjust.len == 3)
|
||||
var/recent_round = min(SSpersistence.saved_modes.Find(M.config_tag),3)
|
||||
var/adjustment = 0
|
||||
while(recent_round)
|
||||
adjustment += repeated_mode_adjust[recent_round]
|
||||
recent_round = SSpersistence.saved_modes.Find(M.config_tag,recent_round+1,0)
|
||||
final_weight *= ((100-adjustment)/100)
|
||||
runnable_modes[M] = final_weight
|
||||
return runnable_modes
|
||||
|
||||
/datum/configuration/proc/get_runnable_midround_modes(crew)
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
diff a/code/controllers/configuration.dm b/code/controllers/configuration.dm (rejected hunks)
|
||||
@@ -337,17 +337,17 @@
|
||||
if("use_account_age_for_jobs")
|
||||
use_account_age_for_jobs = 1
|
||||
if("use_exp_tracking")
|
||||
- use_exp_tracking = 1
|
||||
+ use_exp_tracking = TRUE
|
||||
if("use_exp_restrictions_heads")
|
||||
- use_exp_restrictions_heads = 1
|
||||
+ use_exp_restrictions_heads = TRUE
|
||||
if("use_exp_restrictions_heads_hours")
|
||||
use_exp_restrictions_heads_hours = text2num(value)
|
||||
if("use_exp_restrictions_heads_department")
|
||||
- use_exp_restrictions_heads_department = 1
|
||||
+ use_exp_restrictions_heads_department = TRUE
|
||||
if("use_exp_restrictions_other")
|
||||
- use_exp_restrictions_other = 1
|
||||
+ use_exp_restrictions_other = TRUE
|
||||
if("use_exp_restrictions_admin_bypass")
|
||||
- use_exp_restrictions_admin_bypass = 1
|
||||
+ use_exp_restrictions_admin_bypass = TRUE
|
||||
if("lobby_countdown")
|
||||
lobby_countdown = text2num(value)
|
||||
if("round_end_countdown")
|
||||
@@ -422,7 +422,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
// in those cases, so we just let them run)
|
||||
if (queue_node_flags & SS_NO_TICK_CHECK)
|
||||
if (queue_node.tick_usage > TICK_LIMIT_RUNNING - TICK_USAGE && ran_non_ticker)
|
||||
queue_node.queued_priority += queue_priority_count * 0.10
|
||||
queue_node.queued_priority += queue_priority_count * 0.1
|
||||
queue_priority_count -= queue_node_priority
|
||||
queue_priority_count += queue_node.queued_priority
|
||||
current_tick_budget -= queue_node_priority
|
||||
|
||||
@@ -164,6 +164,7 @@ SUBSYSTEM_DEF(air)
|
||||
currentrun.len--
|
||||
if(!M || (M.process_atmos(seconds) == PROCESS_KILL))
|
||||
atmos_machinery.Remove(M)
|
||||
M.SendSignal(COMSIG_MACHINE_PROCESS_ATMOS)
|
||||
if(MC_TICK_CHECK)
|
||||
return
|
||||
|
||||
@@ -321,7 +322,7 @@ SUBSYSTEM_DEF(air)
|
||||
EG.dismantle()
|
||||
CHECK_TICK
|
||||
|
||||
var/msg = "HEY! LISTEN! [(world.timeofday - timer)/10] Seconds were wasted processing [starting_ats] turf(s) (connected to [ending_ats] other turfs) with atmos differences at round start."
|
||||
var/msg = "HEY! LISTEN! [DisplayTimeText(world.timeofday - timer)] were wasted processing [starting_ats] turf(s) (connected to [ending_ats] other turfs) with atmos differences at round start."
|
||||
to_chat(world, "<span class='boldannounce'>[msg]</span>")
|
||||
warning(msg)
|
||||
|
||||
@@ -382,4 +383,4 @@ SUBSYSTEM_DEF(air)
|
||||
#undef SSAIR_EXCITEDGROUPS
|
||||
#undef SSAIR_HIGHPRESSURE
|
||||
#undef SSAIR_HOTSPOT
|
||||
#undef SSAIR_SUPERCONDUCTIVITY
|
||||
#undef SSAIR_SUPERCONDUCTIVITY
|
||||
@@ -14,6 +14,9 @@ SUBSYSTEM_DEF(augury)
|
||||
/datum/controller/subsystem/augury/proc/register_doom(atom/A, severity)
|
||||
doombringers[A] = severity
|
||||
|
||||
/datum/controller/subsystem/augury/proc/unregister_doom(atom/A)
|
||||
doombringers -= A
|
||||
|
||||
/datum/controller/subsystem/augury/fire()
|
||||
var/biggest_doom = null
|
||||
var/biggest_threat = null
|
||||
|
||||
@@ -185,8 +185,7 @@ SUBSYSTEM_DEF(blackbox)
|
||||
return
|
||||
if(!L || !L.key || !L.mind)
|
||||
return
|
||||
var/turf/T = get_turf(L)
|
||||
var/area/placeofdeath = get_area(T.loc)
|
||||
var/area/placeofdeath = get_area(L)
|
||||
var/sqlname = sanitizeSQL(L.real_name)
|
||||
var/sqlkey = sanitizeSQL(L.ckey)
|
||||
var/sqljob = sanitizeSQL(L.mind.assigned_role)
|
||||
@@ -275,7 +274,7 @@ SUBSYSTEM_DEF(blackbox)
|
||||
details += "\"[deets]\""
|
||||
|
||||
/datum/feedback_variable/proc/get_details()
|
||||
return details.Join(" | ")
|
||||
return details ? details.Join(" | ") : null
|
||||
|
||||
/datum/feedback_variable/proc/get_parsed()
|
||||
return list(variable,value,details.Join(" | "))
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
diff a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm (rejected hunks)
|
||||
@@ -40,7 +40,7 @@ SUBSYSTEM_DEF(blackbox)
|
||||
|
||||
if(config.use_exp_tracking)
|
||||
if((triggertime < 0) || (world.time > (triggertime +3000))) //subsystem fires once at roundstart then once every 10 minutes. a 5 min check skips the first fire. The <0 is midnight rollover check
|
||||
- SSblackbox.update_exp(10,FALSE)
|
||||
+ update_exp(10,FALSE)
|
||||
|
||||
|
||||
/datum/controller/subsystem/blackbox/Recover()
|
||||
@@ -40,6 +40,7 @@ SUBSYSTEM_DEF(machines)
|
||||
var/obj/machinery/thing = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(!QDELETED(thing) && thing.process(seconds) != PROCESS_KILL)
|
||||
thing.SendSignal(COMSIG_MACHINE_PROCESS)
|
||||
if(thing.use_power)
|
||||
thing.auto_use_power() //add back the power state
|
||||
else
|
||||
@@ -61,4 +62,4 @@ SUBSYSTEM_DEF(machines)
|
||||
if (istype(SSmachines.processing))
|
||||
processing = SSmachines.processing
|
||||
if (istype(SSmachines.powernets))
|
||||
powernets = SSmachines.powernets
|
||||
powernets = SSmachines.powernets
|
||||
@@ -8,7 +8,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
|
||||
var/list/obj/structure/chisel_message/chisel_messages = list()
|
||||
var/list/saved_messages = list()
|
||||
|
||||
var/list/saved_modes = list(1,2,3)
|
||||
var/list/saved_trophies = list()
|
||||
|
||||
/datum/controller/subsystem/persistence/Initialize()
|
||||
@@ -16,6 +16,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
LoadPoly()
|
||||
LoadChiselMessages()
|
||||
LoadTrophies()
|
||||
LoadRecentModes()
|
||||
..()
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadSatchels()
|
||||
@@ -41,8 +42,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/json_file = file("data/npc_saves/SecretSatchels[SSmapping.config.map_name].json")
|
||||
if(!fexists(json_file))
|
||||
return
|
||||
var/list/json = list()
|
||||
json = json_decode(file2text(json_file))
|
||||
var/list/json = json_decode(file2text(json_file))
|
||||
old_secret_satchels = json["data"]
|
||||
if(old_secret_satchels.len)
|
||||
if(old_secret_satchels.len >= 20) //guards against low drop pools assuring that one player cannot reliably find his own gear.
|
||||
@@ -84,8 +84,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/json_file = file("data/npc_saves/ChiselMessages[SSmapping.config.map_name].json")
|
||||
if(!fexists(json_file))
|
||||
return
|
||||
var/list/json
|
||||
json = json_decode(file2text(json_file))
|
||||
var/list/json = json_decode(file2text(json_file))
|
||||
|
||||
if(!json)
|
||||
return
|
||||
@@ -129,13 +128,22 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/json_file = file("data/npc_saves/TrophyItems.json")
|
||||
if(!fexists(json_file))
|
||||
return
|
||||
var/list/json = list()
|
||||
json = json_decode(file2text(json_file))
|
||||
var/list/json = json_decode(file2text(json_file))
|
||||
if(!json)
|
||||
return
|
||||
saved_trophies = json["data"]
|
||||
SetUpTrophies(saved_trophies.Copy())
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadRecentModes()
|
||||
var/json_file = file("data/RecentModes.json")
|
||||
if(!fexists(json_file))
|
||||
return
|
||||
var/list/json = json_decode(file2text(json_file))
|
||||
if(!json)
|
||||
return
|
||||
saved_modes = json["data"]
|
||||
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SetUpTrophies(list/trophy_items)
|
||||
for(var/A in GLOB.trophy_cases)
|
||||
var/obj/structure/displaycase/trophy/T = A
|
||||
@@ -165,6 +173,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
CollectChiselMessages()
|
||||
CollectSecretSatchels()
|
||||
CollectTrophies()
|
||||
CollectRoundtype()
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/CollectSecretSatchels()
|
||||
var/list/satchels = list()
|
||||
@@ -224,3 +233,13 @@ SUBSYSTEM_DEF(persistence)
|
||||
data["message"] = T.trophy_message
|
||||
data["placer_key"] = T.placer_key
|
||||
saved_trophies += list(data)
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/CollectRoundtype()
|
||||
saved_modes[3] = saved_modes[2]
|
||||
saved_modes[2] = saved_modes[1]
|
||||
saved_modes[1] = SSticker.mode.config_tag
|
||||
var/json_file = file("data/RecentModes.json")
|
||||
var/list/file_data = list()
|
||||
file_data["data"] = saved_modes
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
@@ -29,7 +29,7 @@ SUBSYSTEM_DEF(server_maint)
|
||||
var/cmob = C.mob
|
||||
if(!(isobserver(cmob) || (isdead(cmob) && C.holder)))
|
||||
log_access("AFK: [key_name(C)]")
|
||||
to_chat(C, "<span class='danger'>You have been inactive for more than [config.afk_period / 600] minutes and have been disconnected.</span>")
|
||||
to_chat(C, "<span class='danger'>You have been inactive for more than [DisplayTimeText(config.afk_period)] and have been disconnected.</span>")
|
||||
qdel(C)
|
||||
|
||||
if (!(!C || world.time - C.connection_time < PING_BUFFER_TIME || C.inactivity >= (wait-1)))
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
diff a/code/controllers/subsystem/server_maint.dm b/code/controllers/subsystem/server_maint.dm (rejected hunks)
|
||||
@@ -6,18 +6,16 @@ SUBSYSTEM_DEF(server_maint)
|
||||
flags = SS_POST_FIRE_TIMING|SS_FIRE_IN_LOBBY
|
||||
priority = 10
|
||||
var/list/currentrun
|
||||
- var/triggertime = null
|
||||
|
||||
/datum/controller/subsystem/server_maint/Initialize(timeofday)
|
||||
if (config.hub)
|
||||
world.visibility = 1
|
||||
- triggertime = REALTIMEOFDAY
|
||||
..()
|
||||
|
||||
/datum/controller/subsystem/server_maint/fire(resumed = FALSE)
|
||||
if(!resumed)
|
||||
src.currentrun = GLOB.clients.Copy()
|
||||
-
|
||||
+
|
||||
var/list/currentrun = src.currentrun
|
||||
var/round_started = SSticker.HasRoundStarted()
|
||||
|
||||
@@ -39,8 +37,3 @@ SUBSYSTEM_DEF(server_maint)
|
||||
return
|
||||
|
||||
#undef PING_BUFFER_TIME
|
||||
- if(config.sql_enabled)
|
||||
- sql_poll_population()
|
||||
- if(config.use_exp_tracking)
|
||||
- if(REALTIMEOFDAY > (triggertime +3000)) //server maint fires once at roundstart then once every 10 minutes. a 5 min check skips the first fire
|
||||
- update_exp(10,0)
|
||||
@@ -178,7 +178,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
emergency = backup_shuttle
|
||||
|
||||
if(world.time - SSticker.round_start_time < config.shuttle_refuel_delay)
|
||||
to_chat(user, "The emergency shuttle is refueling. Please wait another [abs(round(((world.time - SSticker.round_start_time) - config.shuttle_refuel_delay)/600))] minutes before trying again.")
|
||||
to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText((world.time - SSticker.round_start_time) - config.shuttle_refuel_delay)] before trying again.")
|
||||
return
|
||||
|
||||
switch(emergency.mode)
|
||||
@@ -220,7 +220,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
if(call_reason)
|
||||
SSblackbox.add_details("shuttle_reason", call_reason)
|
||||
log_game("Shuttle call reason: [call_reason]")
|
||||
message_admins("[key_name_admin(user)] has called the shuttle. (<A HREF='?_src_=holder;trigger_centcom_recall=1'>TRIGGER CENTCOM RECALL</A>)")
|
||||
message_admins("[key_name_admin(user)] has called the shuttle. (<A HREF='?_src_=holder;[HrefToken()];trigger_centcom_recall=1'>TRIGGER CENTCOM RECALL</A>)")
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/centcom_recall(old_timer, admiral_message)
|
||||
if(emergency.mode != SHUTTLE_CALL || emergency.timer != old_timer)
|
||||
@@ -430,17 +430,14 @@ SUBSYSTEM_DEF(shuttle)
|
||||
continue base
|
||||
if(!(T.flags_1 & UNUSED_TRANSIT_TURF_1))
|
||||
continue base
|
||||
//to_chat(world, "[COORD(topleft)] and [COORD(bottomright)]")
|
||||
break base
|
||||
|
||||
if((!proposed_zone) || (!proposed_zone.len))
|
||||
return FALSE
|
||||
|
||||
var/turf/topleft = proposed_zone[1]
|
||||
//to_chat(world, "[COORD(topleft)] is TOPLEFT")
|
||||
// Then create a transit docking port in the middle
|
||||
var/coords = M.return_coords(0, 0, dock_dir)
|
||||
//to_chat(world, json_encode(coords))
|
||||
/* 0------2
|
||||
| |
|
||||
| |
|
||||
@@ -478,11 +475,9 @@ SUBSYSTEM_DEF(shuttle)
|
||||
if(WEST)
|
||||
transit_path = /turf/open/space/transit/west
|
||||
|
||||
//to_chat(world, "Docking port at [transit_x], [transit_y], [topleft.z]")
|
||||
var/turf/midpoint = locate(transit_x, transit_y, topleft.z)
|
||||
if(!midpoint)
|
||||
return FALSE
|
||||
//to_chat(world, "Making transit dock at [COORD(midpoint)]")
|
||||
var/area/shuttle/transit/A = new()
|
||||
A.parallax_movedir = travel_dir
|
||||
A.contents = proposed_zone
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// The Squeak
|
||||
// because this is about placement of mice mobs, and nothing to do with
|
||||
// mice - the computer peripheral
|
||||
// mice - the computer peripheral
|
||||
|
||||
SUBSYSTEM_DEF(squeak)
|
||||
name = "Squeak"
|
||||
@@ -32,8 +32,9 @@ SUBSYSTEM_DEF(squeak)
|
||||
|
||||
/datum/controller/subsystem/squeak/proc/find_exposed_wires()
|
||||
exposed_wires.Cut()
|
||||
|
||||
var/list/all_turfs = block(locate(1,1,1), locate(world.maxx,world.maxy,1))
|
||||
var/list/all_turfs
|
||||
for (var/z in GLOB.station_z_levels)
|
||||
all_turfs += block(locate(1,1,z), locate(world.maxx,world.maxy,z))
|
||||
for(var/turf/open/floor/plating/T in all_turfs)
|
||||
if(is_blocked_turf(T))
|
||||
continue
|
||||
|
||||
@@ -139,7 +139,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
|
||||
if(!mode.explosion_in_progress && mode.check_finished(force_ending) || force_ending)
|
||||
current_state = GAME_STATE_FINISHED
|
||||
toggle_ooc(1) // Turn it on
|
||||
toggle_ooc(TRUE) // Turn it on
|
||||
toggle_dooc(TRUE)
|
||||
declare_completion(force_ending)
|
||||
Master.SetRunLevel(RUNLEVEL_POSTGAME)
|
||||
|
||||
@@ -166,6 +167,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
to_chat(world, "<B>Unable to choose playable game mode.</B> Reverting to pre-game lobby.")
|
||||
return 0
|
||||
mode = pickweight(runnable_modes)
|
||||
if(!mode) //too few roundtypes all run too recently
|
||||
mode = pick(runnable_modes)
|
||||
|
||||
else
|
||||
mode = config.pick_mode(GLOB.master_mode)
|
||||
@@ -205,7 +208,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
mode.announce()
|
||||
|
||||
if(!config.ooc_during_round)
|
||||
toggle_ooc(0) // Turn it off
|
||||
toggle_ooc(FALSE) // Turn it off
|
||||
|
||||
CHECK_TICK
|
||||
GLOB.start_landmarks_list = shuffle(GLOB.start_landmarks_list) //Shuffle the order of spawn points so they dont always predictably spawn bottom-up and right-to-left
|
||||
@@ -241,10 +244,10 @@ SUBSYSTEM_DEF(ticker)
|
||||
|
||||
PostSetup()
|
||||
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/PostSetup()
|
||||
set waitfor = 0
|
||||
set waitfor = FALSE
|
||||
mode.post_setup()
|
||||
GLOB.start_state = new /datum/station_state()
|
||||
GLOB.start_state.count(1)
|
||||
@@ -511,7 +514,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
end_state.count()
|
||||
var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
|
||||
|
||||
to_chat(world, "<BR>[GLOB.TAB]Shift Duration: <B>[round(world.time / 36000)]:[add_zero("[world.time / 600 % 60]", 2)]:[world.time / 100 % 6][world.time / 100 % 10]</B>")
|
||||
to_chat(world, "<BR>[GLOB.TAB]Shift Duration: <B>[DisplayTimeText(world.time - SSticker.round_start_time)]</B>")
|
||||
to_chat(world, "<BR>[GLOB.TAB]Station Integrity: <B>[mode.station_was_nuked ? "<font color='red'>Destroyed</font>" : "[station_integrity]%"]</B>")
|
||||
if(mode.station_was_nuked)
|
||||
SSticker.news_report = STATION_DESTROYED_NUKE
|
||||
|
||||
@@ -169,7 +169,7 @@ SUBSYSTEM_DEF(vote)
|
||||
admin = TRUE
|
||||
|
||||
if(next_allowed_time > world.time && !admin)
|
||||
to_chat(usr, "<span class='warning'>A vote was initiated recently, you must wait roughly [(next_allowed_time-world.time)/10] seconds before a new vote can be started!</span>")
|
||||
to_chat(usr, "<span class='warning'>A vote was initiated recently, you must wait [DisplayTimeText(next_allowed_time-world.time)] before a new vote can be started!</span>")
|
||||
return 0
|
||||
|
||||
reset()
|
||||
@@ -198,7 +198,7 @@ SUBSYSTEM_DEF(vote)
|
||||
if(mode == "custom")
|
||||
text += "\n[question]"
|
||||
log_vote(text)
|
||||
to_chat(world, "\n<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src]'>here</a> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</font>")
|
||||
to_chat(world, "\n<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src]'>here</a> to place your votes.\nYou have [DisplayTimeText(config.vote_period)] to vote.</font>")
|
||||
time_remaining = round(config.vote_period/10)
|
||||
for(var/c in GLOB.clients)
|
||||
var/client/C = c
|
||||
|
||||
@@ -14,8 +14,8 @@ SUBSYSTEM_DEF(weather)
|
||||
if(W.aesthetic)
|
||||
continue
|
||||
for(var/mob/living/L in GLOB.mob_list)
|
||||
if(W.can_impact(L))
|
||||
W.impact(L)
|
||||
if(W.can_weather_act(L))
|
||||
W.weather_act(L)
|
||||
for(var/Z in eligible_zlevels)
|
||||
var/list/possible_weather_for_this_z = list()
|
||||
for(var/V in existing_weather)
|
||||
@@ -30,8 +30,7 @@ SUBSYSTEM_DEF(weather)
|
||||
/datum/controller/subsystem/weather/Initialize(start_timeofday)
|
||||
..()
|
||||
for(var/V in subtypesof(/datum/weather))
|
||||
var/datum/weather/W = V
|
||||
new W //weather->New will handle adding itself to the list
|
||||
new V //Weather's New() will handle adding stuff to the list
|
||||
|
||||
/datum/controller/subsystem/weather/proc/run_weather(weather_name, Z)
|
||||
if(!weather_name)
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
|
||||
/datum/action/item_action/ninjapulse
|
||||
name = "EM Burst (25E)"
|
||||
desc = "Disable any nearby technology with a electro-magnetic pulse."
|
||||
desc = "Disable any nearby technology with an electro-magnetic pulse."
|
||||
button_icon_state = "emp"
|
||||
icon_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
|
||||
|
||||
@@ -310,7 +310,7 @@
|
||||
replaceable_groups[LAW_INHERENT] = inherent.len
|
||||
if(supplied.len && (LAW_SUPPLIED in groups))
|
||||
replaceable_groups[LAW_SUPPLIED] = supplied.len
|
||||
var picked_group = pickweight(replaceable_groups)
|
||||
var/picked_group = pickweight(replaceable_groups)
|
||||
switch(picked_group)
|
||||
if(LAW_ZEROTH)
|
||||
. = zeroth
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/datum/antagonist/abductor
|
||||
name = "Abductor"
|
||||
var/datum/objective_team/abductor_team/team
|
||||
var/sub_role
|
||||
var/outfit
|
||||
var/landmark_type
|
||||
var/greet_text
|
||||
|
||||
/datum/antagonist/abductor/agent
|
||||
sub_role = "Agent"
|
||||
outfit = /datum/outfit/abductor/agent
|
||||
landmark_type = /obj/effect/landmark/abductor/agent
|
||||
greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve."
|
||||
|
||||
/datum/antagonist/abductor/scientist
|
||||
sub_role = "Scientist"
|
||||
outfit = /datum/outfit/abductor/scientist
|
||||
landmark_type = /obj/effect/landmark/abductor/scientist
|
||||
greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve."
|
||||
|
||||
/datum/antagonist/abductor/New(datum/mind/new_owner, datum/objective_team/abductor_team/T)
|
||||
team = T
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/abductor/on_gain()
|
||||
SSticker.mode.abductors += owner
|
||||
owner.special_role = "[name] [sub_role]"
|
||||
owner.objectives += team.objectives
|
||||
finalize_abductor()
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/abductor/on_removal()
|
||||
SSticker.mode.abductors -= owner
|
||||
team.members -= owner
|
||||
owner.objectives -= team.objectives
|
||||
if(owner.current)
|
||||
to_chat(owner.current,"<span class='userdanger'>You are no longer the [owner.special_role]!</span>")
|
||||
owner.special_role = null
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/abductor/greet()
|
||||
to_chat(owner.current, "<span class='notice'>You are the [owner.special_role]!</span>")
|
||||
to_chat(owner.current, "<span class='notice'>With the help of your teammate, kidnap and experiment on station crew members!</span>")
|
||||
to_chat(owner.current, "<span class='notice'>[greet_text]</span>")
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/abductor/proc/finalize_abductor()
|
||||
//Equip
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
H.set_species(/datum/species/abductor)
|
||||
H.real_name = "[team.name] [sub_role]"
|
||||
H.equipOutfit(outfit)
|
||||
|
||||
//Teleport to ship
|
||||
for(var/obj/effect/landmark/abductor/LM in GLOB.landmarks_list)
|
||||
if(istype(LM, landmark_type) && LM.team_number == team.team_number)
|
||||
H.forceMove(LM.loc)
|
||||
break
|
||||
|
||||
SSticker.mode.update_abductor_icons_added(owner)
|
||||
@@ -0,0 +1,48 @@
|
||||
/datum/antagonist/brother
|
||||
name = "Brother"
|
||||
var/special_role = "blood brother"
|
||||
var/datum/objective_team/brother_team/team
|
||||
|
||||
/datum/antagonist/brother/New(datum/mind/new_owner, datum/objective_team/brother_team/T)
|
||||
team = T
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/brother/on_gain()
|
||||
SSticker.mode.brothers += owner
|
||||
owner.special_role = special_role
|
||||
owner.objectives += team.objectives
|
||||
finalize_brother()
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/brother/on_removal()
|
||||
SSticker.mode.brothers -= owner
|
||||
team.members -= owner
|
||||
owner.objectives -= team.objectives
|
||||
if(owner.current)
|
||||
to_chat(owner.current,"<span class='userdanger'>You are no longer the [special_role]!</span>")
|
||||
owner.special_role = null
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/brother/proc/give_meeting_area()
|
||||
if(!owner.current || !team || !team.meeting_area)
|
||||
return
|
||||
to_chat(owner.current, "<B>Your designated meeting area:</B> [team.meeting_area]")
|
||||
owner.store_memory("<b>Meeting Area</b>: [team.meeting_area]")
|
||||
|
||||
/datum/antagonist/brother/greet()
|
||||
var/brother_text = ""
|
||||
var/list/brothers = team.members - owner
|
||||
for(var/i = 1 to brothers.len)
|
||||
var/datum/mind/M = brothers[i]
|
||||
brother_text += M.name
|
||||
if(i == brothers.len - 1)
|
||||
brother_text += " and "
|
||||
else if(i != brothers.len)
|
||||
brother_text += ", "
|
||||
to_chat(owner.current, "<B><font size=3 color=red>You are the [owner.special_role] of [brother_text].</font></B>")
|
||||
to_chat(owner.current, "The Syndicate only accepts those that have proven themself. Prove yourself and prove your [team.member_name]s by completing your objectives together!")
|
||||
owner.announce_objectives()
|
||||
give_meeting_area()
|
||||
|
||||
/datum/antagonist/brother/proc/finalize_brother()
|
||||
SSticker.mode.update_brother_icons_added(owner)
|
||||
@@ -186,9 +186,9 @@
|
||||
kill_objective.find_target()
|
||||
add_objective(kill_objective)
|
||||
|
||||
var/datum/objective/survive/survive_objective = new
|
||||
survive_objective.owner = owner
|
||||
add_objective(survive_objective)
|
||||
var/datum/objective/survive/exist/exist_objective = new
|
||||
exist_objective.owner = owner
|
||||
add_objective(exist_objective)
|
||||
/datum/antagonist/traitor/proc/forge_single_objective()
|
||||
return 0
|
||||
/datum/antagonist/traitor/human/forge_single_objective() //Returns how many objectives are added
|
||||
|
||||
@@ -256,7 +256,6 @@
|
||||
|
||||
winset(user, windowid, "on-close=\".windowclose [param]\"")
|
||||
|
||||
//to_chat(world, "OnClose [user]: [windowid] : ["on-close=\".windowclose [param]\""]")
|
||||
|
||||
|
||||
// the on-close client verb
|
||||
@@ -268,12 +267,10 @@
|
||||
set hidden = 1 // hide this verb from the user's panel
|
||||
set name = ".windowclose" // no autocomplete on cmd line
|
||||
|
||||
//to_chat(world, "windowclose: [atomref]")
|
||||
if(atomref!="null") // if passed a real atomref
|
||||
var/hsrc = locate(atomref) // find the reffed atom
|
||||
var/href = "close=1"
|
||||
if(hsrc)
|
||||
//to_chat(world, "[src] Topic [href] [hsrc]")
|
||||
usr = src.mob
|
||||
src.Topic(href, params2list(href), hsrc) // this will direct to the atom's
|
||||
return // Topic() proc via client.Topic()
|
||||
@@ -281,6 +278,5 @@
|
||||
// no atomref specified (or not found)
|
||||
// so just reset the user mob's machine var
|
||||
if(src && src.mob)
|
||||
//to_chat(world, "[src] was [src.mob.machine], setting to null")
|
||||
src.mob.unset_machine()
|
||||
return
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
|
||||
//runs a list of callbacks asynchronously, returning once all of them return.
|
||||
//callbacks can be repeated.
|
||||
//callbacks-args is a optional list of argument lists, in the same order as the callbacks,
|
||||
//callbacks-args is an optional list of argument lists, in the same order as the callbacks,
|
||||
// the inner lists will be sent to the callbacks when invoked() as additional args.
|
||||
//can optionly save and return a list of return values, in the same order as the original list of callbacks
|
||||
//resolution is the number of byond ticks between checks.
|
||||
|
||||
@@ -62,7 +62,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* Returns the component that was created. Or the old component in a dupe situation where `COMPONENT_DUPE_UNIQUE` was set
|
||||
1. `/datum/proc/LoadComponent(component_type(type), ...) -> datum/component` (public, final)
|
||||
* Equivalent to calling `GetComponent(component_type)` where, if the result would be `null`, returns `AddComponent(component_type, ...)` instead
|
||||
1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract)
|
||||
1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract, async)
|
||||
* Called on a component's `parent` after a signal recieved causes it to activate. `src` is the parameter
|
||||
* Will only be called if a component's callback returns `TRUE`
|
||||
1. `/datum/proc/TakeComponent(datum/component/C)` (public, final)
|
||||
@@ -87,7 +87,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* Called on a component when a component of the same type was added to the same parent
|
||||
* See `/datum/component/var/dupe_mode`
|
||||
* `C`'s type will always be the same of the called component
|
||||
1. `/datum/component/proc/AfterComponentActivated()` (abstract)
|
||||
1. `/datum/component/proc/AfterComponentActivated()` (abstract, async)
|
||||
* Called on a component that was activated after it's `parent`'s `ComponentActivated()` is called
|
||||
1. `/datum/component/proc/OnTransfer(datum/new_parent)` (abstract, no-sleep)
|
||||
* Called before the new `parent` is assigned in `TakeComponent()`, after the remove signal, before the added signal
|
||||
@@ -101,8 +101,5 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this
|
||||
* These callbacks run asyncronously
|
||||
* Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `SendSignal()` that initiated it
|
||||
1. `/datum/component/proc/ReceiveSignal(signal, ...)` (virtual)
|
||||
* Called when a component recieves any signal and is enabled
|
||||
* Default implementation looks if the signal is registered and runs the appropriate proc
|
||||
|
||||
### See/Define signals and their arguments in __DEFINES\components.dm
|
||||
|
||||
@@ -110,15 +110,6 @@
|
||||
|
||||
procs[sig_type] = CALLBACK(src, proc_on_self)
|
||||
|
||||
/datum/component/proc/ReceiveSignal(sigtype, ...)
|
||||
var/list/sps = signal_procs
|
||||
var/datum/callback/CB = LAZYACCESS(sps, sigtype)
|
||||
if(!CB)
|
||||
return FALSE
|
||||
var/list/arguments = args.Copy()
|
||||
arguments.Cut(1, 2)
|
||||
return CB.InvokeAsync(arglist(arguments))
|
||||
|
||||
/datum/component/proc/InheritComponent(datum/component/C, i_am_original)
|
||||
return
|
||||
|
||||
@@ -126,6 +117,7 @@
|
||||
return
|
||||
|
||||
/datum/component/proc/AfterComponentActivated()
|
||||
set waitfor = FALSE
|
||||
return
|
||||
|
||||
/datum/component/proc/_GetInverseTypeList(current_type)
|
||||
@@ -136,26 +128,40 @@
|
||||
|
||||
/datum/proc/SendSignal(sigtype, ...)
|
||||
var/list/comps = datum_components
|
||||
. = FALSE
|
||||
if(!comps)
|
||||
return
|
||||
return FALSE
|
||||
var/list/arguments = args.Copy()
|
||||
arguments.Cut(1, 2)
|
||||
var/target = comps[/datum/component]
|
||||
if(!islist(target))
|
||||
var/datum/component/C = target
|
||||
if(C.enabled && C.ReceiveSignal(arglist(args)))
|
||||
if(!C.enabled)
|
||||
return FALSE
|
||||
var/list/sps = C.signal_procs
|
||||
var/datum/callback/CB = LAZYACCESS(sps, sigtype)
|
||||
if(!CB)
|
||||
return FALSE
|
||||
. = CB.InvokeAsync(arglist(arguments))
|
||||
if(.)
|
||||
ComponentActivated(C)
|
||||
C.AfterComponentActivated()
|
||||
return TRUE
|
||||
else
|
||||
. = FALSE
|
||||
for(var/I in target)
|
||||
var/datum/component/C = I
|
||||
if(!C.enabled)
|
||||
continue
|
||||
var/list/sps = C.signal_procs
|
||||
var/datum/callback/CB = LAZYACCESS(sps, sigtype)
|
||||
if(!CB)
|
||||
continue
|
||||
if(C.ReceiveSignal(arglist(args)))
|
||||
if(CB.InvokeAsync(arglist(arguments)))
|
||||
ComponentActivated(C)
|
||||
C.AfterComponentActivated()
|
||||
. = TRUE
|
||||
|
||||
/datum/proc/ComponentActivated(datum/component/C)
|
||||
set waitfor = FALSE
|
||||
return
|
||||
|
||||
/datum/proc/GetComponent(c_type)
|
||||
@@ -5,22 +5,34 @@
|
||||
amount - raw amount of the mineral this container is holding, calculated by the defined value MINERAL_MATERIAL_AMOUNT=2000.
|
||||
max_amount - max raw amount of mineral this container can hold.
|
||||
sheet_type - type of the mineral sheet the container handles, used for output.
|
||||
owner - object that this container is being used by, used for output.
|
||||
parent - object that this container is being used by, used for output.
|
||||
MAX_STACK_SIZE - size of a stack of mineral sheets. Constant.
|
||||
*/
|
||||
|
||||
/datum/material_container
|
||||
/datum/component/material_container
|
||||
var/total_amount = 0
|
||||
var/max_amount
|
||||
var/sheet_type
|
||||
var/obj/owner
|
||||
var/list/materials = list()
|
||||
var/list/materials
|
||||
var/show_on_examine
|
||||
var/list/allowed_typecache
|
||||
var/last_inserted_type
|
||||
var/last_amount_inserted
|
||||
var/last_insert_success
|
||||
var/datum/callback/precondition
|
||||
//MAX_STACK_SIZE = 50
|
||||
//MINERAL_MATERIAL_AMOUNT = 2000
|
||||
|
||||
/datum/material_container/New(obj/O, list/mat_list, max_amt = 0)
|
||||
owner = O
|
||||
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition)
|
||||
materials = list()
|
||||
max_amount = max(0, max_amt)
|
||||
show_on_examine = _show_on_examine
|
||||
if(allowed_types)
|
||||
allowed_typecache = typecacheof(allowed_types)
|
||||
precondition = _precondition
|
||||
|
||||
RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
|
||||
RegisterSignal(COMSIG_PARENT_EXAMINE, .proc/OnExamine)
|
||||
|
||||
var/list/possible_mats = list()
|
||||
for(var/mat_type in subtypesof(/datum/material))
|
||||
@@ -31,12 +43,47 @@
|
||||
var/mat_path = possible_mats[id]
|
||||
materials[id] = new mat_path()
|
||||
|
||||
/datum/material_container/Destroy()
|
||||
owner = null
|
||||
return ..()
|
||||
/datum/component/material_container/proc/OnExamine(mob/user)
|
||||
for(var/I in materials)
|
||||
var/datum/material/M = materials[I]
|
||||
var/amt = amount(M.id)
|
||||
if(amt)
|
||||
to_chat(user, "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>")
|
||||
|
||||
/datum/component/material_container/proc/OnAttackBy(obj/item/I, mob/living/user)
|
||||
var/list/tc = allowed_typecache
|
||||
if(user.a_intent == INTENT_HARM || (I.flags_2 & HOLOGRAM_2) || (tc && !is_type_in_typecache(I, tc)))
|
||||
return FALSE
|
||||
. = TRUE
|
||||
last_insert_success = FALSE
|
||||
var/datum/callback/pc = precondition
|
||||
if(pc && !pc.Invoke())
|
||||
return
|
||||
var/material_amount = get_item_material_amount(I)
|
||||
if(!material_amount)
|
||||
to_chat(user, "<span class='warning'>[I] does not contain sufficient amounts of metal or glass to be accepted by [parent].</span>")
|
||||
return
|
||||
if(!has_space(material_amount))
|
||||
to_chat(user, "<span class='warning'>[parent] is full. Please remove metal or glass from [parent] in order to insert more.</span>")
|
||||
return
|
||||
if(!user.temporarilyRemoveItemFromInventory(I))
|
||||
to_chat(user, "<span class='warning'>[I] is stuck to you and cannot be placed into [parent].</span>")
|
||||
return
|
||||
var/inserted = insert_item(I)
|
||||
if(inserted)
|
||||
last_insert_success = TRUE
|
||||
if(istype(I, /obj/item/stack))
|
||||
to_chat(user, "<span class='notice'>You insert [inserted] sheet[inserted>1 ? "s" : ""] into [parent].</span>")
|
||||
if(!QDELETED(I))
|
||||
user.put_in_active_hand(I)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You insert a material total of [inserted] into [parent].</span>")
|
||||
qdel(I)
|
||||
else
|
||||
user.put_in_active_hand(I)
|
||||
|
||||
//For inserting an amount of material
|
||||
/datum/material_container/proc/insert_amount(amt, id = null)
|
||||
/datum/component/material_container/proc/insert_amount(amt, id = null)
|
||||
if(amt > 0 && has_space(amt))
|
||||
var/total_amount_saved = total_amount
|
||||
if(id)
|
||||
@@ -52,7 +99,7 @@
|
||||
return (total_amount - total_amount_saved)
|
||||
return 0
|
||||
|
||||
/datum/material_container/proc/insert_stack(obj/item/stack/S, amt = 0)
|
||||
/datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt = 0)
|
||||
if(amt <= 0)
|
||||
return 0
|
||||
if(amt > S.amount)
|
||||
@@ -67,10 +114,12 @@
|
||||
return 0
|
||||
|
||||
insert_materials(S,amt)
|
||||
last_inserted_type = S.type
|
||||
S.use(amt)
|
||||
last_amount_inserted = amt
|
||||
return amt
|
||||
|
||||
/datum/material_container/proc/insert_item(obj/item/I, multiplier = 1)
|
||||
/datum/component/material_container/proc/insert_item(obj/item/I, multiplier = 1)
|
||||
if(!I)
|
||||
return 0
|
||||
if(istype(I, /obj/item/stack))
|
||||
@@ -82,9 +131,11 @@
|
||||
return 0
|
||||
|
||||
insert_materials(I, multiplier)
|
||||
last_inserted_type = I.type
|
||||
last_amount_inserted = material_amount
|
||||
return material_amount
|
||||
|
||||
/datum/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only
|
||||
/datum/component/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only
|
||||
var/datum/material/M
|
||||
for(var/MAT in materials)
|
||||
M = materials[MAT]
|
||||
@@ -93,7 +144,7 @@
|
||||
|
||||
//For consuming material
|
||||
//mats is a list of types of material to use and the corresponding amounts, example: list(MAT_METAL=100, MAT_GLASS=200)
|
||||
/datum/material_container/proc/use_amount(list/mats, multiplier=1)
|
||||
/datum/component/material_container/proc/use_amount(list/mats, multiplier=1)
|
||||
if(!mats || !mats.len)
|
||||
return 0
|
||||
|
||||
@@ -112,7 +163,7 @@
|
||||
return total_amount_save - total_amount
|
||||
|
||||
|
||||
/datum/material_container/proc/use_amount_type(amt, id)
|
||||
/datum/component/material_container/proc/use_amount_type(amt, id)
|
||||
var/datum/material/M = materials[id]
|
||||
if(M)
|
||||
if(M.amount >= amt)
|
||||
@@ -121,7 +172,7 @@
|
||||
return amt
|
||||
return 0
|
||||
|
||||
/datum/material_container/proc/can_use_amount(amt, id, list/mats)
|
||||
/datum/component/material_container/proc/can_use_amount(amt, id, list/mats)
|
||||
if(amt && id)
|
||||
var/datum/material/M = materials[id]
|
||||
if(M && M.amount >= amt)
|
||||
@@ -136,7 +187,7 @@
|
||||
return FALSE
|
||||
|
||||
//For spawning mineral sheets; internal use only
|
||||
/datum/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null)
|
||||
/datum/component/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null)
|
||||
if(!M.sheet_type)
|
||||
return 0
|
||||
if(sheet_amt > 0)
|
||||
@@ -144,12 +195,12 @@
|
||||
sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT)
|
||||
var/count = 0
|
||||
while(sheet_amt > MAX_STACK_SIZE)
|
||||
new M.sheet_type(get_turf(owner), MAX_STACK_SIZE)
|
||||
new M.sheet_type(get_turf(parent), MAX_STACK_SIZE)
|
||||
count += MAX_STACK_SIZE
|
||||
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
|
||||
sheet_amt -= MAX_STACK_SIZE
|
||||
if(round((sheet_amt * MINERAL_MATERIAL_AMOUNT) / MINERAL_MATERIAL_AMOUNT))
|
||||
var/obj/item/stack/sheet/s = new M.sheet_type(get_turf(owner), sheet_amt)
|
||||
var/obj/item/stack/sheet/s = new M.sheet_type(get_turf(parent), sheet_amt)
|
||||
if(target)
|
||||
s.forceMove(target)
|
||||
count += sheet_amt
|
||||
@@ -157,15 +208,15 @@
|
||||
return count
|
||||
return 0
|
||||
|
||||
/datum/material_container/proc/retrieve_sheets(sheet_amt, id, target = null)
|
||||
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, id, target = null)
|
||||
if(materials[id])
|
||||
return retrieve(sheet_amt, materials[id], target)
|
||||
return 0
|
||||
|
||||
/datum/material_container/proc/retrieve_amount(amt, id, target)
|
||||
/datum/component/material_container/proc/retrieve_amount(amt, id, target)
|
||||
return retrieve_sheets(amount2sheet(amt), id, target)
|
||||
|
||||
/datum/material_container/proc/retrieve_all(target = null)
|
||||
/datum/component/material_container/proc/retrieve_all(target = null)
|
||||
var/result = 0
|
||||
var/datum/material/M
|
||||
for(var/MAT in materials)
|
||||
@@ -173,10 +224,10 @@
|
||||
result += retrieve_sheets(amount2sheet(M.amount), MAT, target)
|
||||
return result
|
||||
|
||||
/datum/material_container/proc/has_space(amt = 0)
|
||||
/datum/component/material_container/proc/has_space(amt = 0)
|
||||
return (total_amount + amt) <= max_amount
|
||||
|
||||
/datum/material_container/proc/has_materials(list/mats, multiplier=1)
|
||||
/datum/component/material_container/proc/has_materials(list/mats, multiplier=1)
|
||||
if(!mats || !mats.len)
|
||||
return 0
|
||||
|
||||
@@ -187,23 +238,23 @@
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/material_container/proc/amount2sheet(amt)
|
||||
/datum/component/material_container/proc/amount2sheet(amt)
|
||||
if(amt >= MINERAL_MATERIAL_AMOUNT)
|
||||
return round(amt / MINERAL_MATERIAL_AMOUNT)
|
||||
return 0
|
||||
|
||||
/datum/material_container/proc/sheet2amount(sheet_amt)
|
||||
/datum/component/material_container/proc/sheet2amount(sheet_amt)
|
||||
if(sheet_amt > 0)
|
||||
return sheet_amt * MINERAL_MATERIAL_AMOUNT
|
||||
return 0
|
||||
|
||||
/datum/material_container/proc/amount(id)
|
||||
/datum/component/material_container/proc/amount(id)
|
||||
var/datum/material/M = materials[id]
|
||||
return M ? M.amount : 0
|
||||
|
||||
//returns the amount of material relevant to this container;
|
||||
//if this container does not support glass, any glass in 'I' will not be taken into account
|
||||
/datum/material_container/proc/get_item_material_amount(obj/item/I)
|
||||
/datum/component/material_container/proc/get_item_material_amount(obj/item/I)
|
||||
if(!istype(I))
|
||||
return 0
|
||||
var/material_amount = 0
|
||||
@@ -0,0 +1,61 @@
|
||||
/datum/component/squeak
|
||||
var/static/list/default_squeak_sounds = list('sound/items/toysqueak1.ogg'=1, 'sound/items/toysqueak2.ogg'=1, 'sound/items/toysqueak3.ogg'=1)
|
||||
var/list/override_squeak_sounds
|
||||
var/squeak_chance = 100
|
||||
var/volume = 30
|
||||
|
||||
// This is so shoes don't squeak every step
|
||||
var/steps = 0
|
||||
var/step_delay = 1
|
||||
|
||||
// This is to stop squeak spam from inhand usage
|
||||
var/last_use = 0
|
||||
var/use_delay = 20
|
||||
|
||||
/datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override)
|
||||
if(custom_sounds)
|
||||
override_squeak_sounds = custom_sounds
|
||||
if(chance_override)
|
||||
squeak_chance = chance_override
|
||||
if(volume_override)
|
||||
volume = volume_override
|
||||
if(step_delay_override)
|
||||
step_delay = step_delay_override
|
||||
if(use_delay_override)
|
||||
use_delay = use_delay_override
|
||||
|
||||
if(istype(parent, /atom))
|
||||
RegisterSignal(COMSIG_ATOM_BLOB_ACT, .proc/play_squeak)
|
||||
RegisterSignal(COMSIG_ATOM_HULK_ATTACK, .proc/play_squeak)
|
||||
RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/play_squeak)
|
||||
if(istype(parent, /atom/movable))
|
||||
RegisterSignal(COMSIG_MOVABLE_CROSSED, .proc/play_squeak)
|
||||
RegisterSignal(COMSIG_MOVABLE_COLLIDE, .proc/play_squeak)
|
||||
RegisterSignal(COMSIG_MOVABLE_IMPACT, .proc/play_squeak)
|
||||
if(istype(parent, /obj/item))
|
||||
RegisterSignal(COMSIG_ITEM_ATTACK, .proc/play_squeak)
|
||||
RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/use_squeak)
|
||||
RegisterSignal(COMSIG_ITEM_ATTACK_OBJ, .proc/play_squeak)
|
||||
if(istype(parent, /obj/item/clothing/shoes))
|
||||
RegisterSignal(COMSIG_SHOES_STEP_ACTION, .proc/step_squeak)
|
||||
else
|
||||
RegisterSignal(COMSIG_ATOM_ENTERED, .proc/play_squeak)
|
||||
|
||||
/datum/component/squeak/proc/play_squeak()
|
||||
if(prob(squeak_chance))
|
||||
if(!override_squeak_sounds)
|
||||
playsound(parent, pickweight(default_squeak_sounds), volume, 1, -1)
|
||||
else
|
||||
playsound(parent, pickweight(override_squeak_sounds), volume, 1, -1)
|
||||
|
||||
/datum/component/squeak/proc/step_squeak()
|
||||
if(steps > step_delay)
|
||||
play_squeak()
|
||||
steps = 0
|
||||
else
|
||||
steps++
|
||||
|
||||
/datum/component/squeak/proc/use_squeak()
|
||||
if(last_use + use_delay < world.time)
|
||||
last_use = world.time
|
||||
play_squeak()
|
||||
+287
-287
@@ -1,287 +1,287 @@
|
||||
|
||||
/datum/datacore
|
||||
var/medical[] = list()
|
||||
var/medicalPrintCount = 0
|
||||
var/general[] = list()
|
||||
var/security[] = list()
|
||||
var/securityPrintCount = 0
|
||||
var/securityCrimeCounter = 0
|
||||
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
|
||||
var/locked[] = list()
|
||||
|
||||
/datum/data
|
||||
var/name = "data"
|
||||
|
||||
/datum/data/record
|
||||
name = "record"
|
||||
var/list/fields = list()
|
||||
|
||||
/datum/data/record/Destroy()
|
||||
if(src in GLOB.data_core.medical)
|
||||
GLOB.data_core.medical -= src
|
||||
if(src in GLOB.data_core.security)
|
||||
GLOB.data_core.security -= src
|
||||
if(src in GLOB.data_core.general)
|
||||
GLOB.data_core.general -= src
|
||||
if(src in GLOB.data_core.locked)
|
||||
GLOB.data_core.locked -= src
|
||||
. = ..()
|
||||
|
||||
/datum/data/crime
|
||||
name = "crime"
|
||||
var/crimeName = ""
|
||||
var/crimeDetails = ""
|
||||
var/author = ""
|
||||
var/time = ""
|
||||
var/dataId = 0
|
||||
|
||||
/datum/datacore/proc/createCrimeEntry(cname = "", cdetails = "", author = "", time = "")
|
||||
var/datum/data/crime/c = new /datum/data/crime
|
||||
c.crimeName = cname
|
||||
c.crimeDetails = cdetails
|
||||
c.author = author
|
||||
c.time = time
|
||||
c.dataId = ++securityCrimeCounter
|
||||
return c
|
||||
|
||||
/datum/datacore/proc/addMinorCrime(id = "", datum/data/crime/crime)
|
||||
for(var/datum/data/record/R in security)
|
||||
if(R.fields["id"] == id)
|
||||
var/list/crimes = R.fields["mi_crim"]
|
||||
crimes |= crime
|
||||
return
|
||||
|
||||
/datum/datacore/proc/removeMinorCrime(id, cDataId)
|
||||
for(var/datum/data/record/R in security)
|
||||
if(R.fields["id"] == id)
|
||||
var/list/crimes = R.fields["mi_crim"]
|
||||
for(var/datum/data/crime/crime in crimes)
|
||||
if(crime.dataId == text2num(cDataId))
|
||||
crimes -= crime
|
||||
return
|
||||
|
||||
/datum/datacore/proc/removeMajorCrime(id, cDataId)
|
||||
for(var/datum/data/record/R in security)
|
||||
if(R.fields["id"] == id)
|
||||
var/list/crimes = R.fields["ma_crim"]
|
||||
for(var/datum/data/crime/crime in crimes)
|
||||
if(crime.dataId == text2num(cDataId))
|
||||
crimes -= crime
|
||||
return
|
||||
|
||||
/datum/datacore/proc/addMajorCrime(id = "", datum/data/crime/crime)
|
||||
for(var/datum/data/record/R in security)
|
||||
if(R.fields["id"] == id)
|
||||
var/list/crimes = R.fields["ma_crim"]
|
||||
crimes |= crime
|
||||
return
|
||||
|
||||
/datum/datacore/proc/manifest()
|
||||
for(var/mob/dead/new_player/N in GLOB.player_list)
|
||||
if(ishuman(N.new_character))
|
||||
manifest_inject(N.new_character, N.client)
|
||||
CHECK_TICK
|
||||
|
||||
/datum/datacore/proc/manifest_modify(name, assignment)
|
||||
var/datum/data/record/foundrecord = find_record("name", name, GLOB.data_core.general)
|
||||
if(foundrecord)
|
||||
foundrecord.fields["rank"] = assignment
|
||||
|
||||
/datum/datacore/proc/get_manifest(monochrome, OOC)
|
||||
var/list/heads = list()
|
||||
var/list/sec = list()
|
||||
var/list/eng = list()
|
||||
var/list/med = list()
|
||||
var/list/sci = list()
|
||||
var/list/sup = list()
|
||||
var/list/civ = list()
|
||||
var/list/bot = list()
|
||||
var/list/misc = list()
|
||||
var/dat = {"
|
||||
<head><style>
|
||||
.manifest {border-collapse:collapse;}
|
||||
.manifest td, th {border:1px solid [monochrome?"black":"#DEF; background-color:white; color:black"]; padding:.25em}
|
||||
.manifest th {height: 2em; [monochrome?"border-top-width: 3px":"background-color: #48C; color:white"]}
|
||||
.manifest tr.head th { [monochrome?"border-top-width: 1px":"background-color: #488;"] }
|
||||
.manifest td:first-child {text-align:right}
|
||||
.manifest tr.alt td {[monochrome?"border-top-width: 2px":"background-color: #DEF"]}
|
||||
</style></head>
|
||||
<table class="manifest" width='350px'>
|
||||
<tr class='head'><th>Name</th><th>Rank</th></tr>
|
||||
"}
|
||||
var/even = 0
|
||||
// sort mobs
|
||||
for(var/datum/data/record/t in GLOB.data_core.general)
|
||||
var/name = t.fields["name"]
|
||||
var/rank = t.fields["rank"]
|
||||
var/department = 0
|
||||
if(rank in GLOB.command_positions)
|
||||
heads[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.security_positions)
|
||||
sec[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.engineering_positions)
|
||||
eng[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.medical_positions)
|
||||
med[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.science_positions)
|
||||
sci[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.supply_positions)
|
||||
sup[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.civilian_positions)
|
||||
civ[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.nonhuman_positions)
|
||||
bot[name] = rank
|
||||
department = 1
|
||||
if(!department && !(name in heads))
|
||||
misc[name] = rank
|
||||
if(heads.len > 0)
|
||||
dat += "<tr><th colspan=3>Heads</th></tr>"
|
||||
for(var/name in heads)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[heads[name]]</td></tr>"
|
||||
even = !even
|
||||
if(sec.len > 0)
|
||||
dat += "<tr><th colspan=3>Security</th></tr>"
|
||||
for(var/name in sec)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sec[name]]</td></tr>"
|
||||
even = !even
|
||||
if(eng.len > 0)
|
||||
dat += "<tr><th colspan=3>Engineering</th></tr>"
|
||||
for(var/name in eng)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[eng[name]]</td></tr>"
|
||||
even = !even
|
||||
if(med.len > 0)
|
||||
dat += "<tr><th colspan=3>Medical</th></tr>"
|
||||
for(var/name in med)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[med[name]]</td></tr>"
|
||||
even = !even
|
||||
if(sci.len > 0)
|
||||
dat += "<tr><th colspan=3>Science</th></tr>"
|
||||
for(var/name in sci)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sci[name]]</td></tr>"
|
||||
even = !even
|
||||
if(sup.len > 0)
|
||||
dat += "<tr><th colspan=3>Supply</th></tr>"
|
||||
for(var/name in sup)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sup[name]]</td></tr>"
|
||||
even = !even
|
||||
if(civ.len > 0)
|
||||
dat += "<tr><th colspan=3>Civilian</th></tr>"
|
||||
for(var/name in civ)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[civ[name]]</td></tr>"
|
||||
even = !even
|
||||
// in case somebody is insane and added them to the manifest, why not
|
||||
if(bot.len > 0)
|
||||
dat += "<tr><th colspan=3>Silicon</th></tr>"
|
||||
for(var/name in bot)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[bot[name]]</td></tr>"
|
||||
even = !even
|
||||
// misc guys
|
||||
if(misc.len > 0)
|
||||
dat += "<tr><th colspan=3>Miscellaneous</th></tr>"
|
||||
for(var/name in misc)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[misc[name]]</td></tr>"
|
||||
even = !even
|
||||
|
||||
dat += "</table>"
|
||||
dat = replacetext(dat, "\n", "")
|
||||
dat = replacetext(dat, "\t", "")
|
||||
return dat
|
||||
|
||||
|
||||
/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H, client/C)
|
||||
if(H.mind && (H.mind.assigned_role != H.mind.special_role))
|
||||
var/assignment
|
||||
if(H.mind.assigned_role)
|
||||
assignment = H.mind.assigned_role
|
||||
else if(H.job)
|
||||
assignment = H.job
|
||||
else
|
||||
assignment = "Unassigned"
|
||||
|
||||
var/static/record_id_num = 1001
|
||||
var/id = num2hex(record_id_num++,6)
|
||||
if(!C)
|
||||
C = H.client
|
||||
var/image = get_id_photo(H, C)
|
||||
var/obj/item/photo/photo_front = new()
|
||||
var/obj/item/photo/photo_side = new()
|
||||
photo_front.photocreate(null, icon(image, dir = SOUTH))
|
||||
photo_side.photocreate(null, icon(image, dir = WEST))
|
||||
|
||||
//These records should ~really~ be merged or something
|
||||
//General Record
|
||||
var/datum/data/record/G = new()
|
||||
G.fields["id"] = id
|
||||
G.fields["name"] = H.real_name
|
||||
G.fields["rank"] = assignment
|
||||
G.fields["age"] = H.age
|
||||
if(config.mutant_races)
|
||||
G.fields["species"] = H.dna.species.name
|
||||
G.fields["fingerprint"] = md5(H.dna.uni_identity)
|
||||
G.fields["p_stat"] = "Active"
|
||||
G.fields["m_stat"] = "Stable"
|
||||
G.fields["sex"] = H.gender
|
||||
G.fields["photo_front"] = photo_front
|
||||
G.fields["photo_side"] = photo_side
|
||||
general += G
|
||||
|
||||
//Medical Record
|
||||
var/datum/data/record/M = new()
|
||||
M.fields["id"] = id
|
||||
M.fields["name"] = H.real_name
|
||||
M.fields["blood_type"] = H.dna.blood_type
|
||||
M.fields["b_dna"] = H.dna.unique_enzymes
|
||||
M.fields["mi_dis"] = "None"
|
||||
M.fields["mi_dis_d"] = "No minor disabilities have been declared."
|
||||
M.fields["ma_dis"] = "None"
|
||||
M.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
|
||||
M.fields["alg"] = "None"
|
||||
M.fields["alg_d"] = "No allergies have been detected in this patient."
|
||||
M.fields["cdi"] = "None"
|
||||
M.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
|
||||
M.fields["notes"] = "No notes."
|
||||
medical += M
|
||||
|
||||
//Security Record
|
||||
var/datum/data/record/S = new()
|
||||
S.fields["id"] = id
|
||||
S.fields["name"] = H.real_name
|
||||
S.fields["criminal"] = "None"
|
||||
S.fields["mi_crim"] = list()
|
||||
S.fields["ma_crim"] = list()
|
||||
S.fields["notes"] = "No notes."
|
||||
security += S
|
||||
|
||||
//Locked Record
|
||||
var/datum/data/record/L = new()
|
||||
L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") //surely this should just be id, like the others?
|
||||
L.fields["name"] = H.real_name
|
||||
L.fields["rank"] = H.mind.assigned_role
|
||||
L.fields["age"] = H.age
|
||||
L.fields["sex"] = H.gender
|
||||
L.fields["blood_type"] = H.dna.blood_type
|
||||
L.fields["b_dna"] = H.dna.unique_enzymes
|
||||
L.fields["enzymes"] = H.dna.struc_enzymes
|
||||
L.fields["identity"] = H.dna.uni_identity
|
||||
L.fields["species"] = H.dna.species.type
|
||||
L.fields["features"] = H.dna.features
|
||||
L.fields["image"] = image
|
||||
L.fields["reference"] = H
|
||||
locked += L
|
||||
return
|
||||
|
||||
/datum/datacore/proc/get_id_photo(mob/living/carbon/human/H, client/C)
|
||||
var/datum/job/J = SSjob.GetJob(H.mind.assigned_role)
|
||||
var/datum/preferences/P
|
||||
if(!C)
|
||||
C = H.client
|
||||
if(C)
|
||||
P = C.prefs
|
||||
return get_flat_human_icon(null, J, P)
|
||||
/datum/datacore
|
||||
var/medical[] = list()
|
||||
var/medicalPrintCount = 0
|
||||
var/general[] = list()
|
||||
var/security[] = list()
|
||||
var/securityPrintCount = 0
|
||||
var/securityCrimeCounter = 0
|
||||
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
|
||||
var/locked[] = list()
|
||||
|
||||
/datum/data
|
||||
var/name = "data"
|
||||
|
||||
/datum/data/record
|
||||
name = "record"
|
||||
var/list/fields = list()
|
||||
|
||||
/datum/data/record/Destroy()
|
||||
if(src in GLOB.data_core.medical)
|
||||
GLOB.data_core.medical -= src
|
||||
if(src in GLOB.data_core.security)
|
||||
GLOB.data_core.security -= src
|
||||
if(src in GLOB.data_core.general)
|
||||
GLOB.data_core.general -= src
|
||||
if(src in GLOB.data_core.locked)
|
||||
GLOB.data_core.locked -= src
|
||||
. = ..()
|
||||
|
||||
/datum/data/crime
|
||||
name = "crime"
|
||||
var/crimeName = ""
|
||||
var/crimeDetails = ""
|
||||
var/author = ""
|
||||
var/time = ""
|
||||
var/dataId = 0
|
||||
|
||||
/datum/datacore/proc/createCrimeEntry(cname = "", cdetails = "", author = "", time = "")
|
||||
var/datum/data/crime/c = new /datum/data/crime
|
||||
c.crimeName = cname
|
||||
c.crimeDetails = cdetails
|
||||
c.author = author
|
||||
c.time = time
|
||||
c.dataId = ++securityCrimeCounter
|
||||
return c
|
||||
|
||||
/datum/datacore/proc/addMinorCrime(id = "", datum/data/crime/crime)
|
||||
for(var/datum/data/record/R in security)
|
||||
if(R.fields["id"] == id)
|
||||
var/list/crimes = R.fields["mi_crim"]
|
||||
crimes |= crime
|
||||
return
|
||||
|
||||
/datum/datacore/proc/removeMinorCrime(id, cDataId)
|
||||
for(var/datum/data/record/R in security)
|
||||
if(R.fields["id"] == id)
|
||||
var/list/crimes = R.fields["mi_crim"]
|
||||
for(var/datum/data/crime/crime in crimes)
|
||||
if(crime.dataId == text2num(cDataId))
|
||||
crimes -= crime
|
||||
return
|
||||
|
||||
/datum/datacore/proc/removeMajorCrime(id, cDataId)
|
||||
for(var/datum/data/record/R in security)
|
||||
if(R.fields["id"] == id)
|
||||
var/list/crimes = R.fields["ma_crim"]
|
||||
for(var/datum/data/crime/crime in crimes)
|
||||
if(crime.dataId == text2num(cDataId))
|
||||
crimes -= crime
|
||||
return
|
||||
|
||||
/datum/datacore/proc/addMajorCrime(id = "", datum/data/crime/crime)
|
||||
for(var/datum/data/record/R in security)
|
||||
if(R.fields["id"] == id)
|
||||
var/list/crimes = R.fields["ma_crim"]
|
||||
crimes |= crime
|
||||
return
|
||||
|
||||
/datum/datacore/proc/manifest()
|
||||
for(var/mob/dead/new_player/N in GLOB.player_list)
|
||||
if(ishuman(N.new_character))
|
||||
manifest_inject(N.new_character, N.client)
|
||||
CHECK_TICK
|
||||
|
||||
/datum/datacore/proc/manifest_modify(name, assignment)
|
||||
var/datum/data/record/foundrecord = find_record("name", name, GLOB.data_core.general)
|
||||
if(foundrecord)
|
||||
foundrecord.fields["rank"] = assignment
|
||||
|
||||
/datum/datacore/proc/get_manifest(monochrome, OOC)
|
||||
var/list/heads = list()
|
||||
var/list/sec = list()
|
||||
var/list/eng = list()
|
||||
var/list/med = list()
|
||||
var/list/sci = list()
|
||||
var/list/sup = list()
|
||||
var/list/civ = list()
|
||||
var/list/bot = list()
|
||||
var/list/misc = list()
|
||||
var/dat = {"
|
||||
<head><style>
|
||||
.manifest {border-collapse:collapse;}
|
||||
.manifest td, th {border:1px solid [monochrome?"black":"#DEF; background-color:white; color:black"]; padding:.25em}
|
||||
.manifest th {height: 2em; [monochrome?"border-top-width: 3px":"background-color: #48C; color:white"]}
|
||||
.manifest tr.head th { [monochrome?"border-top-width: 1px":"background-color: #488;"] }
|
||||
.manifest td:first-child {text-align:right}
|
||||
.manifest tr.alt td {[monochrome?"border-top-width: 2px":"background-color: #DEF"]}
|
||||
</style></head>
|
||||
<table class="manifest" width='350px'>
|
||||
<tr class='head'><th>Name</th><th>Rank</th></tr>
|
||||
"}
|
||||
var/even = 0
|
||||
// sort mobs
|
||||
for(var/datum/data/record/t in GLOB.data_core.general)
|
||||
var/name = t.fields["name"]
|
||||
var/rank = t.fields["rank"]
|
||||
var/department = 0
|
||||
if(rank in GLOB.command_positions)
|
||||
heads[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.security_positions)
|
||||
sec[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.engineering_positions)
|
||||
eng[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.medical_positions)
|
||||
med[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.science_positions)
|
||||
sci[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.supply_positions)
|
||||
sup[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.civilian_positions)
|
||||
civ[name] = rank
|
||||
department = 1
|
||||
if(rank in GLOB.nonhuman_positions)
|
||||
bot[name] = rank
|
||||
department = 1
|
||||
if(!department && !(name in heads))
|
||||
misc[name] = rank
|
||||
if(heads.len > 0)
|
||||
dat += "<tr><th colspan=3>Heads</th></tr>"
|
||||
for(var/name in heads)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[heads[name]]</td></tr>"
|
||||
even = !even
|
||||
if(sec.len > 0)
|
||||
dat += "<tr><th colspan=3>Security</th></tr>"
|
||||
for(var/name in sec)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sec[name]]</td></tr>"
|
||||
even = !even
|
||||
if(eng.len > 0)
|
||||
dat += "<tr><th colspan=3>Engineering</th></tr>"
|
||||
for(var/name in eng)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[eng[name]]</td></tr>"
|
||||
even = !even
|
||||
if(med.len > 0)
|
||||
dat += "<tr><th colspan=3>Medical</th></tr>"
|
||||
for(var/name in med)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[med[name]]</td></tr>"
|
||||
even = !even
|
||||
if(sci.len > 0)
|
||||
dat += "<tr><th colspan=3>Science</th></tr>"
|
||||
for(var/name in sci)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sci[name]]</td></tr>"
|
||||
even = !even
|
||||
if(sup.len > 0)
|
||||
dat += "<tr><th colspan=3>Supply</th></tr>"
|
||||
for(var/name in sup)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[sup[name]]</td></tr>"
|
||||
even = !even
|
||||
if(civ.len > 0)
|
||||
dat += "<tr><th colspan=3>Civilian</th></tr>"
|
||||
for(var/name in civ)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[civ[name]]</td></tr>"
|
||||
even = !even
|
||||
// in case somebody is insane and added them to the manifest, why not
|
||||
if(bot.len > 0)
|
||||
dat += "<tr><th colspan=3>Silicon</th></tr>"
|
||||
for(var/name in bot)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[bot[name]]</td></tr>"
|
||||
even = !even
|
||||
// misc guys
|
||||
if(misc.len > 0)
|
||||
dat += "<tr><th colspan=3>Miscellaneous</th></tr>"
|
||||
for(var/name in misc)
|
||||
dat += "<tr[even ? " class='alt'" : ""]><td>[name]</td><td>[misc[name]]</td></tr>"
|
||||
even = !even
|
||||
|
||||
dat += "</table>"
|
||||
dat = replacetext(dat, "\n", "")
|
||||
dat = replacetext(dat, "\t", "")
|
||||
return dat
|
||||
|
||||
|
||||
/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H, client/C)
|
||||
set waitfor = FALSE
|
||||
if(H.mind && (H.mind.assigned_role != H.mind.special_role))
|
||||
var/assignment
|
||||
if(H.mind.assigned_role)
|
||||
assignment = H.mind.assigned_role
|
||||
else if(H.job)
|
||||
assignment = H.job
|
||||
else
|
||||
assignment = "Unassigned"
|
||||
|
||||
var/static/record_id_num = 1001
|
||||
var/id = num2hex(record_id_num++,6)
|
||||
if(!C)
|
||||
C = H.client
|
||||
var/image = get_id_photo(H, C)
|
||||
var/obj/item/photo/photo_front = new()
|
||||
var/obj/item/photo/photo_side = new()
|
||||
photo_front.photocreate(null, icon(image, dir = SOUTH))
|
||||
photo_side.photocreate(null, icon(image, dir = WEST))
|
||||
|
||||
//These records should ~really~ be merged or something
|
||||
//General Record
|
||||
var/datum/data/record/G = new()
|
||||
G.fields["id"] = id
|
||||
G.fields["name"] = H.real_name
|
||||
G.fields["rank"] = assignment
|
||||
G.fields["age"] = H.age
|
||||
if(config.mutant_races)
|
||||
G.fields["species"] = H.dna.species.name
|
||||
G.fields["fingerprint"] = md5(H.dna.uni_identity)
|
||||
G.fields["p_stat"] = "Active"
|
||||
G.fields["m_stat"] = "Stable"
|
||||
G.fields["sex"] = H.gender
|
||||
G.fields["photo_front"] = photo_front
|
||||
G.fields["photo_side"] = photo_side
|
||||
general += G
|
||||
|
||||
//Medical Record
|
||||
var/datum/data/record/M = new()
|
||||
M.fields["id"] = id
|
||||
M.fields["name"] = H.real_name
|
||||
M.fields["blood_type"] = H.dna.blood_type
|
||||
M.fields["b_dna"] = H.dna.unique_enzymes
|
||||
M.fields["mi_dis"] = "None"
|
||||
M.fields["mi_dis_d"] = "No minor disabilities have been declared."
|
||||
M.fields["ma_dis"] = "None"
|
||||
M.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
|
||||
M.fields["alg"] = "None"
|
||||
M.fields["alg_d"] = "No allergies have been detected in this patient."
|
||||
M.fields["cdi"] = "None"
|
||||
M.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
|
||||
M.fields["notes"] = "No notes."
|
||||
medical += M
|
||||
|
||||
//Security Record
|
||||
var/datum/data/record/S = new()
|
||||
S.fields["id"] = id
|
||||
S.fields["name"] = H.real_name
|
||||
S.fields["criminal"] = "None"
|
||||
S.fields["mi_crim"] = list()
|
||||
S.fields["ma_crim"] = list()
|
||||
S.fields["notes"] = "No notes."
|
||||
security += S
|
||||
|
||||
//Locked Record
|
||||
var/datum/data/record/L = new()
|
||||
L.fields["id"] = md5("[H.real_name][H.mind.assigned_role]") //surely this should just be id, like the others?
|
||||
L.fields["name"] = H.real_name
|
||||
L.fields["rank"] = H.mind.assigned_role
|
||||
L.fields["age"] = H.age
|
||||
L.fields["sex"] = H.gender
|
||||
L.fields["blood_type"] = H.dna.blood_type
|
||||
L.fields["b_dna"] = H.dna.unique_enzymes
|
||||
L.fields["enzymes"] = H.dna.struc_enzymes
|
||||
L.fields["identity"] = H.dna.uni_identity
|
||||
L.fields["species"] = H.dna.species.type
|
||||
L.fields["features"] = H.dna.features
|
||||
L.fields["image"] = image
|
||||
L.fields["mindref"] = H.mind
|
||||
locked += L
|
||||
return
|
||||
|
||||
/datum/datacore/proc/get_id_photo(mob/living/carbon/human/H, client/C)
|
||||
var/datum/job/J = SSjob.GetJob(H.mind.assigned_role)
|
||||
var/datum/preferences/P
|
||||
if(!C)
|
||||
C = H.client
|
||||
if(C)
|
||||
P = C.prefs
|
||||
return get_flat_human_icon(null, J, P, DUMMY_HUMAN_SLOT_MANIFEST)
|
||||
|
||||
@@ -83,10 +83,10 @@
|
||||
if(isliving(A))
|
||||
atomsnowflake += "<a href='?_src_=vars;[HrefToken()];rename=[refid]'><b>[D]</b></a>"
|
||||
if(A.dir)
|
||||
atomsnowflake += "<br><font size='1'><a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=left'><<</a> <a href='?_src_=vars;datumedit=[refid];varnameedit=dir'>[dir2text(A.dir)]</a> <a href='?_src_=vars;rotatedatum=[refid];rotatedir=right'>>></a></font>"
|
||||
atomsnowflake += "<br><font size='1'><a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=left'><<</a> <a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=dir'>[dir2text(A.dir)]</a> <a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=right'>>></a></font>"
|
||||
var/mob/living/M = A
|
||||
atomsnowflake += {"
|
||||
<br><font size='1'><a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=ckey'>[M.ckey ? M.ckey : "No ckey"]</a> / <a href='?_src_=vars;datumedit=[refid];varnameedit=real_name'>[M.real_name ? M.real_name : "No real name"]</a></font>
|
||||
<br><font size='1'><a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=ckey'>[M.ckey ? M.ckey : "No ckey"]</a> / <a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=real_name'>[M.real_name ? M.real_name : "No real name"]</a></font>
|
||||
<br><font size='1'>
|
||||
BRUTE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brute'>[M.getBruteLoss()]</a>
|
||||
FIRE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=fire'>[M.getFireLoss()]</a>
|
||||
|
||||
@@ -245,7 +245,6 @@
|
||||
/datum/disease/advance/proc/GenerateCure()
|
||||
if(properties && properties.len)
|
||||
var/res = Clamp(properties["resistance"] - (symptoms.len / 2), 1, advance_cures.len)
|
||||
//to_chat(world, "Res = [res]")
|
||||
cures = list(advance_cures[res])
|
||||
|
||||
// Get the cure name from the cure_id
|
||||
@@ -333,9 +332,6 @@
|
||||
|
||||
// Mix a list of advance diseases and return the mixed result.
|
||||
/proc/Advance_Mix(var/list/D_list)
|
||||
|
||||
//to_chat(world, "Mixing!!!!")
|
||||
|
||||
var/list/diseases = list()
|
||||
|
||||
for(var/datum/disease/advance/A in D_list)
|
||||
@@ -359,7 +355,6 @@
|
||||
D2.Mix(D1)
|
||||
|
||||
// Should be only 1 entry left, but if not let's only return a single entry
|
||||
//to_chat(world, "END MIXING!!!!!")
|
||||
var/datum/disease/advance/to_return = pick(diseases)
|
||||
to_return.Refresh(1)
|
||||
return to_return
|
||||
|
||||
@@ -1,74 +1,74 @@
|
||||
/datum/disease/dnaspread
|
||||
name = "Space Retrovirus"
|
||||
max_stages = 4
|
||||
spread_text = "On contact"
|
||||
spread_flags = CONTACT_GENERAL
|
||||
cure_text = "Mutadone"
|
||||
cures = list("mutadone")
|
||||
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
|
||||
agent = "S4E1 retrovirus"
|
||||
viable_mobtypes = list(/mob/living/carbon/human)
|
||||
var/datum/dna/original_dna = null
|
||||
var/transformed = 0
|
||||
desc = "This disease transplants the genetic code of the initial vector into new hosts."
|
||||
severity = MEDIUM
|
||||
|
||||
|
||||
/datum/disease/dnaspread/stage_act()
|
||||
..()
|
||||
if(!affected_mob.dna)
|
||||
cure()
|
||||
if(NOTRANSSTING in affected_mob.dna.species.species_traits) //Only species that can be spread by transformation sting can be spread by the retrovirus
|
||||
cure()
|
||||
|
||||
if(!strain_data["dna"])
|
||||
//Absorbs the target DNA.
|
||||
strain_data["dna"] = new affected_mob.dna.type
|
||||
affected_mob.dna.copy_dna(strain_data["dna"])
|
||||
/datum/disease/dnaspread
|
||||
name = "Space Retrovirus"
|
||||
max_stages = 4
|
||||
spread_text = "On contact"
|
||||
spread_flags = CONTACT_GENERAL
|
||||
cure_text = "Mutadone"
|
||||
cures = list("mutadone")
|
||||
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
|
||||
agent = "S4E1 retrovirus"
|
||||
viable_mobtypes = list(/mob/living/carbon/human)
|
||||
var/datum/dna/original_dna = null
|
||||
var/transformed = 0
|
||||
desc = "This disease transplants the genetic code of the initial vector into new hosts."
|
||||
severity = MEDIUM
|
||||
|
||||
|
||||
/datum/disease/dnaspread/stage_act()
|
||||
..()
|
||||
if(!affected_mob.dna)
|
||||
cure()
|
||||
if((NOTRANSSTING in affected_mob.dna.species.species_traits) || (NO_DNA_COPY in affected_mob.dna.species.species_traits)) //Only species that can be spread by transformation sting can be spread by the retrovirus
|
||||
cure()
|
||||
|
||||
if(!strain_data["dna"])
|
||||
//Absorbs the target DNA.
|
||||
strain_data["dna"] = new affected_mob.dna.type
|
||||
affected_mob.dna.copy_dna(strain_data["dna"])
|
||||
carrier = TRUE
|
||||
stage = 4
|
||||
return
|
||||
|
||||
switch(stage)
|
||||
if(2 || 3) //Pretend to be a cold and give time to spread.
|
||||
if(prob(8))
|
||||
affected_mob.emote("sneeze")
|
||||
if(prob(8))
|
||||
affected_mob.emote("cough")
|
||||
if(prob(1))
|
||||
to_chat(affected_mob, "<span class='danger'>Your muscles ache.</span>")
|
||||
if(prob(20))
|
||||
affected_mob.take_bodypart_damage(1)
|
||||
if(prob(1))
|
||||
to_chat(affected_mob, "<span class='danger'>Your stomach hurts.</span>")
|
||||
if(prob(20))
|
||||
affected_mob.adjustToxLoss(2)
|
||||
affected_mob.updatehealth()
|
||||
if(4)
|
||||
if(!transformed && !carrier)
|
||||
//Save original dna for when the disease is cured.
|
||||
original_dna = new affected_mob.dna.type
|
||||
affected_mob.dna.copy_dna(original_dna)
|
||||
|
||||
to_chat(affected_mob, "<span class='danger'>You don't feel like yourself..</span>")
|
||||
var/datum/dna/transform_dna = strain_data["dna"]
|
||||
|
||||
transform_dna.transfer_identity(affected_mob, transfer_SE = 1)
|
||||
affected_mob.real_name = affected_mob.dna.real_name
|
||||
affected_mob.updateappearance(mutcolor_update=1)
|
||||
affected_mob.domutcheck()
|
||||
|
||||
transformed = 1
|
||||
carrier = 1 //Just chill out at stage 4
|
||||
|
||||
return
|
||||
|
||||
/datum/disease/dnaspread/Destroy()
|
||||
if (original_dna && transformed && affected_mob)
|
||||
original_dna.transfer_identity(affected_mob, transfer_SE = 1)
|
||||
affected_mob.real_name = affected_mob.dna.real_name
|
||||
affected_mob.updateappearance(mutcolor_update=1)
|
||||
affected_mob.domutcheck()
|
||||
|
||||
to_chat(affected_mob, "<span class='notice'>You feel more like yourself.</span>")
|
||||
return ..()
|
||||
return
|
||||
|
||||
switch(stage)
|
||||
if(2 || 3) //Pretend to be a cold and give time to spread.
|
||||
if(prob(8))
|
||||
affected_mob.emote("sneeze")
|
||||
if(prob(8))
|
||||
affected_mob.emote("cough")
|
||||
if(prob(1))
|
||||
to_chat(affected_mob, "<span class='danger'>Your muscles ache.</span>")
|
||||
if(prob(20))
|
||||
affected_mob.take_bodypart_damage(1)
|
||||
if(prob(1))
|
||||
to_chat(affected_mob, "<span class='danger'>Your stomach hurts.</span>")
|
||||
if(prob(20))
|
||||
affected_mob.adjustToxLoss(2)
|
||||
affected_mob.updatehealth()
|
||||
if(4)
|
||||
if(!transformed && !carrier)
|
||||
//Save original dna for when the disease is cured.
|
||||
original_dna = new affected_mob.dna.type
|
||||
affected_mob.dna.copy_dna(original_dna)
|
||||
|
||||
to_chat(affected_mob, "<span class='danger'>You don't feel like yourself..</span>")
|
||||
var/datum/dna/transform_dna = strain_data["dna"]
|
||||
|
||||
transform_dna.transfer_identity(affected_mob, transfer_SE = 1)
|
||||
affected_mob.real_name = affected_mob.dna.real_name
|
||||
affected_mob.updateappearance(mutcolor_update=1)
|
||||
affected_mob.domutcheck()
|
||||
|
||||
transformed = 1
|
||||
carrier = 1 //Just chill out at stage 4
|
||||
|
||||
return
|
||||
|
||||
/datum/disease/dnaspread/Destroy()
|
||||
if (original_dna && transformed && affected_mob)
|
||||
original_dna.transfer_identity(affected_mob, transfer_SE = 1)
|
||||
affected_mob.real_name = affected_mob.dna.real_name
|
||||
affected_mob.updateappearance(mutcolor_update=1)
|
||||
affected_mob.domutcheck()
|
||||
|
||||
to_chat(affected_mob, "<span class='notice'>You feel more like yourself.</span>")
|
||||
return ..()
|
||||
|
||||
+4
-2
@@ -235,7 +235,9 @@
|
||||
flavor_text = dna.features["flavor_text"] //Update the flavor_text to use new dna text
|
||||
|
||||
if(mrace)
|
||||
set_species(mrace, icon_update=0)
|
||||
var/datum/species/newrace = new mrace.type
|
||||
newrace.copy_properties_from(mrace)
|
||||
set_species(newrace, icon_update=0)
|
||||
|
||||
if(newreal_name)
|
||||
real_name = newreal_name
|
||||
@@ -396,4 +398,4 @@
|
||||
value = values
|
||||
return value
|
||||
|
||||
/////////////////////////// DNA HELPER-PROCS
|
||||
/////////////////////////// DNA HELPER-PROCS
|
||||
@@ -21,6 +21,7 @@ GLOBAL_LIST_INIT(huds, list(
|
||||
ANTAG_HUD_SOULLESS = new/datum/atom_hud/antag/hidden(),
|
||||
ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(),
|
||||
ANTAG_HUD_BORER = new/datum/atom_hud/antag(),
|
||||
ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(),
|
||||
))
|
||||
|
||||
/datum/atom_hud
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
/datum/action/neck_chop/Trigger()
|
||||
if(owner.incapacitated())
|
||||
to_chat(owner, "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>")
|
||||
to_chat(owner, "<span class='warning'>You can't use [name] while you're incapacitated.</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if (H.mind.martial_art.streak == "neck_chop")
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
/datum/action/leg_sweep/Trigger()
|
||||
if(owner.incapacitated())
|
||||
to_chat(owner, "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>")
|
||||
to_chat(owner, "<span class='warning'>You can't use [name] while you're incapacitated.</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if (H.mind.martial_art.streak == "leg_sweep")
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
/datum/action/lung_punch/Trigger()
|
||||
if(owner.incapacitated())
|
||||
to_chat(owner, "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>")
|
||||
to_chat(owner, "<span class='warning'>You can't use [name] while you're incapacitated.</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if (H.mind.martial_art.streak == "quick_choke")
|
||||
@@ -57,14 +57,14 @@
|
||||
|
||||
/datum/martial_art/krav_maga/teach(mob/living/carbon/human/H,make_temporary=0)
|
||||
if(..())
|
||||
to_chat(H, "<span class = 'userdanger'>You know the arts of Krav Maga!</span>")
|
||||
to_chat(H, "<span class = 'userdanger'>You know the arts of [name]!</span>")
|
||||
to_chat(H, "<span class = 'danger'>Place your cursor over a move at the top of the screen to see what it does.</span>")
|
||||
neckchop.Grant(H)
|
||||
legsweep.Grant(H)
|
||||
lungpunch.Grant(H)
|
||||
|
||||
/datum/martial_art/krav_maga/on_remove(mob/living/carbon/human/H)
|
||||
to_chat(H, "<span class = 'userdanger'>You suddenly forget the arts of Krav Maga...</span>")
|
||||
to_chat(H, "<span class = 'userdanger'>You suddenly forget the arts of [name]...</span>")
|
||||
neckchop.Remove(H)
|
||||
legsweep.Remove(H)
|
||||
lungpunch.Remove(H)
|
||||
@@ -140,7 +140,7 @@
|
||||
playsound(get_turf(D), 'sound/effects/hit_punch.ogg', 50, 1, -1)
|
||||
D.visible_message("<span class='danger'>[A] [picked_hit_type] [D]!</span>", \
|
||||
"<span class='userdanger'>[A] [picked_hit_type] you!</span>")
|
||||
add_logs(A, D, "[picked_hit_type] with Krav Maga")
|
||||
add_logs(A, D, "[picked_hit_type] with [name]")
|
||||
return 1
|
||||
|
||||
/datum/martial_art/krav_maga/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
|
||||
|
||||
+44
-65
@@ -121,8 +121,9 @@
|
||||
new_character.key = key //now transfer the key to link the client to our new body
|
||||
if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs.
|
||||
var/mob/living/L = new_character
|
||||
L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting...
|
||||
L.update_arousal_hud() //Removes the old icon
|
||||
if(L.client && L.client.prefs)
|
||||
L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting...
|
||||
L.update_arousal_hud() //Removes the old icon
|
||||
|
||||
/datum/mind/proc/store_memory(new_text)
|
||||
memory += "[new_text]<BR>"
|
||||
@@ -131,10 +132,10 @@
|
||||
memory = null
|
||||
|
||||
// Datum antag mind procs
|
||||
/datum/mind/proc/add_antag_datum(datum_type)
|
||||
/datum/mind/proc/add_antag_datum(datum_type, team)
|
||||
if(!datum_type)
|
||||
return
|
||||
var/datum/antagonist/A = new datum_type(src)
|
||||
var/datum/antagonist/A = new datum_type(src, team)
|
||||
if(!A.can_be_owned(src))
|
||||
qdel(A)
|
||||
return
|
||||
@@ -194,6 +195,11 @@
|
||||
src.remove_antag_datum(ANTAG_DATUM_TRAITOR)
|
||||
SSticker.mode.update_traitor_icons_removed(src)
|
||||
|
||||
/datum/mind/proc/remove_brother()
|
||||
if(src in SSticker.mode.brothers)
|
||||
src.remove_antag_datum(ANTAG_DATUM_BROTHER)
|
||||
SSticker.mode.update_brother_icons_removed(src)
|
||||
|
||||
/datum/mind/proc/remove_nukeop()
|
||||
if(src in SSticker.mode.syndicates)
|
||||
SSticker.mode.syndicates -= src
|
||||
@@ -348,6 +354,12 @@
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/objective in objectives)
|
||||
output += "<br><B>Objective #[obj_count++]</B>: [objective.explanation_text]"
|
||||
var/list/datum/mind/other_owners = objective.get_owners() - src
|
||||
if(other_owners.len)
|
||||
output += "<ul>"
|
||||
for(var/datum/mind/M in other_owners)
|
||||
output += "<li>Conspirator: [M.name]</li>"
|
||||
output += "</ul>"
|
||||
|
||||
if(window)
|
||||
recipient << browse(output,"window=memory")
|
||||
@@ -384,7 +396,7 @@
|
||||
|
||||
/** TRAITOR ***/
|
||||
text = "traitor"
|
||||
if (SSticker.mode.config_tag=="traitor" || SSticker.mode.config_tag=="traitorchan")
|
||||
if (SSticker.mode.config_tag=="traitor" || SSticker.mode.config_tag=="traitorchan" || SSticker.mode.config_tag=="traitorbro")
|
||||
text = uppertext(text)
|
||||
text = "<i><b>[text]</b></i>: "
|
||||
if (src in SSticker.mode.traitors)
|
||||
@@ -404,6 +416,21 @@
|
||||
|
||||
if(ishuman(current) || ismonkey(current))
|
||||
|
||||
/** BROTHER **/
|
||||
text = "brother"
|
||||
if(SSticker.mode.config_tag == "traitorbro")
|
||||
text = uppertext(text)
|
||||
text = "<i><b>[text]</b></i>: "
|
||||
if(src in SSticker.mode.brothers)
|
||||
text += "<b>Brother</b> | <a href='?src=\ref[src];brother=clear'>no</a>"
|
||||
|
||||
if(current && current.client && (ROLE_BROTHER in current.client.prefs.be_special))
|
||||
text += " | Enabled in Prefs"
|
||||
else
|
||||
text += " | Disabled in Prefs"
|
||||
|
||||
sections["brother"] = text
|
||||
|
||||
/** CHANGELING ***/
|
||||
text = "changeling"
|
||||
if (SSticker.mode.config_tag=="changeling" || SSticker.mode.config_tag=="traitorchan")
|
||||
@@ -563,8 +590,6 @@
|
||||
if(src in SSticker.mode.abductors)
|
||||
text += "<b>Abductor</b> | <a href='?src=\ref[src];abductor=clear'>human</a>"
|
||||
text += " | <a href='?src=\ref[src];common=undress'>undress</a> | <a href='?src=\ref[src];abductor=equip'>equip</a>"
|
||||
else
|
||||
text += "<a href='?src=\ref[src];abductor=abductor'>abductor</a> | <b>human</b>"
|
||||
|
||||
if(current && current.client && (ROLE_ABDUCTOR in current.client.prefs.be_special))
|
||||
text += " | Enabled in Prefs"
|
||||
@@ -1031,7 +1056,7 @@
|
||||
log_admin("[key_name(usr)] has wizard'ed [current].")
|
||||
SSticker.mode.update_wiz_icons_added(src)
|
||||
if("lair")
|
||||
current.loc = pick(GLOB.wizardstart)
|
||||
current.forceMove(pick(GLOB.wizardstart))
|
||||
if("dressup")
|
||||
SSticker.mode.equip_wizard(current)
|
||||
if("name")
|
||||
@@ -1093,7 +1118,7 @@
|
||||
message_admins("[key_name_admin(usr)] has nuke op'ed [current].")
|
||||
log_admin("[key_name(usr)] has nuke op'ed [current].")
|
||||
if("lair")
|
||||
current.loc = get_turf(locate("landmark*Syndicate-Spawn"))
|
||||
current.forceMove(get_turf(locate("landmark*Syndicate-Spawn")))
|
||||
if("dressup")
|
||||
var/mob/living/carbon/human/H = current
|
||||
qdel(H.belt)
|
||||
@@ -1217,13 +1242,6 @@
|
||||
if("clear")
|
||||
to_chat(usr, "Not implemented yet. Sorry!")
|
||||
//SSticker.mode.update_abductor_icons_removed(src)
|
||||
if("abductor")
|
||||
if(!ishuman(current))
|
||||
to_chat(usr, "<span class='warning'>This only works on humans!</span>")
|
||||
return
|
||||
make_Abductor()
|
||||
log_admin("[key_name(usr)] turned [current] into abductor.")
|
||||
SSticker.mode.update_abductor_icons_added(src)
|
||||
if("equip")
|
||||
if(!ishuman(current))
|
||||
to_chat(usr, "<span class='warning'>This only works on humans!</span>")
|
||||
@@ -1252,7 +1270,6 @@
|
||||
src = null
|
||||
M = H.monkeyize()
|
||||
src = M.mind
|
||||
//to_chat(world, "DEBUG: \"healthy\": M=[M], M.mind=[M.mind], src=[src]!")
|
||||
else if (istype(M) && length(M.viruses))
|
||||
for(var/thing in M.viruses)
|
||||
var/datum/disease/D = thing
|
||||
@@ -1284,6 +1301,13 @@
|
||||
if(H)
|
||||
src = H.mind
|
||||
|
||||
else if (href_list["brother"])
|
||||
switch(href_list["brother"])
|
||||
if("clear")
|
||||
remove_brother()
|
||||
log_admin("[key_name(usr)] has de-brother'ed [current].")
|
||||
SSticker.mode.update_brother_icons_removed(src)
|
||||
|
||||
else if (href_list["silicon"])
|
||||
switch(href_list["silicon"])
|
||||
if("unemag")
|
||||
@@ -1368,7 +1392,7 @@
|
||||
current.faction |= "syndicate"
|
||||
|
||||
if(spawnloc)
|
||||
current.loc = spawnloc
|
||||
current.forceMove(spawnloc)
|
||||
|
||||
if(ishuman(current))
|
||||
var/mob/living/carbon/human/H = current
|
||||
@@ -1418,7 +1442,7 @@
|
||||
SSjob.SendToLateJoin(current)
|
||||
to_chat(current, "HOT INSERTION, GO GO GO")
|
||||
else
|
||||
current.loc = pick(GLOB.wizardstart)
|
||||
current.forceMove(pick(GLOB.wizardstart))
|
||||
|
||||
SSticker.mode.equip_wizard(current)
|
||||
SSticker.mode.name_wizard(current)
|
||||
@@ -1463,52 +1487,7 @@
|
||||
take_uplink()
|
||||
var/fail = 0
|
||||
fail |= !SSticker.mode.equip_revolutionary(current)
|
||||
|
||||
/datum/mind/proc/make_Abductor()
|
||||
var/role = alert("Abductor Role ?","Role","Agent","Scientist")
|
||||
var/team = input("Abductor Team ?","Team ?") in list(1,2,3,4)
|
||||
var/teleport = alert("Teleport to ship ?","Teleport","Yes","No")
|
||||
|
||||
if(!role || !team || !teleport)
|
||||
return
|
||||
|
||||
if(!ishuman(current))
|
||||
return
|
||||
|
||||
SSticker.mode.abductors |= src
|
||||
|
||||
var/datum/objective/experiment/O = new
|
||||
O.owner = src
|
||||
objectives += O
|
||||
|
||||
var/mob/living/carbon/human/H = current
|
||||
|
||||
H.set_species(/datum/species/abductor)
|
||||
var/datum/species/abductor/S = H.dna.species
|
||||
|
||||
if(role == "Scientist")
|
||||
S.scientist = TRUE
|
||||
S.team = team
|
||||
|
||||
var/list/obj/effect/landmark/abductor/agent_landmarks = new
|
||||
var/list/obj/effect/landmark/abductor/scientist_landmarks = new
|
||||
agent_landmarks.len = 4
|
||||
scientist_landmarks.len = 4
|
||||
for(var/obj/effect/landmark/abductor/A in GLOB.landmarks_list)
|
||||
if(istype(A, /obj/effect/landmark/abductor/agent))
|
||||
agent_landmarks[text2num(A.team)] = A
|
||||
else if(istype(A, /obj/effect/landmark/abductor/scientist))
|
||||
scientist_landmarks[text2num(A.team)] = A
|
||||
|
||||
var/obj/effect/landmark/L
|
||||
if(teleport=="Yes")
|
||||
switch(role)
|
||||
if("Agent")
|
||||
L = agent_landmarks[team]
|
||||
if("Scientist")
|
||||
L = scientist_landmarks[team]
|
||||
H.forceMove(L.loc)
|
||||
|
||||
|
||||
/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/S)
|
||||
spell_list += S
|
||||
S.action.Grant(current)
|
||||
|
||||
@@ -117,9 +117,10 @@ GLOBAL_LIST_EMPTY(mutations_list)
|
||||
|
||||
name = "Hulk"
|
||||
quality = POSITIVE
|
||||
dna_block = NON_SCANNABLE
|
||||
get_chance = 15
|
||||
lowest_value = 256 * 12
|
||||
text_gain_indication = "<span class='notice'>Your muscles hurt!</span>"
|
||||
species_allowed = list("human") //no skeleton/lizard hulk
|
||||
species_allowed = list("fly") //no skeleton/lizard hulk
|
||||
health_req = 25
|
||||
|
||||
/datum/mutation/human/hulk/on_acquiring(mob/living/carbon/human/owner)
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
bar.pixel_y = 32 + (PROGRESSBAR_HEIGHT * (listindex - 1))
|
||||
|
||||
/datum/progressbar/proc/update(progress)
|
||||
//to_chat(world, "Update [progress] - [goal] - [(progress / goal)] - [((progress / goal) * 100)] - [round(((progress / goal) * 100), 5)]")
|
||||
if (!user || !user.client)
|
||||
shown = 0
|
||||
return
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
id = "spacehotel"
|
||||
suffix = "spacehotel.dmm"
|
||||
name = "The Twin-Nexus Hotel"
|
||||
description = "A interstellar hotel, where the weary spaceman can rest their head and relax, assured that the residental staff will not murder them in their sleep. Probably."
|
||||
description = "An interstellar hotel, where the weary spaceman can rest their head and relax, assured that the residental staff will not murder them in their sleep. Probably."
|
||||
|
||||
/datum/map_template/ruin/space/turreted_outpost
|
||||
id = "turreted-outpost"
|
||||
|
||||
@@ -29,11 +29,20 @@
|
||||
/datum/status_effect/incapacitating/knockdown
|
||||
id = "knockdown"
|
||||
|
||||
/datum/status_effect/incapacitating/knockdown/tick()
|
||||
if(owner.staminaloss)
|
||||
owner.adjustStaminaLoss(-0.3) //reduce stamina loss by 0.3 per tick, 6 per 2 seconds
|
||||
|
||||
|
||||
//UNCONSCIOUS
|
||||
/datum/status_effect/incapacitating/unconscious
|
||||
id = "unconscious"
|
||||
needs_update_stat = TRUE
|
||||
|
||||
/datum/status_effect/incapacitating/unconscious/tick()
|
||||
if(owner.staminaloss)
|
||||
owner.adjustStaminaLoss(-0.3) //reduce stamina loss by 0.3 per tick, 6 per 2 seconds
|
||||
|
||||
//SLEEPING
|
||||
/datum/status_effect/incapacitating/sleeping
|
||||
id = "sleeping"
|
||||
@@ -57,7 +66,7 @@
|
||||
|
||||
/datum/status_effect/incapacitating/sleeping/tick()
|
||||
if(owner.staminaloss)
|
||||
owner.adjustStaminaLoss(-0.35) //reduce stamina loss by 0.35 per tick, 7 per 2 seconds
|
||||
owner.adjustStaminaLoss(-0.5) //reduce stamina loss by 0.5 per tick, 10 per 2 seconds
|
||||
if(human_owner && human_owner.drunkenness)
|
||||
human_owner.drunkenness *= 0.997 //reduce drunkenness by 0.3% per tick, 6% per 2 seconds
|
||||
if(prob(20))
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
/datum/weather/New()
|
||||
..()
|
||||
SSweather.existing_weather |= src
|
||||
SSweather.existing_weather += src
|
||||
|
||||
/datum/weather/Destroy()
|
||||
SSweather.existing_weather -= src
|
||||
@@ -108,7 +108,7 @@
|
||||
stage = END_STAGE
|
||||
update_areas()
|
||||
|
||||
/datum/weather/proc/can_impact(mob/living/L) //Can this weather impact a mob?
|
||||
/datum/weather/proc/can_weather_act(mob/living/L) //Can this weather impact a mob?
|
||||
var/turf/mob_turf = get_turf(L)
|
||||
if(mob_turf && (mob_turf.z != target_z))
|
||||
return
|
||||
@@ -118,7 +118,7 @@
|
||||
return
|
||||
return 1
|
||||
|
||||
/datum/weather/proc/impact(mob/living/L) //What effect does this weather have on the hapless mob?
|
||||
/datum/weather/proc/weather_act(mob/living/L) //What effect does this weather have on the hapless mob?
|
||||
return
|
||||
|
||||
/datum/weather/proc/update_areas()
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
//Different types of weather.
|
||||
|
||||
/datum/weather/floor_is_lava //The Floor is Lava: Makes all turfs damage anyone on them unless they're standing on a solid object.
|
||||
name = "the floor is lava"
|
||||
desc = "The ground turns into surprisingly cool lava, lightly damaging anything on the floor."
|
||||
|
||||
telegraph_message = "<span class='warning'>Waves of heat emanate from the ground...</span>"
|
||||
telegraph_duration = 150
|
||||
|
||||
weather_message = "<span class='userdanger'>The floor is lava! Get on top of something!</span>"
|
||||
weather_duration_lower = 300
|
||||
weather_duration_upper = 600
|
||||
weather_overlay = "lava"
|
||||
|
||||
end_message = "<span class='danger'>The ground cools and returns to its usual form.</span>"
|
||||
end_duration = 0
|
||||
|
||||
area_type = /area
|
||||
protected_areas = list(/area/space)
|
||||
target_z = ZLEVEL_STATION_PRIMARY
|
||||
|
||||
overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only
|
||||
immunity_type = "lava"
|
||||
|
||||
/datum/weather/floor_is_lava/impact(mob/living/L)
|
||||
for(var/obj/structure/O in L.loc)
|
||||
if(O.density)
|
||||
return
|
||||
if(L.loc.density)
|
||||
return
|
||||
if(!L.client) //Only sentient people are going along with it!
|
||||
return
|
||||
L.adjustFireLoss(3)
|
||||
|
||||
|
||||
/datum/weather/advanced_darkness //Advanced Darkness: Restricts the vision of all affected mobs to a single tile in the cardinal directions.
|
||||
name = "advanced darkness"
|
||||
desc = "Everything in the area is effectively blinded, unable to see more than a foot or so around itself."
|
||||
|
||||
telegraph_message = "<span class='warning'>The lights begin to dim... is the power going out?</span>"
|
||||
telegraph_duration = 150
|
||||
|
||||
weather_message = "<span class='userdanger'>This isn't your average everday darkness... this is <i>advanced</i> darkness!</span>"
|
||||
weather_duration_lower = 300
|
||||
weather_duration_upper = 300
|
||||
|
||||
end_message = "<span class='danger'>At last, the darkness recedes.</span>"
|
||||
end_duration = 0
|
||||
|
||||
area_type = /area
|
||||
target_z = ZLEVEL_STATION_PRIMARY
|
||||
|
||||
/datum/weather/advanced_darkness/update_areas()
|
||||
for(var/V in impacted_areas)
|
||||
var/area/A = V
|
||||
if(stage == MAIN_STAGE)
|
||||
A.invisibility = 0
|
||||
A.set_opacity(TRUE)
|
||||
A.layer = overlay_layer
|
||||
A.icon = 'icons/effects/weather_effects.dmi'
|
||||
A.icon_state = "darkness"
|
||||
else
|
||||
A.invisibility = INVISIBILITY_MAXIMUM
|
||||
A.set_opacity(FALSE)
|
||||
|
||||
|
||||
/datum/weather/ash_storm //Ash Storms: Common happenings on lavaland. Heavily obscures vision and deals heavy fire damage to anyone caught outside.
|
||||
name = "ash storm"
|
||||
desc = "An intense atmospheric storm lifts ash off of the planet's surface and billows it down across the area, dealing intense fire damage to the unprotected."
|
||||
|
||||
telegraph_message = "<span class='boldwarning'>An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter.</span>"
|
||||
telegraph_duration = 300
|
||||
telegraph_sound = 'sound/lavaland/ash_storm_windup.ogg'
|
||||
telegraph_overlay = "light_ash"
|
||||
|
||||
weather_message = "<span class='userdanger'><i>Smoldering clouds of scorching ash billow down around you! Get inside!</i></span>"
|
||||
weather_duration_lower = 600
|
||||
weather_duration_upper = 1500
|
||||
weather_sound = 'sound/lavaland/ash_storm_start.ogg'
|
||||
weather_overlay = "ash_storm"
|
||||
|
||||
end_message = "<span class='boldannounce'>The shrieking wind whips away the last of the ash and falls to its usual murmur. It should be safe to go outside now.</span>"
|
||||
end_duration = 300
|
||||
end_sound = 'sound/lavaland/ash_storm_end.ogg'
|
||||
end_overlay = "light_ash"
|
||||
|
||||
area_type = /area/lavaland/surface/outdoors
|
||||
target_z = ZLEVEL_LAVALAND
|
||||
|
||||
immunity_type = "ash"
|
||||
|
||||
probability = 90
|
||||
|
||||
/datum/weather/ash_storm/proc/is_ash_immune(mob/living/L)
|
||||
if(istype(L.loc, /obj/mecha)) //Mechs are immune
|
||||
return TRUE
|
||||
if(ishuman(L)) //Are you immune?
|
||||
var/mob/living/carbon/human/H = L
|
||||
var/thermal_protection = H.get_thermal_protection()
|
||||
if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT)
|
||||
return TRUE
|
||||
if(istype(L.loc, /mob/living) && L.loc != L) //Matryoshka check
|
||||
return is_ash_immune(L.loc)
|
||||
return FALSE //RIP you
|
||||
|
||||
/datum/weather/ash_storm/impact(mob/living/L)
|
||||
if(is_ash_immune(L))
|
||||
return
|
||||
L.adjustFireLoss(4)
|
||||
|
||||
/datum/weather/ash_storm/emberfall //Emberfall: An ash storm passes by, resulting in harmless embers falling like snow. 10% to happen in place of an ash storm.
|
||||
name = "emberfall"
|
||||
desc = "A passing ash storm blankets the area in harmless embers."
|
||||
|
||||
weather_message = "<span class='notice'>Gentle embers waft down around you like grotesque snow. The storm seems to have passed you by...</span>"
|
||||
weather_sound = 'sound/lavaland/ash_storm_windup.ogg'
|
||||
weather_overlay = "light_ash"
|
||||
|
||||
end_message = "<span class='notice'>The emberfall slows, stops. Another layer of hardened soot to the basalt beneath your feet.</span>"
|
||||
|
||||
aesthetic = TRUE
|
||||
|
||||
probability = 10
|
||||
|
||||
/datum/weather/rad_storm
|
||||
name = "radiation storm"
|
||||
desc = "A cloud of intense radiation passes through the area dealing rad damage to those who are unprotected."
|
||||
|
||||
telegraph_duration = 400
|
||||
telegraph_message = "<span class='danger'>The air begins to grow warm.</span>"
|
||||
|
||||
weather_message = "<span class='userdanger'><i>You feel waves of heat wash over you! Find shelter!</i></span>"
|
||||
weather_overlay = "ash_storm"
|
||||
weather_duration_lower = 100
|
||||
weather_duration_upper = 600
|
||||
weather_color = "green"
|
||||
weather_sound = 'sound/misc/bloblarm.ogg'
|
||||
|
||||
end_duration = 100
|
||||
end_message = "<span class='notice'>The air seems to be cooling off again.</span>"
|
||||
|
||||
area_type = /area
|
||||
protected_areas = list(/area/maintenance, /area/ai_monitored/turret_protected/ai_upload, /area/ai_monitored/turret_protected/ai_upload_foyer,
|
||||
/area/ai_monitored/turret_protected/ai, /area/storage/emergency/starboard, /area/storage/emergency/port, /area/shuttle)
|
||||
target_z = ZLEVEL_STATION_PRIMARY
|
||||
|
||||
immunity_type = "rad"
|
||||
|
||||
/datum/weather/rad_storm/telegraph()
|
||||
..()
|
||||
status_alarm("alert")
|
||||
|
||||
|
||||
/datum/weather/rad_storm/impact(mob/living/L)
|
||||
var/resist = L.getarmor(null, "rad")
|
||||
if(prob(40))
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.dna && H.dna.species)
|
||||
if(!(RADIMMUNE in H.dna.species.species_traits))
|
||||
if(prob(max(0,100-resist)))
|
||||
H.randmuti()
|
||||
if(prob(50))
|
||||
if(prob(90))
|
||||
H.randmutb()
|
||||
else
|
||||
H.randmutg()
|
||||
H.domutcheck()
|
||||
L.rad_act(20,1)
|
||||
/datum/weather/rad_storm/end()
|
||||
if(..())
|
||||
return
|
||||
priority_announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert")
|
||||
status_alarm()
|
||||
sleep(300)
|
||||
revoke_maint_all_access() // Need to make this a timer at some point.
|
||||
|
||||
|
||||
/datum/weather/rad_storm/proc/status_alarm(command) //Makes the status displays show the radiation warning for those who missed the announcement.
|
||||
var/datum/radio_frequency/frequency = SSradio.return_frequency(1435)
|
||||
|
||||
if(!frequency)
|
||||
return
|
||||
|
||||
var/datum/signal/status_signal = new
|
||||
var/atom/movable/virtualspeaker/virt = new /atom/movable/virtualspeaker(null)
|
||||
status_signal.source = virt
|
||||
status_signal.transmission_method = 1
|
||||
status_signal.data["command"] = "shuttle"
|
||||
|
||||
if(command == "alert")
|
||||
status_signal.data["command"] = "alert"
|
||||
status_signal.data["picture_state"] = "radiation"
|
||||
|
||||
frequency.post_signal(src, status_signal)
|
||||
|
||||
|
||||
/datum/weather/acid_rain
|
||||
name = "acid rain"
|
||||
desc = "Some stay dry and others feel the pain"
|
||||
|
||||
telegraph_duration = 400
|
||||
telegraph_message = "<span class='danger'>Stinging droplets start to fall upon you..</span>"
|
||||
telegraph_sound = 'sound/ambience/acidrain_start.ogg'
|
||||
|
||||
weather_message = "<span class='userdanger'><i>Your skin melts underneath the rain!</i></span>"
|
||||
weather_overlay = "acid_rain"
|
||||
weather_duration_lower = 600
|
||||
weather_duration_upper = 1500
|
||||
weather_sound = 'sound/ambience/acidrain_mid.ogg'
|
||||
|
||||
end_duration = 100
|
||||
end_message = "<span class='notice'>The rain starts to dissipate.</span>"
|
||||
end_sound = 'sound/ambience/acidrain_end.ogg'
|
||||
|
||||
area_type = /area/lavaland/surface/outdoors
|
||||
target_z = ZLEVEL_LAVALAND
|
||||
|
||||
immunity_type = "acid" // temp
|
||||
|
||||
|
||||
/datum/weather/acid_rain/impact(mob/living/L)
|
||||
var/resist = L.getarmor(null, "acid")
|
||||
if(prob(max(0,100-resist)))
|
||||
L.acid_act(20,20)
|
||||
@@ -0,0 +1,29 @@
|
||||
//Acid rain is part of the natural weather cycle in the humid forests of Planetstation, and cause acid damage to anyone unprotected.
|
||||
/datum/weather/acid_rain
|
||||
name = "acid rain"
|
||||
desc = "The planet's thunderstorms are by nature acidic, and will incinerate anyone standing beneath them without protection."
|
||||
|
||||
telegraph_duration = 400
|
||||
telegraph_message = "<span class='boldwarning'>Thunder rumbles far above. You hear droplets drumming against the canopy. Seek shelter.</span>"
|
||||
telegraph_sound = 'sound/ambience/acidrain_start.ogg'
|
||||
|
||||
weather_message = "<span class='userdanger'><i>Acidic rain pours down around you! Get inside!</i></span>"
|
||||
weather_overlay = "acid_rain"
|
||||
weather_duration_lower = 600
|
||||
weather_duration_upper = 1500
|
||||
weather_sound = 'sound/ambience/acidrain_mid.ogg'
|
||||
|
||||
end_duration = 100
|
||||
end_message = "<span class='boldannounce'>The downpour gradually slows to a light shower. It should be safe outside now.</span>"
|
||||
end_sound = 'sound/ambience/acidrain_end.ogg'
|
||||
|
||||
area_type = /area/lavaland/surface/outdoors
|
||||
target_z = ZLEVEL_LAVALAND
|
||||
|
||||
immunity_type = "acid" // temp
|
||||
|
||||
|
||||
/datum/weather/acid_rain/weather_act(mob/living/L)
|
||||
var/resist = L.getarmor(null, "acid")
|
||||
if(prob(max(0,100-resist)))
|
||||
L.acid_act(20,20)
|
||||
@@ -0,0 +1,30 @@
|
||||
//Restricts the vision of affected mobs to a single tile in the cardinal directions.
|
||||
/datum/weather/advanced_darkness
|
||||
name = "advanced darkness"
|
||||
desc = "Everything in the area is effectively blinded, unable to see more than a foot or so around itself."
|
||||
|
||||
telegraph_message = "<span class='warning'>Your eyes hurt... a vignette settles in your vision and closes in.</span>"
|
||||
telegraph_duration = 150
|
||||
|
||||
weather_message = "<span class='userdanger'>This isn't your average everday darkness... this is <i>advanced</i> darkness!</span>"
|
||||
weather_duration_lower = 300
|
||||
weather_duration_upper = 300
|
||||
|
||||
end_message = "<span class='danger'>At last, the darkness recedes.</span>"
|
||||
end_duration = 0
|
||||
|
||||
area_type = /area
|
||||
target_z = ZLEVEL_STATION_PRIMARY
|
||||
|
||||
/datum/weather/advanced_darkness/update_areas()
|
||||
for(var/V in impacted_areas)
|
||||
var/area/A = V
|
||||
if(stage == MAIN_STAGE)
|
||||
A.invisibility = 0
|
||||
A.set_opacity(TRUE)
|
||||
A.layer = overlay_layer
|
||||
A.icon = 'icons/effects/weather_effects.dmi'
|
||||
A.icon_state = "darkness"
|
||||
else
|
||||
A.invisibility = INVISIBILITY_MAXIMUM
|
||||
A.set_opacity(FALSE)
|
||||
@@ -0,0 +1,61 @@
|
||||
//Ash storms happen frequently on lavaland. They heavily obscure vision, and cause high fire damage to anyone caught outside.
|
||||
/datum/weather/ash_storm
|
||||
name = "ash storm"
|
||||
desc = "An intense atmospheric storm lifts ash off of the planet's surface and billows it down across the area, dealing intense fire damage to the unprotected."
|
||||
|
||||
telegraph_message = "<span class='boldwarning'>An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter.</span>"
|
||||
telegraph_duration = 300
|
||||
telegraph_sound = 'sound/lavaland/ash_storm_windup.ogg'
|
||||
telegraph_overlay = "light_ash"
|
||||
|
||||
weather_message = "<span class='userdanger'><i>Smoldering clouds of scorching ash billow down around you! Get inside!</i></span>"
|
||||
weather_duration_lower = 600
|
||||
weather_duration_upper = 1200
|
||||
weather_sound = 'sound/lavaland/ash_storm_start.ogg'
|
||||
weather_overlay = "ash_storm"
|
||||
|
||||
end_message = "<span class='boldannounce'>The shrieking wind whips away the last of the ash and falls to its usual murmur. It should be safe to go outside now.</span>"
|
||||
end_duration = 300
|
||||
end_sound = 'sound/lavaland/ash_storm_end.ogg'
|
||||
end_overlay = "light_ash"
|
||||
|
||||
area_type = /area/lavaland/surface/outdoors
|
||||
target_z = ZLEVEL_LAVALAND
|
||||
|
||||
immunity_type = "ash"
|
||||
|
||||
probability = 90
|
||||
|
||||
/datum/weather/ash_storm/proc/is_ash_immune(mob/living/L)
|
||||
if(istype(L.loc, /obj/mecha)) //Mechs are immune
|
||||
return TRUE
|
||||
if(ishuman(L)) //Are you immune?
|
||||
var/mob/living/carbon/human/H = L
|
||||
var/thermal_protection = H.get_thermal_protection()
|
||||
if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT)
|
||||
return TRUE
|
||||
if(istype(L.loc, /mob/living) && L.loc != L) //Matryoshka check
|
||||
return is_ash_immune(L.loc)
|
||||
return FALSE //RIP you
|
||||
|
||||
/datum/weather/ash_storm/weather_act(mob/living/L)
|
||||
if(is_ash_immune(L))
|
||||
return
|
||||
L.adjustFireLoss(4)
|
||||
|
||||
|
||||
//Emberfalls are the result of an ash storm passing by close to the playable area of lavaland. They have a 10% chance to trigger in place of an ash storm.
|
||||
/datum/weather/ash_storm/emberfall
|
||||
name = "emberfall"
|
||||
desc = "A passing ash storm blankets the area in harmless embers."
|
||||
|
||||
weather_message = "<span class='notice'>Gentle embers waft down around you like grotesque snow. The storm seems to have passed you by...</span>"
|
||||
weather_sound = 'sound/lavaland/ash_storm_windup.ogg'
|
||||
weather_overlay = "light_ash"
|
||||
|
||||
end_message = "<span class='notice'>The emberfall slows, stops. Another layer of hardened soot to the basalt beneath your feet.</span>"
|
||||
end_sound = null
|
||||
|
||||
aesthetic = TRUE
|
||||
|
||||
probability = 10
|
||||
@@ -0,0 +1,32 @@
|
||||
//Causes fire damage to anyone not standing on a dense object.
|
||||
/datum/weather/floor_is_lava
|
||||
name = "the floor is lava"
|
||||
desc = "The ground turns into surprisingly cool lava, lightly damaging anything on the floor."
|
||||
|
||||
telegraph_message = "<span class='warning'>You feel the ground beneath you getting hot. Waves of heat distort the air.</span>"
|
||||
telegraph_duration = 150
|
||||
|
||||
weather_message = "<span class='userdanger'>The floor is lava! Get on top of something!</span>"
|
||||
weather_duration_lower = 300
|
||||
weather_duration_upper = 600
|
||||
weather_overlay = "lava"
|
||||
|
||||
end_message = "<span class='danger'>The ground cools and returns to its usual form.</span>"
|
||||
end_duration = 0
|
||||
|
||||
area_type = /area
|
||||
protected_areas = list(/area/space)
|
||||
target_z = ZLEVEL_STATION_PRIMARY
|
||||
|
||||
overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only
|
||||
immunity_type = "lava"
|
||||
|
||||
/datum/weather/floor_is_lava/weather_act(mob/living/L)
|
||||
for(var/obj/structure/O in L.loc)
|
||||
if(O.density)
|
||||
return
|
||||
if(L.loc.density)
|
||||
return
|
||||
if(!L.client) //Only sentient people are going along with it!
|
||||
return
|
||||
L.adjustFireLoss(3)
|
||||
@@ -0,0 +1,72 @@
|
||||
//Radiation storms occur when the station passes through an irradiated area, and irradiate anyone not standing in protected areas (maintenance, emergency storage, etc.)
|
||||
/datum/weather/rad_storm
|
||||
name = "radiation storm"
|
||||
desc = "A cloud of intense radiation passes through the area dealing rad damage to those who are unprotected."
|
||||
|
||||
telegraph_duration = 400
|
||||
telegraph_message = "<span class='danger'>The air begins to grow warm.</span>"
|
||||
|
||||
weather_message = "<span class='userdanger'><i>You feel waves of heat wash over you! Find shelter!</i></span>"
|
||||
weather_overlay = "ash_storm"
|
||||
weather_duration_lower = 600
|
||||
weather_duration_upper = 1500
|
||||
weather_color = "green"
|
||||
weather_sound = 'sound/misc/bloblarm.ogg'
|
||||
|
||||
end_duration = 100
|
||||
end_message = "<span class='notice'>The air seems to be cooling off again.</span>"
|
||||
|
||||
area_type = /area
|
||||
protected_areas = list(/area/maintenance, /area/ai_monitored/turret_protected/ai_upload, /area/ai_monitored/turret_protected/ai_upload_foyer,
|
||||
/area/ai_monitored/turret_protected/ai, /area/storage/emergency/starboard, /area/storage/emergency/port, /area/shuttle)
|
||||
target_z = ZLEVEL_STATION_PRIMARY
|
||||
|
||||
immunity_type = "rad"
|
||||
|
||||
/datum/weather/rad_storm/telegraph()
|
||||
..()
|
||||
status_alarm("alert")
|
||||
|
||||
|
||||
/datum/weather/rad_storm/weather_act(mob/living/L)
|
||||
var/resist = L.getarmor(null, "rad")
|
||||
if(prob(40))
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.dna && H.dna.species)
|
||||
if(!(RADIMMUNE in H.dna.species.species_traits))
|
||||
if(prob(max(0,100-resist)))
|
||||
H.randmuti()
|
||||
if(prob(50))
|
||||
if(prob(90))
|
||||
H.randmutb()
|
||||
else
|
||||
H.randmutg()
|
||||
H.domutcheck()
|
||||
L.rad_act(20,1)
|
||||
|
||||
/datum/weather/rad_storm/end()
|
||||
if(..())
|
||||
return
|
||||
priority_announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert")
|
||||
status_alarm()
|
||||
sleep(300)
|
||||
revoke_maint_all_access() // Need to make this a timer at some point.
|
||||
|
||||
/datum/weather/rad_storm/proc/status_alarm(command) //Makes the status displays show the radiation warning for those who missed the announcement.
|
||||
var/datum/radio_frequency/frequency = SSradio.return_frequency(1435)
|
||||
|
||||
if(!frequency)
|
||||
return
|
||||
|
||||
var/datum/signal/status_signal = new
|
||||
var/atom/movable/virtualspeaker/virt = new /atom/movable/virtualspeaker(null)
|
||||
status_signal.source = virt
|
||||
status_signal.transmission_method = 1
|
||||
status_signal.data["command"] = "shuttle"
|
||||
|
||||
if(command == "alert")
|
||||
status_signal.data["command"] = "alert"
|
||||
status_signal.data["picture_state"] = "radiation"
|
||||
|
||||
frequency.post_signal(src, status_signal)
|
||||
+14
-1
@@ -150,6 +150,7 @@
|
||||
return 0
|
||||
|
||||
/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
SendSignal(COMSIG_ATOM_HULK_ATTACK, user)
|
||||
if(does_attack_animation)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
add_logs(user, src, "punched", "hulk powers")
|
||||
@@ -222,10 +223,12 @@
|
||||
return
|
||||
|
||||
/atom/proc/emp_act(severity)
|
||||
SendSignal(COMSIG_ATOM_EMP_ACT, severity)
|
||||
if(istype(wires) && !(flags_2 & NO_EMP_WIRES_2))
|
||||
wires.emp_pulse()
|
||||
|
||||
/atom/proc/bullet_act(obj/item/projectile/P, def_zone)
|
||||
SendSignal(COMSIG_ATOM_BULLET_ACT, P, def_zone)
|
||||
. = P.on_hit(src, 0, def_zone)
|
||||
|
||||
/atom/proc/in_contents_of(container)//can take class or object instance as argument
|
||||
@@ -291,6 +294,7 @@
|
||||
to_chat(user, "[total_volume] units of various reagents")
|
||||
else
|
||||
to_chat(user, "Nothing.")
|
||||
SendSignal(COMSIG_PARENT_EXAMINE, user)
|
||||
|
||||
/atom/proc/relaymove(mob/user)
|
||||
if(buckle_message_cooldown <= world.time)
|
||||
@@ -307,9 +311,11 @@
|
||||
SendSignal(COMSIG_ATOM_EX_ACT, severity, target)
|
||||
|
||||
/atom/proc/blob_act(obj/structure/blob/B)
|
||||
SendSignal(COMSIG_ATOM_BLOB_ACT, B)
|
||||
return
|
||||
|
||||
/atom/proc/fire_act(exposed_temperature, exposed_volume)
|
||||
SendSignal(COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked)
|
||||
@@ -448,7 +454,6 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
|
||||
cur_y = y_arr.Find(src.z)
|
||||
if(cur_y)
|
||||
break
|
||||
// to_chat(world, "X = [cur_x]; Y = [cur_y]")
|
||||
if(cur_x && cur_y)
|
||||
return list("x"=cur_x,"y"=cur_y)
|
||||
else
|
||||
@@ -473,21 +478,26 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
|
||||
SendSignal(COMSIG_ATOM_SING_PULL, S, current_size)
|
||||
|
||||
/atom/proc/acid_act(acidpwr, acid_volume)
|
||||
SendSignal(COMSIG_ATOM_ACID_ACT, acidpwr, acid_volume)
|
||||
return
|
||||
|
||||
/atom/proc/emag_act()
|
||||
SendSignal(COMSIG_ATOM_EMAG_ACT)
|
||||
return
|
||||
|
||||
/atom/proc/narsie_act()
|
||||
SendSignal(COMSIG_ATOM_NARSIE_ACT)
|
||||
return
|
||||
|
||||
/atom/proc/ratvar_act()
|
||||
SendSignal(COMSIG_ATOM_RATVAR_ACT)
|
||||
return
|
||||
|
||||
/atom/proc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
|
||||
return FALSE
|
||||
|
||||
/atom/proc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
|
||||
SendSignal(COMSIG_ATOM_RCD_ACT, user, the_rcd, passed_mode)
|
||||
return FALSE
|
||||
|
||||
/atom/proc/storage_contents_dump_act(obj/item/storage/src_object, mob/user)
|
||||
@@ -627,3 +637,6 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
|
||||
|
||||
/atom/Entered(atom/movable/AM, atom/oldLoc)
|
||||
SendSignal(COMSIG_ATOM_ENTERED, AM, oldLoc)
|
||||
|
||||
/atom/proc/return_temperature()
|
||||
return
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/atom/movable
|
||||
layer = OBJ_LAYER
|
||||
var/last_move = null
|
||||
@@ -117,6 +116,7 @@
|
||||
|
||||
//Called after a successful Move(). By this point, we've already moved
|
||||
/atom/movable/proc/Moved(atom/OldLoc, Dir)
|
||||
SendSignal(COMSIG_MOVABLE_MOVED, OldLoc, Dir)
|
||||
if (!inertia_moving)
|
||||
inertia_next_move = world.time + inertia_move_delay
|
||||
newtonian_move(Dir)
|
||||
@@ -215,6 +215,7 @@
|
||||
//to differentiate it, naturally everyone forgot about this immediately and so some things
|
||||
//would bump twice, so now it's called Collide
|
||||
/atom/movable/proc/Collide(atom/A)
|
||||
SendSignal(COMSIG_MOVABLE_COLLIDE, A)
|
||||
if(A)
|
||||
if(throwing)
|
||||
throwing.hit_atom(A)
|
||||
@@ -308,6 +309,7 @@
|
||||
|
||||
/atom/movable/proc/throw_impact(atom/hit_atom, throwingdatum)
|
||||
set waitfor = 0
|
||||
SendSignal(COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
|
||||
return hit_atom.hitby(src)
|
||||
|
||||
/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked)
|
||||
@@ -315,7 +317,8 @@
|
||||
step(src, AM.dir)
|
||||
..()
|
||||
|
||||
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback)
|
||||
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback) //If this returns FALSE then callback will not be called.
|
||||
. = FALSE
|
||||
if (!target || (flags_1 & NODROP_1) || speed <= 0)
|
||||
return
|
||||
|
||||
@@ -344,7 +347,9 @@
|
||||
//then lets add it to speed
|
||||
speed += user_momentum
|
||||
if (speed <= 0)
|
||||
return //no throw speed, the user was moving too fast.
|
||||
return//no throw speed, the user was moving too fast.
|
||||
|
||||
. = TRUE // No failure conditions past this point.
|
||||
|
||||
var/datum/thrownthing/TT = new()
|
||||
TT.thrownthing = src
|
||||
@@ -692,4 +697,4 @@
|
||||
return FALSE
|
||||
if(anchored || throwing)
|
||||
return FALSE
|
||||
return TRUE
|
||||
return TRUE
|
||||
@@ -261,7 +261,7 @@
|
||||
|
||||
/obj/item/antag_spawner/slaughter_demon/spawn_antag(client/C, turf/T, type = "")
|
||||
|
||||
var /obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T)
|
||||
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T)
|
||||
var/mob/living/simple_animal/slaughter/S = new demon_type(holder)
|
||||
S.holder = holder
|
||||
S.key = C.key
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
diff a/code/game/gamemodes/antag_spawner.dm b/code/game/gamemodes/antag_spawner.dm (rejected hunks)
|
||||
@@ -108,6 +108,7 @@
|
||||
new_objective.explanation_text = "Protect [usr.real_name], the wizard."
|
||||
M.mind.objectives += new_objective
|
||||
SSticker.mode.apprentices += M.mind
|
||||
+ M.mind.assigned_role = "Apprentice"
|
||||
M.mind.special_role = "apprentice"
|
||||
SSticker.mode.update_wiz_icons_added(M.mind)
|
||||
M << sound('sound/effects/magic.ogg')
|
||||
@@ -229,13 +229,29 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/Life()
|
||||
if(..())
|
||||
var/list/blobs_in_area = range(2, src)
|
||||
if(independent)
|
||||
return // strong independent blobbernaut that don't need no blob
|
||||
var/damagesources = 0
|
||||
if(!(locate(/obj/structure/blob) in range(2, src)))
|
||||
if(!(locate(/obj/structure/blob) in blobs_in_area))
|
||||
damagesources++
|
||||
if(!factory)
|
||||
damagesources++
|
||||
else
|
||||
if(locate(/obj/structure/blob/core) in blobs_in_area)
|
||||
adjustHealth(-maxHealth*0.1)
|
||||
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src)) //hello yes you are being healed
|
||||
if(overmind)
|
||||
H.color = overmind.blob_reagent_datum.complementary_color
|
||||
else
|
||||
H.color = "#000000"
|
||||
if(locate(/obj/structure/blob/node) in blobs_in_area)
|
||||
adjustHealth(-maxHealth*0.05)
|
||||
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src))
|
||||
if(overmind)
|
||||
H.color = overmind.blob_reagent_datum.complementary_color
|
||||
else
|
||||
H.color = "#000000"
|
||||
if(damagesources)
|
||||
for(var/i in 1 to damagesources)
|
||||
adjustHealth(maxHealth*0.025) //take 2.5% of max health as damage when not near the blob or if the naut has no factory, 5% if both
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
if(!placed)
|
||||
if(manualplace_min_time && world.time >= manualplace_min_time)
|
||||
to_chat(src, "<b><span class='big'><font color=\"#EE4000\">You may now place your blob core.</font></span></b>")
|
||||
to_chat(src, "<span class='big'><font color=\"#EE4000\">You will automatically place your blob core in [round((autoplace_max_time - world.time)/600, 0.5)] minutes.</font></span>")
|
||||
to_chat(src, "<span class='big'><font color=\"#EE4000\">You will automatically place your blob core in [DisplayTimeText(autoplace_max_time - world.time)].</font></span>")
|
||||
manualplace_min_time = 0
|
||||
if(autoplace_max_time && world.time >= autoplace_max_time)
|
||||
place_blob_core(base_point_rate, 1)
|
||||
|
||||
@@ -365,5 +365,5 @@
|
||||
to_chat(src, "<b>Shortcuts:</b> Click = Expand Blob <b>|</b> Middle Mouse Click = Rally Spores <b>|</b> Ctrl Click = Create Shield Blob <b>|</b> Alt Click = Remove Blob")
|
||||
to_chat(src, "Attempting to talk will send a message to all other overminds, allowing you to coordinate with them.")
|
||||
if(!placed && autoplace_max_time <= world.time)
|
||||
to_chat(src, "<span class='big'><font color=\"#EE4000\">You will automatically place your blob core in [round((autoplace_max_time - world.time)/600, 0.5)] minutes.</font></span>")
|
||||
to_chat(src, "<span class='big'><font color=\"#EE4000\">You will automatically place your blob core in [DisplayTimeText(autoplace_max_time - world.time)].</font></span>")
|
||||
to_chat(src, "<span class='big'><font color=\"#EE4000\">You [manualplace_min_time ? "will be able to":"can"] manually place your blob core by pressing the Place Blob Core button in the bottom right corner of the screen.</font></span>")
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/datum/objective_team/brother_team
|
||||
name = "brotherhood"
|
||||
member_name = "blood brother"
|
||||
var/list/objectives = list()
|
||||
var/meeting_area
|
||||
|
||||
/datum/objective_team/brother_team/is_solo()
|
||||
return FALSE
|
||||
|
||||
/datum/objective_team/brother_team/proc/add_objective(datum/objective/O, needs_target = FALSE)
|
||||
O.team = src
|
||||
if(needs_target)
|
||||
O.find_target()
|
||||
O.update_explanation_text()
|
||||
objectives += O
|
||||
|
||||
/datum/objective_team/brother_team/proc/forge_brother_objectives()
|
||||
objectives = list()
|
||||
var/is_hijacker = prob(10)
|
||||
for(var/i = 1 to max(1, config.brother_objectives_amount + (members.len > 2) - is_hijacker))
|
||||
forge_single_objective()
|
||||
if(is_hijacker)
|
||||
if(!locate(/datum/objective/hijack) in objectives)
|
||||
add_objective(new/datum/objective/hijack)
|
||||
else if(!locate(/datum/objective/escape) in objectives)
|
||||
add_objective(new/datum/objective/escape)
|
||||
|
||||
/datum/objective_team/brother_team/proc/forge_single_objective()
|
||||
if(prob(50))
|
||||
if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len))
|
||||
add_objective(new/datum/objective/destroy, TRUE)
|
||||
else if(prob(30))
|
||||
add_objective(new/datum/objective/maroon, TRUE)
|
||||
else
|
||||
add_objective(new/datum/objective/assassinate, TRUE)
|
||||
else
|
||||
add_objective(new/datum/objective/steal, TRUE)
|
||||
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/brothers = list()
|
||||
var/list/datum/objective_team/brother_team/brother_teams = list()
|
||||
|
||||
/datum/game_mode/traitor/bros
|
||||
name = "traitor+brothers"
|
||||
config_tag = "traitorbro"
|
||||
restricted_jobs = list("AI", "Cyborg")
|
||||
|
||||
announce_span = "danger"
|
||||
announce_text = "There are Syndicate agents and Blood Brothers on the station!\n\
|
||||
<span class='danger'>Traitors</span>: Accomplish your objectives.\n\
|
||||
<span class='danger'>Blood Brothers</span>: Accomplish your objectives.\n\
|
||||
<span class='notice'>Crew</span>: Do not let the traitors or brothers succeed!"
|
||||
|
||||
var/list/datum/objective_team/brother_team/pre_brother_teams = list()
|
||||
var/const/team_amount = 2 //hard limit on brother teams if scaling is turned off
|
||||
var/const/min_team_size = 2
|
||||
|
||||
var/meeting_areas = list("The Bar", "Dorms", "Escape Dock", "Arrivals", "Holodeck", "Primary Tool Storage", "Recreation Area", "Chapel", "Library")
|
||||
|
||||
/datum/game_mode/traitor/bros/pre_setup()
|
||||
if(config.protect_roles_from_antagonist)
|
||||
restricted_jobs += protected_jobs
|
||||
if(config.protect_assistant_from_antagonist)
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
var/list/datum/mind/possible_brothers = get_players_for_role(ROLE_BROTHER)
|
||||
|
||||
var/num_teams = team_amount
|
||||
if(config.brother_scaling_coeff)
|
||||
num_teams = max(1, round(num_players()/config.brother_scaling_coeff))
|
||||
|
||||
for(var/j = 1 to num_teams)
|
||||
if(possible_brothers.len < min_team_size || antag_candidates.len <= required_enemies)
|
||||
break
|
||||
var/datum/objective_team/brother_team/team = new
|
||||
var/team_size = prob(10) ? min(3, possible_brothers.len) : 2
|
||||
for(var/k = 1 to team_size)
|
||||
var/datum/mind/bro = pick(possible_brothers)
|
||||
possible_brothers -= bro
|
||||
antag_candidates -= bro
|
||||
team.members += bro
|
||||
bro.restricted_roles = restricted_jobs
|
||||
log_game("[bro.key] (ckey) has been selected as a Brother")
|
||||
pre_brother_teams += team
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/traitor/bros/post_setup()
|
||||
for(var/datum/objective_team/brother_team/team in pre_brother_teams)
|
||||
team.meeting_area = pick(meeting_areas)
|
||||
meeting_areas -= team.meeting_area
|
||||
team.forge_brother_objectives()
|
||||
for(var/datum/mind/M in team.members)
|
||||
M.add_antag_datum(ANTAG_DATUM_BROTHER, team)
|
||||
modePlayer += M
|
||||
brother_teams += pre_brother_teams
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/traitor/bros/generate_report()
|
||||
return "It's Syndicate recruiting season. Be alert for potential Syndicate infiltrators, but also watch out for disgruntled employees trying to defect. Unlike Nanotrasen, the Syndicate prides itself in teamwork and will only recruit pairs that share a brotherly trust."
|
||||
|
||||
/datum/game_mode/proc/auto_declare_completion_brother()
|
||||
if(!LAZYLEN(brother_teams))
|
||||
return
|
||||
var/text = "<br><font size=4><b>The blood brothers were:</b></font>"
|
||||
var/teamnumber = 1
|
||||
for(var/datum/objective_team/brother_team/team in brother_teams)
|
||||
if(!team.members.len)
|
||||
continue
|
||||
text += "<br><font size=3><b>Team #[teamnumber++]</b></font>"
|
||||
for(var/datum/mind/M in team.members)
|
||||
text += printplayer(M)
|
||||
var/win = TRUE
|
||||
var/objective_count = 1
|
||||
for(var/datum/objective/objective in team.objectives)
|
||||
if(objective.check_completion())
|
||||
text += "<br><B>Objective #[objective_count]</B>: [objective.explanation_text] <font color='green'><B>Success!</B></font>"
|
||||
SSblackbox.add_details("traitor_objective","[objective.type]|SUCCESS")
|
||||
else
|
||||
text += "<br><B>Objective #[objective_count]</B>: [objective.explanation_text] <font color='red'>Fail.</font>"
|
||||
SSblackbox.add_details("traitor_objective","[objective.type]|FAIL")
|
||||
win = FALSE
|
||||
objective_count++
|
||||
if(win)
|
||||
text += "<br><font color='green'><B>The blood brothers were successful!</B></font>"
|
||||
SSblackbox.add_details("brother_success","SUCCESS")
|
||||
else
|
||||
text += "<br><font color='red'><B>The blood brothers have failed!</B></font>"
|
||||
SSblackbox.add_details("brother_success","FAIL")
|
||||
text += "<br>"
|
||||
to_chat(world, text)
|
||||
|
||||
/datum/game_mode/proc/update_brother_icons_added(datum/mind/brother_mind)
|
||||
var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER]
|
||||
brotherhud.join_hud(brother_mind.current)
|
||||
set_antag_hud(brother_mind.current, "brother")
|
||||
|
||||
/datum/game_mode/proc/update_brother_icons_removed(datum/mind/brother_mind)
|
||||
var/datum/atom_hud/antag/brotherhud = GLOB.huds[ANTAG_HUD_BROTHER]
|
||||
brotherhud.leave_hud(brother_mind.current)
|
||||
set_antag_hud(brother_mind.current, null)
|
||||
@@ -340,6 +340,10 @@ GLOBAL_LIST_INIT(slot2type, list("head" = /obj/item/clothing/head/changeling, "w
|
||||
return
|
||||
if(!target)
|
||||
return
|
||||
if(NO_DNA_COPY in target.dna.species.species_traits)
|
||||
if(verbose)
|
||||
to_chat(user, "<span class='warning'>[target] is not compatible with our biology.</span>")
|
||||
return
|
||||
if((target.disabilities & NOCLONE) || (target.disabilities & HUSK))
|
||||
if(verbose)
|
||||
to_chat(user, "<span class='warning'>DNA of [target] is ruined beyond usability!</span>")
|
||||
|
||||
@@ -207,7 +207,7 @@
|
||||
time_duration = round(time_duration * (2 * efficiency), 1)
|
||||
CO.active = TRUE //you'd be active in a second but you should update immediately
|
||||
invoker.visible_message("<span class='warning'>The air in front of [invoker] ripples before suddenly tearing open!</span>", \
|
||||
"<span class='brass'>With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [time_duration / 10] seconds and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].</span>")
|
||||
"<span class='brass'>With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [DisplayTimeText(time_duration)] and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].</span>")
|
||||
var/obj/effect/clockwork/spatial_gateway/S1 = new(issrcobelisk ? get_turf(src) : get_step(get_turf(invoker), invoker.dir))
|
||||
var/obj/effect/clockwork/spatial_gateway/S2 = new(istargetobelisk ? get_turf(target) : get_step(get_turf(target), target.dir))
|
||||
|
||||
|
||||
@@ -318,23 +318,10 @@
|
||||
if(servants > SCRIPT_SERVANT_REQ)
|
||||
servants -= SCRIPT_SERVANT_REQ
|
||||
production_time += min(SLAB_SERVANT_SLOWDOWN * servants, SLAB_SLOWDOWN_MAXIMUM)
|
||||
var/production_text_addon = ""
|
||||
if(production_time != SLAB_PRODUCTION_TIME+SLAB_SLOWDOWN_MAXIMUM)
|
||||
production_text_addon = ", which increases for each human or silicon Servant above <b>[SCRIPT_SERVANT_REQ]</b>"
|
||||
production_time = production_time/600
|
||||
var/list/production_text
|
||||
if(round(production_time))
|
||||
production_text = list("<b>[round(production_time)] minute\s")
|
||||
if(production_time != round(production_time))
|
||||
production_time -= round(production_time)
|
||||
production_time *= 60
|
||||
if(!LAZYLEN(production_text))
|
||||
production_text = list("<b>[round(production_time, 1)] second\s")
|
||||
else
|
||||
production_text += " and [round(production_time, 1)] second\s"
|
||||
production_text += "</b>"
|
||||
production_text += production_text_addon
|
||||
production_text = production_text.Join()
|
||||
production_time = "<b>[DisplayTimeText(production_time)]</b>, which increases for each human or silicon Servant above <b>[SCRIPT_SERVANT_REQ]</b>"
|
||||
else
|
||||
production_time = "<b>[DisplayTimeText(production_time)]</b>"
|
||||
|
||||
textlist = list("<font color=#BE8700 size=3><b><center>[text2ratvar("Purge all untruths and honor Engine.")]</center></b></font><br>\
|
||||
\
|
||||
@@ -439,23 +426,10 @@
|
||||
if(servants > SCRIPT_SERVANT_REQ)
|
||||
servants -= SCRIPT_SERVANT_REQ
|
||||
production_time += min(SLAB_SERVANT_SLOWDOWN * servants, SLAB_SLOWDOWN_MAXIMUM)
|
||||
var/production_text_addon = ""
|
||||
if(production_time != SLAB_PRODUCTION_TIME+SLAB_SLOWDOWN_MAXIMUM)
|
||||
production_text_addon = ", which increases for each human or silicon Servant above <b>[SCRIPT_SERVANT_REQ]</b>"
|
||||
production_time = production_time/600
|
||||
var/list/production_text
|
||||
if(round(production_time))
|
||||
production_text = list("<b>[round(production_time)] minute\s")
|
||||
if(production_time != round(production_time))
|
||||
production_time -= round(production_time)
|
||||
production_time *= 60
|
||||
if(!LAZYLEN(production_text))
|
||||
production_text = list("<b>[round(production_time, 1)] second\s")
|
||||
else
|
||||
production_text += " and [round(production_time, 1)] second\s"
|
||||
production_text += "</b>"
|
||||
production_text += production_text_addon
|
||||
production_text = production_text.Join()
|
||||
production_time = "<b>[DisplayTimeText(production_time)]</b>, which increases for each human or silicon Servant above <b>[SCRIPT_SERVANT_REQ]</b>"
|
||||
else
|
||||
production_time = "<b>[DisplayTimeText(production_time)]</b>"
|
||||
dat += "<font color=#BE8700 size=3>Components & Their Uses</font><br><br>"
|
||||
dat += "<b>Components</b> are your primary resource as a Servant. There are five types of component, with each one being used in different roles:<br><br>"
|
||||
dat += "<font color=#6E001A>[get_component_icon(BELLIGERENT_EYE)]BE</font> Belligerent Eyes are aggressive and judgemental, and are used in offensive scripture;<br>"
|
||||
@@ -466,7 +440,7 @@
|
||||
dat += "Although this is a good rule of thumb, their effects become much more nuanced when used together. For instance, a turret might have both belligerent eyes and \
|
||||
vanguard cogwheels as construction requirements, because it defends its allies by harming its enemies.<br><br>"
|
||||
dat += "Components' primary use is fueling <b>scripture</b> (covered in its own section), and they can be created through various ways. This clockwork slab, for instance, \
|
||||
will make a random component of every type - or a specific one, if you choose a target component from the interface - every <b>[production_text]</b>. This number will increase \
|
||||
will make a random component of every type - or a specific one, if you choose a target component from the interface - every [production_time]. This number will increase \
|
||||
as the amount of Servants in the covenant increase; additionally, slabs can only produce components when held by a Servant, and holding more than one slab will cause both \
|
||||
of them to halt progress until one of them is removed from their person.<br><br>"
|
||||
dat += "Your slab has an internal storage of components, but it isn't meant to be the main one. Instead, there's a <b>global storage</b> of components that can be \
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
autoping = FALSE
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
force_replace_ai_name = TRUE
|
||||
overrides_aicore_laws = TRUE
|
||||
|
||||
/obj/item/device/mmi/posibrain/soul_vessel/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
glow.linked = src
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/celestial_gateway/ex_act(severity)
|
||||
var/damage = max((obj_integrity * 0.70) / severity, 100) //requires multiple bombs to take down
|
||||
var/damage = max((obj_integrity * 0.7) / severity, 100) //requires multiple bombs to take down
|
||||
take_damage(damage, BRUTE, "bomb", 0)
|
||||
|
||||
/obj/structure/destructible/clockwork/massive/celestial_gateway/attackby(obj/item/I, mob/living/user, params) //add components directly to the ark
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
..()
|
||||
if(is_servant_of_ratvar(user) || isobserver(user))
|
||||
if(linkedwall)
|
||||
to_chat(user, "<span class='brass'>It is linked to a Clockwork Wall and will generate a component every <b>[round(get_production_time() * 0.1, 0.1)]</b> seconds!</span>")
|
||||
to_chat(user, "<span class='brass'>It is linked to a Clockwork Wall and will generate a component every <b>[DisplayTimeText(get_production_time())]</b>!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='alloy'>It is unlinked! Construct a Clockwork Wall nearby to generate components!</span>")
|
||||
to_chat(user, "<b>Stored components:</b>")
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
/proc/pollCultists(var/mob/living/Nominee) //Cult Master Poll
|
||||
if(world.time < CULT_POLL_WAIT)
|
||||
to_chat(Nominee, "It would be premature to select a leader while everyone is still settling in, try again in [round((CULT_POLL_WAIT-world.time)/10)] seconds.")
|
||||
to_chat(Nominee, "It would be premature to select a leader while everyone is still settling in, try again in [DisplayTimeText(CULT_POLL_WAIT-world.time)].")
|
||||
return
|
||||
GLOB.cult_vote_called = TRUE //somebody's trying to be a master, make sure we don't let anyone else try
|
||||
for(var/datum/mind/B in SSticker.mode.cult)
|
||||
@@ -232,7 +232,7 @@
|
||||
return FALSE
|
||||
if(cooldown > world.time)
|
||||
if(!CM.active)
|
||||
to_chat(owner, "<span class='cultlarge'><b>You need to wait [round((cooldown - world.time) * 0.1)] seconds before you can mark another target!</b></span>")
|
||||
to_chat(owner, "<span class='cultlarge'><b>You need to wait [DisplayTimeText(cooldown - world.time)] before you can mark another target!</b></span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
@@ -324,7 +324,7 @@
|
||||
return FALSE
|
||||
if(cooldown > world.time)
|
||||
if(!PM.active)
|
||||
to_chat(owner, "<span class='cultlarge'><b>You need to wait [round((cooldown - world.time) * 0.1)] seconds before you can pulse again!</b></span>")
|
||||
to_chat(owner, "<span class='cultlarge'><b>You need to wait [DisplayTimeText(cooldown - world.time)] before you can pulse again!</b></span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>\The [src] is [anchored ? "":"not "]secured to the floor.</span>")
|
||||
if((iscultist(user) || isobserver(user)) && cooldowntime > world.time)
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is too weak, [p_they()] will be ready to use again in [getETA()].</span>")
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is too weak, [p_they()] will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
|
||||
|
||||
/obj/structure/destructible/cult/examine_status(mob/user)
|
||||
if(iscultist(user) || isobserver(user))
|
||||
@@ -50,13 +50,6 @@
|
||||
animate(src, color = previouscolor, time = 8)
|
||||
addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
|
||||
|
||||
/obj/structure/destructible/cult/proc/getETA()
|
||||
var/time = (cooldowntime - world.time)/600
|
||||
var/eta = "[round(time, 1)] minutes"
|
||||
if(time <= 1)
|
||||
time = (cooldowntime - world.time)*0.1
|
||||
eta = "[round(time, 1)] seconds"
|
||||
return eta
|
||||
|
||||
/obj/structure/destructible/cult/talisman
|
||||
name = "altar"
|
||||
@@ -72,7 +65,7 @@
|
||||
to_chat(user, "<span class='cultitalic'>You need to anchor [src] to the floor with a tome first.</span>")
|
||||
return
|
||||
if(cooldowntime > world.time)
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [getETA()].</span>")
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
|
||||
return
|
||||
var/choice = alert(user,"You study the schematics etched into the forge...",,"Eldritch Whetstone","Zealot's Blindfold","Flask of Unholy Water")
|
||||
var/pickedtype
|
||||
@@ -105,7 +98,7 @@
|
||||
to_chat(user, "<span class='cultitalic'>You need to anchor [src] to the floor with a tome first.</span>")
|
||||
return
|
||||
if(cooldowntime > world.time)
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [getETA()].</span>")
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
|
||||
return
|
||||
var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Nar-Sien Hardsuit")
|
||||
var/pickedtype
|
||||
@@ -212,7 +205,7 @@
|
||||
to_chat(user, "<span class='cultitalic'>You need to anchor [src] to the floor with a tome first.</span>")
|
||||
return
|
||||
if(cooldowntime > world.time)
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [getETA()].</span>")
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
|
||||
return
|
||||
var/choice = alert(user,"You flip through the black pages of the archives...",,"Supply Talisman","Shuttle Curse","Veil Walker Set")
|
||||
var/list/pickedtype = list()
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
//Todo
|
||||
@@ -121,7 +121,7 @@
|
||||
var/list/datum/game_mode/runnable_modes = config.get_runnable_midround_modes(living_crew.len)
|
||||
var/list/datum/game_mode/usable_modes = list()
|
||||
for(var/datum/game_mode/G in runnable_modes)
|
||||
if(G.reroll_friendly && living_crew >= G.required_players)
|
||||
if(G.reroll_friendly && living_crew.len >= G.required_players)
|
||||
usable_modes += G
|
||||
else
|
||||
qdel(G)
|
||||
@@ -160,7 +160,7 @@
|
||||
if(config.protect_assistant_from_antagonist)
|
||||
replacementmode.restricted_jobs += "Assistant"
|
||||
|
||||
message_admins("The roundtype will be converted. If you have other plans for the station or feel the station is too messed up to inhabit <A HREF='?_src_=holder;toggle_midround_antag=\ref[usr]'>stop the creation of antags</A> or <A HREF='?_src_=holder;end_round=\ref[usr]'>end the round now</A>.")
|
||||
message_admins("The roundtype will be converted. If you have other plans for the station or feel the station is too messed up to inhabit <A HREF='?_src_=holder;[HrefToken()];toggle_midround_antag=\ref[usr]'>stop the creation of antags</A> or <A HREF='?_src_=holder;[HrefToken()];end_round=\ref[usr]'>end the round now</A>.")
|
||||
|
||||
. = 1
|
||||
sleep(rand(600,1800))
|
||||
|
||||
@@ -331,16 +331,3 @@
|
||||
adjust_influence(bawss, amount/bosses.len)
|
||||
announce_to_mind(bawss, "<span class='notice'>[name] Gang: [amount/bosses.len] influence given from internal automatic restructuring.</span>")
|
||||
|
||||
//Multiverse
|
||||
|
||||
/datum/gang/multiverse
|
||||
dom_attempts = 0
|
||||
fighting_style = "multiverse"
|
||||
is_deconvertible = FALSE
|
||||
|
||||
/datum/gang/multiverse/New(loc, multiverse_override)
|
||||
name = multiverse_override
|
||||
ganghud = new()
|
||||
|
||||
/datum/gang/multiverse/income()
|
||||
return
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
diff a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm (rejected hunks)
|
||||
@@ -309,8 +309,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
|
||||
owner_AI.nuking = TRUE
|
||||
owner_AI.doomsday_device = DOOM
|
||||
owner_AI.doomsday_device.start()
|
||||
- for(var/pinpointer in GLOB.pinpointer_list)
|
||||
- var/obj/item/weapon/pinpointer/P = pinpointer
|
||||
+ for(var/obj/item/weapon/pinpointer/nuke/P in GLOB.pinpointer_list)
|
||||
P.switch_mode_to(TRACK_MALF_AI) //Pinpointers start tracking the AI wherever it goes
|
||||
qdel(src)
|
||||
|
||||
@@ -119,6 +119,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
|
||||
/obj/effect/meteor/Destroy()
|
||||
GLOB.meteor_list -= src
|
||||
SSaugury.unregister_doom(src)
|
||||
walk(src,0) //this cancels the walk_towards() proc
|
||||
. = ..()
|
||||
|
||||
@@ -309,6 +310,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
||||
|
||||
/obj/effect/meteor/meaty/xeno/New()
|
||||
meteordrop += subtypesof(/obj/item/organ/alien)
|
||||
meteordrop -= /obj/item/organ/alien/eggsac
|
||||
..()
|
||||
|
||||
/obj/effect/meteor/meaty/xeno/ram_turf(turf/T)
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
/datum/objective_team/abductor_team
|
||||
member_name = "abductor"
|
||||
var/list/objectives = list()
|
||||
var/team_number
|
||||
|
||||
/datum/objective_team/abductor_team/is_solo()
|
||||
return FALSE
|
||||
|
||||
/datum/objective_team/abductor_team/proc/add_objective(datum/objective/O)
|
||||
O.team = src
|
||||
O.update_explanation_text()
|
||||
objectives += O
|
||||
|
||||
/datum/game_mode
|
||||
var/abductor_teams = 0
|
||||
var/list/datum/mind/abductors = list()
|
||||
var/list/datum/mind/abductees = list()
|
||||
|
||||
@@ -12,12 +24,8 @@
|
||||
required_players = 15
|
||||
maximum_players = 50
|
||||
var/max_teams = 4
|
||||
abductor_teams = 1
|
||||
var/list/datum/mind/scientists = list()
|
||||
var/list/datum/mind/agents = list()
|
||||
var/list/datum/objective/team_objectives = list()
|
||||
var/list/team_names = list()
|
||||
var/finished = 0
|
||||
var/list/datum/objective_team/abductor_team/abductor_teams = list()
|
||||
var/finished = FALSE
|
||||
|
||||
/datum/game_mode/abduction/announce()
|
||||
to_chat(world, "<B>The current game mode is - Abduction!</B>")
|
||||
@@ -26,163 +34,78 @@
|
||||
to_chat(world, "<b>Crew</b> - don't get abducted and stop the abductors.")
|
||||
|
||||
/datum/game_mode/abduction/pre_setup()
|
||||
abductor_teams = max(1, min(max_teams,round(num_players()/config.abductor_scaling_coeff)))
|
||||
var/possible_teams = max(1,round(antag_candidates.len / 2))
|
||||
abductor_teams = min(abductor_teams,possible_teams)
|
||||
var/num_teams = max(1, min(max_teams, round(num_players() / config.abductor_scaling_coeff)))
|
||||
var/possible_teams = max(1, round(antag_candidates.len / 2))
|
||||
num_teams = min(num_teams, possible_teams)
|
||||
|
||||
abductors.len = 2*abductor_teams
|
||||
scientists.len = abductor_teams
|
||||
agents.len = abductor_teams
|
||||
team_objectives.len = abductor_teams
|
||||
team_names.len = abductor_teams
|
||||
for(var/i = 1 to num_teams)
|
||||
if(!make_abductor_team())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
for(var/i=1,i<=abductor_teams,i++)
|
||||
if(!make_abductor_team(i))
|
||||
return 0
|
||||
/datum/game_mode/abduction/proc/make_abductor_team(datum/mind/agent, datum/mind/scientist)
|
||||
var/team_number = abductor_teams.len+1
|
||||
|
||||
return 1
|
||||
var/datum/objective_team/abductor_team/team = new
|
||||
team.team_number = team_number
|
||||
team.name = "Mothership [pick(GLOB.possible_changeling_IDs)]" //TODO Ensure unique and actual alieny names
|
||||
team.add_objective(new/datum/objective/experiment)
|
||||
|
||||
/datum/game_mode/abduction/proc/make_abductor_team(team_number,preset_agent=null,preset_scientist=null)
|
||||
//Team Name
|
||||
team_names[team_number] = "Mothership [pick(GLOB.possible_changeling_IDs)]" //TODO Ensure unique and actual alieny names
|
||||
//Team Objective
|
||||
var/datum/objective/experiment/team_objective = new
|
||||
team_objective.team = team_number
|
||||
team_objectives[team_number] = team_objective
|
||||
//Team Members
|
||||
if(antag_candidates.len < (!agent + !scientist))
|
||||
return
|
||||
|
||||
if(!preset_agent || !preset_scientist)
|
||||
if(antag_candidates.len <=2)
|
||||
return 0
|
||||
|
||||
var/datum/mind/scientist
|
||||
var/datum/mind/agent
|
||||
|
||||
if(!preset_scientist)
|
||||
if(!scientist)
|
||||
scientist = pick(antag_candidates)
|
||||
antag_candidates -= scientist
|
||||
else
|
||||
scientist = preset_scientist
|
||||
antag_candidates -= scientist
|
||||
team.members |= scientist
|
||||
scientist.assigned_role = "Abductor Scientist"
|
||||
log_game("[scientist.key] (ckey) has been selected as [team.name] abductor scientist.")
|
||||
|
||||
if(!preset_agent)
|
||||
if(!agent)
|
||||
agent = pick(antag_candidates)
|
||||
antag_candidates -= agent
|
||||
else
|
||||
agent = preset_agent
|
||||
antag_candidates -= agent
|
||||
team.members |= agent
|
||||
agent.assigned_role = "Abductor Agent"
|
||||
log_game("[agent.key] (ckey) has been selected as [team.name] abductor agent.")
|
||||
|
||||
|
||||
scientist.assigned_role = "abductor scientist"
|
||||
scientist.special_role = "abductor scientist"
|
||||
log_game("[scientist.key] (ckey) has been selected as an abductor team [team_number] scientist.")
|
||||
|
||||
agent.assigned_role = "abductor agent"
|
||||
agent.special_role = "abductor agent"
|
||||
log_game("[agent.key] (ckey) has been selected as an abductor team [team_number] agent.")
|
||||
|
||||
abductors |= agent
|
||||
abductors |= scientist
|
||||
scientists[team_number] = scientist
|
||||
agents[team_number] = agent
|
||||
return 1
|
||||
abductor_teams += team
|
||||
return team
|
||||
|
||||
/datum/game_mode/abduction/post_setup()
|
||||
for(var/team_number=1,team_number<=abductor_teams,team_number++)
|
||||
post_setup_team(team_number)
|
||||
for(var/datum/objective_team/abductor_team/team in abductor_teams)
|
||||
post_setup_team(team)
|
||||
return ..()
|
||||
|
||||
//Used for create antag buttons
|
||||
/datum/game_mode/abduction/proc/post_setup_team(team_number)
|
||||
var/list/obj/effect/landmark/abductor/agent_landmarks = list()
|
||||
var/list/obj/effect/landmark/abductor/scientist_landmarks = list()
|
||||
agent_landmarks.len = max_teams
|
||||
scientist_landmarks.len = max_teams
|
||||
for(var/obj/effect/landmark/abductor/A in GLOB.landmarks_list)
|
||||
if(istype(A, /obj/effect/landmark/abductor/agent))
|
||||
agent_landmarks[text2num(A.team)] = A
|
||||
else if(istype(A, /obj/effect/landmark/abductor/scientist))
|
||||
scientist_landmarks[text2num(A.team)] = A
|
||||
|
||||
var/team_name = team_names[team_number]
|
||||
|
||||
var/datum/mind/agent
|
||||
var/obj/effect/landmark/L
|
||||
var/datum/mind/scientist
|
||||
var/mob/living/carbon/human/H
|
||||
var/datum/species/abductor/S
|
||||
|
||||
agent = agents[team_number]
|
||||
H = agent.current
|
||||
L = agent_landmarks[team_number]
|
||||
H.forceMove(L.loc)
|
||||
H.set_species(/datum/species/abductor)
|
||||
S = H.dna.species
|
||||
S.team = team_number
|
||||
H.real_name = team_name + " Agent"
|
||||
H.equipOutfit(/datum/outfit/abductor/agent)
|
||||
greet_agent(agent,team_number)
|
||||
|
||||
|
||||
scientist = scientists[team_number]
|
||||
H = scientist.current
|
||||
L = scientist_landmarks[team_number]
|
||||
H.forceMove(L.loc)
|
||||
H.set_species(/datum/species/abductor)
|
||||
S = H.dna.species
|
||||
S.scientist = TRUE
|
||||
S.team = team_number
|
||||
H.real_name = team_name + " Scientist"
|
||||
H.equipOutfit(/datum/outfit/abductor/scientist)
|
||||
greet_scientist(scientist,team_number)
|
||||
|
||||
|
||||
|
||||
/datum/game_mode/abduction/proc/greet_agent(datum/mind/abductor,team_number)
|
||||
abductor.objectives += team_objectives[team_number]
|
||||
var/team_name = team_names[team_number]
|
||||
|
||||
to_chat(abductor.current, "<span class='notice'>You are an agent of [team_name]!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>With the help of your teammate, kidnap and experiment on station crew members!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve.</span>")
|
||||
|
||||
abductor.announce_objectives()
|
||||
|
||||
/datum/game_mode/abduction/proc/greet_scientist(datum/mind/abductor,team_number)
|
||||
abductor.objectives += team_objectives[team_number]
|
||||
var/team_name = team_names[team_number]
|
||||
|
||||
to_chat(abductor.current, "<span class='notice'>You are a scientist of [team_name]!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>With the help of your teammate, kidnap and experiment on station crew members!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>Use your tool and ship consoles to support the agent and retrieve human specimens.</span>")
|
||||
|
||||
abductor.announce_objectives()
|
||||
|
||||
/datum/game_mode/abduction/proc/get_team_console(team_number)
|
||||
for(var/obj/machinery/abductor/console/C in GLOB.machines)
|
||||
if(C.team == team_number)
|
||||
return C
|
||||
/datum/game_mode/abduction/proc/post_setup_team(datum/objective_team/abductor_team/team)
|
||||
for(var/datum/mind/M in team.members)
|
||||
if(M.assigned_role == "Abductor Scientist")
|
||||
M.add_antag_datum(ANTAG_DATUM_ABDUCTOR_SCIENTIST, team)
|
||||
else
|
||||
M.add_antag_datum(ANTAG_DATUM_ABDUCTOR_AGENT, team)
|
||||
|
||||
/datum/game_mode/abduction/check_finished()
|
||||
if(!finished)
|
||||
for(var/team_number=1,team_number<=abductor_teams,team_number++)
|
||||
var/obj/machinery/abductor/console/con = get_team_console(team_number)
|
||||
var/datum/objective/objective = team_objectives[team_number]
|
||||
if (con.experiment.points >= objective.target_amount)
|
||||
SSshuttle.emergency.request(null, set_coefficient = 0.5)
|
||||
finished = 1
|
||||
return ..()
|
||||
for(var/datum/objective_team/abductor_team/team in abductor_teams)
|
||||
for(var/datum/objective/O in team.objectives)
|
||||
if(O.check_completion())
|
||||
SSshuttle.emergency.request(null, set_coefficient = 0.5)
|
||||
finished = TRUE
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/abduction/declare_completion()
|
||||
for(var/team_number=1,team_number<=abductor_teams,team_number++)
|
||||
var/obj/machinery/abductor/console/console = get_team_console(team_number)
|
||||
var/datum/objective/objective = team_objectives[team_number]
|
||||
var/team_name = team_names[team_number]
|
||||
if(console.experiment.points >= objective.target_amount)
|
||||
to_chat(world, "<span class='greenannounce'>[team_name] team fulfilled its mission!</span>")
|
||||
for(var/datum/objective_team/abductor_team/team in abductor_teams)
|
||||
var/won = TRUE
|
||||
for(var/datum/objective/O in team.objectives)
|
||||
if(!O.check_completion())
|
||||
won = FALSE
|
||||
if(won)
|
||||
to_chat(world, "<span class='greenannounce'>[team.name] team fulfilled its mission!</span>")
|
||||
else
|
||||
to_chat(world, "<span class='boldannounce'>[team_name] team failed its mission.</span>")
|
||||
to_chat(world, "<span class='boldannounce'>[team.name] team failed its mission.</span>")
|
||||
..()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/proc/auto_declare_completion_abduction()
|
||||
var/text = ""
|
||||
@@ -200,40 +123,28 @@
|
||||
text += "<br>"
|
||||
to_chat(world, text)
|
||||
|
||||
//Landmarks
|
||||
// TODO: Split into separate landmarks for prettier ships
|
||||
// LANDMARKS
|
||||
/obj/effect/landmark/abductor
|
||||
var/team = 1
|
||||
var/team_number = 1
|
||||
|
||||
/obj/effect/landmark/abductor/agent
|
||||
/obj/effect/landmark/abductor/scientist
|
||||
|
||||
|
||||
// OBJECTIVES
|
||||
/datum/objective/experiment
|
||||
target_amount = 6
|
||||
var/team
|
||||
|
||||
/datum/objective/experiment/New()
|
||||
explanation_text = "Experiment on [target_amount] humans."
|
||||
|
||||
/datum/objective/experiment/check_completion()
|
||||
var/ab_team = team
|
||||
if(owner)
|
||||
if(!owner.current || !ishuman(owner.current))
|
||||
return 0
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(H.dna.species.id != "abductor")
|
||||
return 0
|
||||
var/datum/species/abductor/S = H.dna.species
|
||||
ab_team = S.team
|
||||
for(var/obj/machinery/abductor/experiment/E in GLOB.machines)
|
||||
if(E.team == ab_team)
|
||||
if(E.points >= target_amount)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
return 0
|
||||
if(!istype(team, /datum/objective_team/abductor_team))
|
||||
return FALSE
|
||||
var/datum/objective_team/abductor_team/T = team
|
||||
if(E.team_number == T.team_number)
|
||||
return E.points >= target_amount
|
||||
return FALSE
|
||||
|
||||
/datum/game_mode/proc/update_abductor_icons_added(datum/mind/alien_mind)
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_ABDUCTOR]
|
||||
|
||||
@@ -532,7 +532,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
flags_2 = BANG_PROTECT_2
|
||||
|
||||
/obj/item/device/radio/headset/abductor/Initialize(mapload)
|
||||
..()
|
||||
. = ..()
|
||||
make_syndie()
|
||||
|
||||
/obj/item/device/radio/headset/abductor/attackby(obj/item/W, mob/user, params)
|
||||
|
||||
@@ -5,20 +5,14 @@
|
||||
back = /obj/item/storage/backpack
|
||||
ears = /obj/item/device/radio/headset/abductor
|
||||
|
||||
/datum/outfit/abductor/proc/get_team_console(team_number)
|
||||
for(var/obj/machinery/abductor/console/C in GLOB.machines)
|
||||
if(C.team == team_number)
|
||||
return C
|
||||
|
||||
/datum/outfit/abductor/proc/link_to_console(mob/living/carbon/human/H, team_number)
|
||||
if(!team_number && isabductor(H))
|
||||
var/datum/species/abductor/S = H.dna.species
|
||||
team_number = S.team
|
||||
|
||||
var/datum/antagonist/abductor/A = H.mind.has_antag_datum(ANTAG_DATUM_ABDUCTOR)
|
||||
if(!team_number && A)
|
||||
team_number = A.team.team_number
|
||||
if(!team_number)
|
||||
team_number = 1
|
||||
|
||||
var/obj/machinery/abductor/console/console = get_team_console(team_number)
|
||||
var/obj/machinery/abductor/console/console = get_abductor_console(team_number)
|
||||
if(console)
|
||||
var/obj/item/clothing/suit/armor/abductor/vest/V = locate() in H
|
||||
if(V)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/obj/machinery/computer/camera_advanced/abductor
|
||||
name = "Human Observation Console"
|
||||
var/team = 0
|
||||
var/team_number = 0
|
||||
networks = list("SS13","Abductor")
|
||||
var/datum/action/innate/teleport_in/tele_in_action = new
|
||||
var/datum/action/innate/teleport_out/tele_out_action = new
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user