mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 17:52:36 +00:00
* Harddel Fix Pack #42 + Better Live Reftracking Support * awooga Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//#define LOWMEMORYMODE //uncomment this to load centcom and runtime station and thats it.
|
||||
#define LOWMEMORYMODE //uncomment this to load centcom and runtime station and thats it.
|
||||
|
||||
#include "map_files\generic\CentCom_skyrat.dmm" //SKYRAT EDIT ADDITION - SMMS
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#define isatom(A) (isloc(A))
|
||||
|
||||
#define isdatum(thing) (istype(thing, /datum))
|
||||
|
||||
#define isweakref(D) (istype(D, /datum/weakref))
|
||||
|
||||
//Turfs
|
||||
|
||||
@@ -57,9 +57,16 @@ GLOBAL_LIST_INIT(testing_global_profiler, list("_PROFILE_NAME" = "Global"))
|
||||
SEND_TEXT(world.log, text)
|
||||
#endif
|
||||
|
||||
#ifdef REFERENCE_TRACKING
|
||||
#if defined(REFERENCE_DOING_IT_LIVE)
|
||||
#define log_reftracker(msg) log_harddel("## REF SEARCH [msg]")
|
||||
|
||||
/proc/log_harddel(text)
|
||||
WRITE_LOG(GLOB.harddel_log, text)
|
||||
|
||||
#elif defined(REFERENCE_TRACKING) // Doing it locally
|
||||
#define log_reftracker(msg) log_world("## REF SEARCH [msg]")
|
||||
#else
|
||||
|
||||
#else //Not tracking at all
|
||||
#define log_reftracker(msg)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* Adds a memory to a mob's mind if conditions are met, called wherever the memory takes place (memory for catching on fire in mob's fire code, for example)
|
||||
* Argument:
|
||||
* * memory_type: defined string in memory_defines.dm, shows the memories.json file which story parts to use (and generally what type it is)
|
||||
* * extra_info: the contents of the story. You're gonna want at least the protagonist for who is the main character in the story
|
||||
* * extra_info: the contents of the story. You're gonna want at least the protagonist for who is the main character in the story (Any non basic type will be converted to a string on insertion)
|
||||
* * story_value: the quality of the memory, make easy or roundstart memories have a low value so they don't flood persistence
|
||||
* * memory_flags: special specifications for skipping parts of the memory like moods for stories where showing moods doesn't make sense
|
||||
* Returns the datum memory created, null otherwise.
|
||||
|
||||
@@ -39,6 +39,16 @@
|
||||
#define TRACK_MAX_SHARE //Allows max share tracking, for use in the atmos debugging ui
|
||||
#endif //ifdef TESTING
|
||||
|
||||
/// If this is uncommented, we set up the ref tracker to be used in a live environment
|
||||
/// And to log events to [log_dir]/harddels.log
|
||||
//#define REFERENCE_DOING_IT_LIVE
|
||||
#ifdef REFERENCE_DOING_IT_LIVE
|
||||
// compile the backend
|
||||
#define REFERENCE_TRACKING
|
||||
// actually look for refs
|
||||
#define GC_FAILURE_HARD_LOOKUP
|
||||
#endif // REFERENCE_DOING_IT_LIVE
|
||||
|
||||
//#define UNIT_TESTS //If this is uncommented, we do a single run though of the game setup and tear down process with unit tests in between
|
||||
|
||||
#ifndef PRELOAD_RSC //set to:
|
||||
|
||||
@@ -89,3 +89,7 @@ GLOBAL_PROTECT(picture_logging_id)
|
||||
GLOBAL_VAR(picture_logging_prefix)
|
||||
GLOBAL_PROTECT(picture_logging_prefix)
|
||||
/////
|
||||
#ifdef REFERENCE_DOING_IT_LIVE
|
||||
GLOBAL_LIST_EMPTY(harddel_log)
|
||||
GLOBAL_PROTECT(harddel_log)
|
||||
#endif
|
||||
|
||||
@@ -144,6 +144,14 @@
|
||||
icon_state = "flash"
|
||||
alpha = 80
|
||||
|
||||
/atom/movable/screen/fullscreen/bluespace_sparkle
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
icon_state = "shieldsparkles"
|
||||
layer = FLASH_LAYER
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
show_when_dead = TRUE
|
||||
|
||||
/atom/movable/screen/fullscreen/color_vision/green
|
||||
color = "#00ff00"
|
||||
|
||||
|
||||
@@ -632,6 +632,9 @@ GLOBAL_LIST_EMPTY(colored_images)
|
||||
/datum/controller/subsystem/air/proc/start_processing_machine(obj/machinery/machine)
|
||||
if(machine.atmos_processing)
|
||||
return
|
||||
if(QDELETED(machine))
|
||||
stack_trace("We tried to add a garbage collecting machine to SSair. Don't")
|
||||
return
|
||||
machine.atmos_processing = TRUE
|
||||
atmos_machinery += machine
|
||||
|
||||
|
||||
@@ -372,7 +372,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
#ifdef REFERENCE_TRACKING
|
||||
if (QDEL_HINT_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion.
|
||||
SSgarbage.Queue(D)
|
||||
D.find_references()
|
||||
D.find_references() //This breaks ci. Consider it insurance against somehow pring reftracking on accident
|
||||
if (QDEL_HINT_IFFAIL_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled and the object fails to collect, display all references to this object.
|
||||
SSgarbage.Queue(D)
|
||||
SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE
|
||||
|
||||
@@ -40,7 +40,8 @@ SUBSYSTEM_DEF(parallax)
|
||||
if(!istype(movable_eye))
|
||||
continue
|
||||
|
||||
for (movable_eye; isloc(movable_eye.loc) && !isturf(movable_eye.loc); movable_eye = movable_eye.loc);
|
||||
while(isloc(movable_eye.loc) && !isturf(movable_eye.loc))
|
||||
movable_eye = movable_eye.loc
|
||||
//get the last movable holding the mobs eye
|
||||
|
||||
if(movable_eye == processing_client.movingmob)
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
|
||||
/datum/action/proc/link_to(Target)
|
||||
target = Target
|
||||
RegisterSignal(Target, COMSIG_ATOM_UPDATED_ICON, .proc/OnUpdatedIcon)
|
||||
RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, .proc/OnUpdatedIcon)
|
||||
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/clear_ref, override = TRUE)
|
||||
|
||||
/datum/action/Destroy()
|
||||
if(owner)
|
||||
@@ -49,7 +50,7 @@
|
||||
return
|
||||
Remove(owner)
|
||||
owner = M
|
||||
RegisterSignal(owner, COMSIG_PARENT_QDELETING, .proc/owner_deleted)
|
||||
RegisterSignal(owner, COMSIG_PARENT_QDELETING, .proc/clear_ref, override = TRUE)
|
||||
|
||||
//button id generation
|
||||
var/counter = 0
|
||||
@@ -75,9 +76,12 @@
|
||||
else
|
||||
Remove(owner)
|
||||
|
||||
/datum/action/proc/owner_deleted(datum/source)
|
||||
/datum/action/proc/clear_ref(datum/ref)
|
||||
SIGNAL_HANDLER
|
||||
if(ref == owner)
|
||||
Remove(owner)
|
||||
if(ref == target)
|
||||
qdel(src)
|
||||
|
||||
/datum/action/proc/Remove(mob/M)
|
||||
for(var/datum/weakref/reference as anything in sharers)
|
||||
@@ -93,7 +97,10 @@
|
||||
M.update_action_buttons()
|
||||
if(owner)
|
||||
UnregisterSignal(owner, COMSIG_PARENT_QDELETING)
|
||||
if(target == owner)
|
||||
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/clear_ref)
|
||||
owner = null
|
||||
if(button)
|
||||
button.moved = FALSE //so the button appears in its normal position when given to another owner.
|
||||
button.locked = FALSE
|
||||
button.id = null
|
||||
|
||||
@@ -22,16 +22,16 @@
|
||||
///Max attemps to make
|
||||
var/max_attempts = 3
|
||||
|
||||
|
||||
/datum/ai_behavior/item_move_close_and_attack/setup(datum/ai_controller/controller, target_key, throw_count_key)
|
||||
. = ..()
|
||||
controller.current_movement_target = controller.blackboard[target_key]
|
||||
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
controller.current_movement_target = target_ref?.resolve()
|
||||
|
||||
/datum/ai_behavior/item_move_close_and_attack/perform(delta_time, datum/ai_controller/controller, target_key, throw_count_key)
|
||||
. = ..()
|
||||
var/obj/item/item_pawn = controller.pawn
|
||||
var/atom/throw_target = controller.blackboard[target_key]
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
var/atom/throw_target = target_ref?.resolve()
|
||||
|
||||
item_pawn.visible_message(span_warning("[item_pawn] hurls towards [throw_target]!"))
|
||||
item_pawn.throw_at(throw_target, rand(4,5), 9)
|
||||
@@ -48,12 +48,15 @@
|
||||
controller.blackboard -= target_key
|
||||
controller.blackboard[throw_count_key] = 0
|
||||
|
||||
/datum/ai_behavior/item_move_close_and_attack/haunted
|
||||
/datum/ai_behavior/item_move_close_and_attack/ghostly
|
||||
attack_sound = 'sound/items/haunted/ghostitemattack.ogg'
|
||||
max_attempts = 4
|
||||
|
||||
/datum/ai_behavior/item_move_close_and_attack/haunted/finish_action(datum/ai_controller/controller, succeeded, target_key, throw_count_key)
|
||||
var/atom/throw_target = controller.blackboard[target_key]
|
||||
/datum/ai_behavior/item_move_close_and_attack/ghostly/haunted
|
||||
|
||||
/datum/ai_behavior/item_move_close_and_attack/ghostly/haunted/finish_action(datum/ai_controller/controller, succeeded, target_key, throw_count_key)
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
var/atom/throw_target = target_ref?.resolve()
|
||||
var/list/hauntee_list = controller.blackboard[BB_TO_HAUNT_LIST]
|
||||
hauntee_list[throw_target]--
|
||||
return ..()
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
/datum/ai_behavior/item_move_close_and_attack/ghostly/cursed
|
||||
|
||||
/datum/ai_behavior/item_move_close_and_attack/cursed
|
||||
attack_sound = 'sound/items/haunted/ghostitemattack.ogg'
|
||||
max_attempts = 4
|
||||
|
||||
/datum/ai_behavior/item_move_close_and_attack/cursed/reset_blackboard(datum/ai_controller/controller, succeeded, target_key, throw_count_key)
|
||||
var/atom/throw_target = controller.blackboard[target_key]
|
||||
/datum/ai_behavior/item_move_close_and_attack/ghostly/cursed/reset_blackboard(datum/ai_controller/controller, succeeded, target_key, throw_count_key)
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
var/atom/throw_target = target_ref?.resolve()
|
||||
//dropping our target from the blackboard if they are no longer a valid target after the attack behavior
|
||||
if(get_dist(throw_target, controller.pawn) > CURSED_VIEW_RANGE)
|
||||
controller.blackboard[target_key] = null
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
var/obj/item/item_pawn = controller.pawn
|
||||
|
||||
//make sure we have a target
|
||||
var/mob/living/carbon/curse_target = controller.blackboard[BB_CURSE_TARGET]
|
||||
var/datum/weakref/target_ref = controller.blackboard[BB_CURSE_TARGET]
|
||||
var/mob/living/carbon/curse_target = target_ref?.resolve()
|
||||
if(!curse_target)
|
||||
controller.queue_behavior(/datum/ai_behavior/find_and_set, BB_CURSE_TARGET, /mob/living/carbon, CURSED_VIEW_RANGE)
|
||||
return
|
||||
@@ -11,4 +12,4 @@
|
||||
controller.blackboard[BB_CURSE_TARGET] = null
|
||||
return
|
||||
controller.current_movement_target = curse_target
|
||||
controller.queue_behavior(/datum/ai_behavior/item_move_close_and_attack/cursed)
|
||||
controller.queue_behavior(/datum/ai_behavior/item_move_close_and_attack/ghostly/cursed)
|
||||
|
||||
@@ -79,20 +79,22 @@
|
||||
pawn.activate_hand(pawn.get_active_hand())
|
||||
finish_action(controller, TRUE)
|
||||
|
||||
/// Use the currently held item, or unarmed, on an object in the world
|
||||
/// Use the currently held item, or unarmed, on a weakref to an object in the world
|
||||
/datum/ai_behavior/use_on_object
|
||||
required_distance = 1
|
||||
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT
|
||||
|
||||
/datum/ai_behavior/use_on_object/setup(datum/ai_controller/controller, target_key)
|
||||
. = ..()
|
||||
controller.current_movement_target = controller.blackboard[target_key]
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
controller.current_movement_target = target_ref?.resolve()
|
||||
|
||||
/datum/ai_behavior/use_on_object/perform(delta_time, datum/ai_controller/controller, target_key)
|
||||
. = ..()
|
||||
var/mob/living/pawn = controller.pawn
|
||||
var/obj/item/held_item = pawn.get_item_by_slot(pawn.get_active_hand())
|
||||
var/atom/target = controller.blackboard[BB_MONKEY_CURRENT_PRESS_TARGET]
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
var/atom/target = target_ref?.resolve()
|
||||
|
||||
if(!target || !pawn.CanReach(target))
|
||||
finish_action(controller, FALSE)
|
||||
@@ -113,13 +115,15 @@
|
||||
|
||||
/datum/ai_behavior/give/setup(datum/ai_controller/controller, target_key)
|
||||
. = ..()
|
||||
controller.current_movement_target = controller.blackboard[target_key]
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
controller.current_movement_target = target_ref?.resolve()
|
||||
|
||||
/datum/ai_behavior/give/perform(delta_time, datum/ai_controller/controller, target_key)
|
||||
. = ..()
|
||||
var/mob/living/pawn = controller.pawn
|
||||
var/obj/item/held_item = pawn.get_item_by_slot(pawn.get_active_hand())
|
||||
var/atom/target = controller.blackboard[target_key]
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
var/atom/target = target_ref?.resolve()
|
||||
|
||||
if(!target || !pawn.CanReach(target) || !isliving(target))
|
||||
finish_action(controller, FALSE)
|
||||
@@ -151,12 +155,14 @@
|
||||
|
||||
/datum/ai_behavior/consume/setup(datum/ai_controller/controller, target_key)
|
||||
. = ..()
|
||||
controller.current_movement_target = controller.blackboard[target_key]
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
controller.current_movement_target = target_ref?.resolve()
|
||||
|
||||
/datum/ai_behavior/consume/perform(delta_time, datum/ai_controller/controller, target_key, hunger_timer_key)
|
||||
. = ..()
|
||||
var/mob/living/living_pawn = controller.pawn
|
||||
var/obj/item/target = controller.blackboard[target_key]
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
var/obj/item/target = target_ref.resolve()
|
||||
|
||||
if(!(target in living_pawn.held_items))
|
||||
if(!living_pawn.put_in_hand_check(target))
|
||||
@@ -187,7 +193,7 @@
|
||||
. = ..()
|
||||
var/find_this_thing = search_tactic(controller, locate_path, search_range)
|
||||
if(find_this_thing)
|
||||
controller.blackboard[set_key] = find_this_thing
|
||||
controller.blackboard[set_key] = WEAKREF(find_this_thing)
|
||||
finish_action(controller, TRUE)
|
||||
else
|
||||
finish_action(controller, FALSE)
|
||||
@@ -341,7 +347,8 @@
|
||||
/datum/ai_behavior/setup_instrument/perform(delta_time, datum/ai_controller/controller, song_instrument_key, song_lines_key)
|
||||
. = ..()
|
||||
|
||||
var/obj/item/instrument/song_instrument = controller.blackboard[song_instrument_key]
|
||||
var/datum/weakref/instrument_ref = controller.blackboard[song_instrument_key]
|
||||
var/obj/item/instrument/song_instrument = instrument_ref.resolve()
|
||||
var/datum/song/song = song_instrument.song
|
||||
var/song_lines = controller.blackboard[song_lines_key]
|
||||
|
||||
@@ -357,7 +364,8 @@
|
||||
/datum/ai_behavior/play_instrument/perform(delta_time, datum/ai_controller/controller, song_instrument_key)
|
||||
. = ..()
|
||||
|
||||
var/obj/item/instrument/song_instrument = controller.blackboard[song_instrument_key]
|
||||
var/datum/weakref/instrument_ref = controller.blackboard[song_instrument_key]
|
||||
var/obj/item/instrument/song_instrument = instrument_ref.resolve()
|
||||
var/datum/song/song = song_instrument.song
|
||||
|
||||
song.start_playing(controller.pawn)
|
||||
@@ -377,5 +385,5 @@
|
||||
possible_targets += thing
|
||||
if(!possible_targets.len)
|
||||
finish_action(controller, FALSE)
|
||||
controller.blackboard[target_key] = pick(possible_targets)
|
||||
controller.blackboard[target_key] = WEAKREF(pick(possible_targets))
|
||||
finish_action(controller, TRUE)
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
* * BB_SONG_LINES - not set by this subtree, is the song loaded into the song datum.
|
||||
*/
|
||||
/datum/ai_planning_subtree/generic_play_instrument/SelectBehaviors(datum/ai_controller/controller, delta_time)
|
||||
if(!controller.blackboard[BB_SONG_INSTRUMENT])
|
||||
var/datum/weakref/player_ref = controller.blackboard[BB_SONG_INSTRUMENT]
|
||||
var/obj/item/instrument/song_player = player_ref?.resolve()
|
||||
|
||||
if(!song_player)
|
||||
controller.queue_behavior(/datum/ai_behavior/find_and_set/in_hands, BB_SONG_INSTRUMENT, /obj/item/instrument)
|
||||
return //we can't play a song since we do not have an instrument
|
||||
|
||||
var/obj/item/instrument/song_player = controller.blackboard[BB_SONG_INSTRUMENT]
|
||||
|
||||
var/list/parsed_song_lines = splittext(controller.blackboard[BB_SONG_LINES], "\n")
|
||||
popleft(parsed_song_lines) //remove BPM as it is parsed out
|
||||
if(!compare_list(song_player.song.lines, parsed_song_lines) || !song_player.song.repeat)
|
||||
@@ -53,7 +54,8 @@
|
||||
if(world.time < controller.blackboard[BB_NEXT_HUNGRY])
|
||||
return
|
||||
|
||||
if(!controller.blackboard[BB_FOOD_TARGET])
|
||||
var/datum/weakref/food_ref = controller.blackboard[BB_FOOD_TARGET]
|
||||
if(!food_ref?.resolve())
|
||||
controller.queue_behavior(/datum/ai_behavior/find_and_set/edible, BB_FOOD_TARGET, /obj/item, 2)
|
||||
return
|
||||
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
|
||||
var/list/to_haunt_list = controller.blackboard[BB_TO_HAUNT_LIST]
|
||||
|
||||
for(var/i in to_haunt_list)
|
||||
if(to_haunt_list[i] <= 0)
|
||||
for(var/mob/living/potential_target as anything in to_haunt_list)
|
||||
if(to_haunt_list[potential_target] <= 0)
|
||||
to_haunt_list -= potential_target
|
||||
continue
|
||||
var/mob/living/potential_target = i
|
||||
if(get_dist(potential_target, item_pawn) <= 7)
|
||||
controller.blackboard[BB_HAUNT_TARGET] = potential_target
|
||||
controller.queue_behavior(/datum/ai_behavior/item_move_close_and_attack/haunted, BB_HAUNT_TARGET, BB_HAUNTED_THROW_ATTEMPT_COUNT)
|
||||
controller.queue_behavior(/datum/ai_behavior/item_move_close_and_attack/ghostly/haunted, BB_HAUNT_TARGET, BB_HAUNTED_THROW_ATTEMPT_COUNT)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
|
||||
// flee from anyone who attacked us and we didn't beat down
|
||||
for(var/mob/living/L in view(living_pawn, MONKEY_FLEE_VISION))
|
||||
if(controller.blackboard[BB_MONKEY_ENEMIES][L] && L.stat == CONSCIOUS)
|
||||
if(controller.blackboard[BB_MONKEY_ENEMIES][WEAKREF(L)] && L.stat == CONSCIOUS)
|
||||
target = L
|
||||
break
|
||||
|
||||
@@ -141,12 +141,14 @@
|
||||
|
||||
/datum/ai_behavior/monkey_attack_mob/setup(datum/ai_controller/controller, target_key)
|
||||
. = ..()
|
||||
controller.current_movement_target = controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET]
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
controller.current_movement_target = target_ref?.resolve()
|
||||
|
||||
/datum/ai_behavior/monkey_attack_mob/perform(delta_time, datum/ai_controller/controller, target_key)
|
||||
. = ..()
|
||||
|
||||
var/mob/living/target = controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET]
|
||||
var/datum/weakref/target_ref = controller.blackboard[target_key]
|
||||
var/mob/living/target = target_ref?.resolve()
|
||||
var/mob/living/living_pawn = controller.pawn
|
||||
|
||||
if(!target || target.stat != CONSCIOUS)
|
||||
@@ -167,11 +169,11 @@
|
||||
monkey_attack(controller, target, delta_time, FALSE)
|
||||
|
||||
|
||||
/datum/ai_behavior/monkey_attack_mob/finish_action(datum/ai_controller/controller, succeeded)
|
||||
/datum/ai_behavior/monkey_attack_mob/finish_action(datum/ai_controller/controller, succeeded, target_key)
|
||||
. = ..()
|
||||
var/mob/living/living_pawn = controller.pawn
|
||||
walk(living_pawn, 0)
|
||||
controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET] = null
|
||||
controller.blackboard[target_key] = null
|
||||
|
||||
/// attack using a held weapon otherwise bite the enemy, then if we are angry there is a chance we might calm down a little
|
||||
/datum/ai_behavior/monkey_attack_mob/proc/monkey_attack(datum/ai_controller/controller, mob/living/target, delta_time, disarm)
|
||||
@@ -219,14 +221,16 @@
|
||||
if(controller.blackboard[BB_MONKEY_AGGRESSIVE])
|
||||
return
|
||||
|
||||
/// mob refs are uids, so this is safe
|
||||
var/datum/weakref/target_ref = WEAKREF(target)
|
||||
if(DT_PROB(MONKEY_HATRED_REDUCTION_PROB, delta_time))
|
||||
controller.blackboard[BB_MONKEY_ENEMIES][target]--
|
||||
controller.blackboard[BB_MONKEY_ENEMIES][target_ref]--
|
||||
|
||||
// if we are not angry at our target, go back to idle
|
||||
if(controller.blackboard[BB_MONKEY_ENEMIES][target] <= 0)
|
||||
if(controller.blackboard[BB_MONKEY_ENEMIES][target_ref] <= 0)
|
||||
var/list/enemies = controller.blackboard[BB_MONKEY_ENEMIES]
|
||||
enemies.Remove(target)
|
||||
if(controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET] == target)
|
||||
enemies.Remove(target_ref)
|
||||
if(controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET] == WEAKREF(target))
|
||||
finish_action(controller, TRUE)
|
||||
|
||||
/datum/ai_behavior/disposal_mob
|
||||
@@ -234,8 +238,8 @@
|
||||
|
||||
/datum/ai_behavior/disposal_mob/setup(datum/ai_controller/controller, attack_target_key, disposal_target_key)
|
||||
. = ..()
|
||||
controller.current_movement_target = controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET]
|
||||
|
||||
var/datum/weakref/target_ref = controller.blackboard[attack_target_key]
|
||||
controller.current_movement_target = target_ref?.resolve()
|
||||
|
||||
/datum/ai_behavior/disposal_mob/finish_action(datum/ai_controller/controller, succeeded, attack_target_key, disposal_target_key)
|
||||
. = ..()
|
||||
@@ -249,7 +253,8 @@
|
||||
if(controller.blackboard[BB_MONKEY_DISPOSING]) //We are disposing, don't do ANYTHING!!!!
|
||||
return
|
||||
|
||||
var/mob/living/target = controller.blackboard[attack_target_key]
|
||||
var/datum/weakref/target_ref = controller.blackboard[attack_target_key]
|
||||
var/mob/living/target = target_ref?.resolve()
|
||||
var/mob/living/living_pawn = controller.pawn
|
||||
|
||||
controller.current_movement_target = target
|
||||
@@ -259,7 +264,8 @@
|
||||
target.grabbedby(living_pawn)
|
||||
return //Do the rest next turn
|
||||
|
||||
var/obj/machinery/disposal/disposal = controller.blackboard[disposal_target_key]
|
||||
var/datum/weakref/disposal_ref = controller.blackboard[disposal_target_key]
|
||||
var/obj/machinery/disposal/disposal = disposal_ref.resolve()
|
||||
controller.current_movement_target = disposal
|
||||
|
||||
if(living_pawn.Adjacent(disposal))
|
||||
@@ -269,7 +275,8 @@
|
||||
|
||||
/datum/ai_behavior/disposal_mob/proc/try_disposal_mob(datum/ai_controller/controller, attack_target_key, disposal_target_key)
|
||||
var/mob/living/living_pawn = controller.pawn
|
||||
var/mob/living/target = controller.blackboard[attack_target_key]
|
||||
var/datum/weakref/target_ref = controller.blackboard[attack_target_key]
|
||||
var/mob/living/target = target_ref?.resolve()
|
||||
var/obj/machinery/disposal/disposal = controller.blackboard[disposal_target_key]
|
||||
|
||||
controller.blackboard[BB_MONKEY_DISPOSING] = TRUE
|
||||
@@ -292,9 +299,9 @@
|
||||
if(!DT_PROB(MONKEY_RECRUIT_PROB, delta_time))
|
||||
continue
|
||||
var/datum/ai_controller/monkey/monkey_ai = L.ai_controller
|
||||
var/atom/your_enemy = controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET]
|
||||
var/datum/weakref/enemy_ref = controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET]
|
||||
var/list/enemies = L.ai_controller.blackboard[BB_MONKEY_ENEMIES]
|
||||
enemies[your_enemy] = MONKEY_RECRUIT_HATED_AMOUNT
|
||||
enemies[enemy_ref] = MONKEY_RECRUIT_HATED_AMOUNT
|
||||
monkey_ai.blackboard[BB_MONKEY_RECRUIT_COOLDOWN] = world.time + MONKEY_RECRUIT_COOLDOWN
|
||||
finish_action(controller, TRUE)
|
||||
|
||||
@@ -302,10 +309,11 @@
|
||||
var/list/enemies = controller.blackboard[enemies_key]
|
||||
var/list/valids = list()
|
||||
for(var/mob/living/possible_enemy in view(MONKEY_ENEMY_VISION, controller.pawn))
|
||||
if(possible_enemy == controller.pawn || (!enemies[possible_enemy] && (!controller.blackboard[BB_MONKEY_AGGRESSIVE] || HAS_AI_CONTROLLER_TYPE(possible_enemy, /datum/ai_controller/monkey)))) //Are they an enemy? (And do we even care?)
|
||||
var/datum/weakref/enemy_ref = WEAKREF(possible_enemy)
|
||||
if(possible_enemy == controller.pawn || (!enemies[enemy_ref] && (!controller.blackboard[BB_MONKEY_AGGRESSIVE] || HAS_AI_CONTROLLER_TYPE(possible_enemy, /datum/ai_controller/monkey)))) //Are they an enemy? (And do we even care?)
|
||||
continue
|
||||
// Weighted list, so the closer they are the more likely they are to be chosen as the enemy
|
||||
valids[possible_enemy] = CEILING(100 / (get_dist(controller.pawn, possible_enemy) || 1), 1)
|
||||
valids[enemy_ref] = CEILING(100 / (get_dist(controller.pawn, possible_enemy) || 1), 1)
|
||||
|
||||
if(!valids.len)
|
||||
finish_action(controller, FALSE)
|
||||
|
||||
@@ -125,7 +125,7 @@ have ways of interacting with a specific mob and control it.
|
||||
///Reactive events to being hit
|
||||
/datum/ai_controller/monkey/proc/retaliate(mob/living/L)
|
||||
var/list/enemies = blackboard[BB_MONKEY_ENEMIES]
|
||||
enemies[L] += MONKEY_HATRED_AMOUNT
|
||||
enemies[WEAKREF(L)] += MONKEY_HATRED_AMOUNT
|
||||
|
||||
/datum/ai_controller/monkey/proc/on_attackby(datum/source, obj/item/I, mob/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
controller.queue_behavior(/datum/ai_behavior/monkey_set_combat_target, BB_MONKEY_CURRENT_ATTACK_TARGET, BB_MONKEY_ENEMIES)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
var/mob/living/selected_enemy = controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET]
|
||||
var/datum/weakref/target_ref = controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET]
|
||||
var/mob/living/selected_enemy = target_ref?.resolve()
|
||||
|
||||
if(!selected_enemy.stat) //He's up, get him!
|
||||
if(living_pawn.health < MONKEY_FLEE_HEALTH) //Time to skeddadle
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
var/obj/item/item_pawn = controller.pawn
|
||||
|
||||
//make sure we have a target
|
||||
var/mob/living/carbon/curse_target = controller.blackboard[BB_ITEM_TARGET]
|
||||
var/datum/weakref/target_ref = controller.blackboard[BB_ITEM_TARGET]
|
||||
var/mob/living/carbon/curse_target = target_ref?.resolve()
|
||||
|
||||
if(curse_target && get_dist(curse_target, item_pawn) > ITEM_AGGRO_VIEW_RANGE)
|
||||
controller.blackboard[BB_ITEM_TARGET] = null
|
||||
return
|
||||
|
||||
if(!controller.blackboard[BB_ITEM_TARGET])
|
||||
if(!curse_target)
|
||||
controller.queue_behavior(/datum/ai_behavior/find_and_set/item_target, BB_ITEM_TARGET, /mob/living/carbon, ITEM_AGGRO_VIEW_RANGE)
|
||||
|
||||
controller.queue_behavior(/datum/ai_behavior/item_move_close_and_attack/ghostly, BB_ITEM_TARGET, BB_ITEM_THROW_ATTEMPT_COUNT)
|
||||
|
||||
@@ -11,45 +11,3 @@
|
||||
item_pawn.visible_message(span_warning("[item_pawn] slips out of the hands of [item_holder]!"))
|
||||
item_holder.dropItemToGround(item_pawn, TRUE)
|
||||
finish_action(controller, TRUE)
|
||||
|
||||
///This behavior is for obj/items, it is used to move closer to a target and throw themselves towards them.
|
||||
/datum/ai_behavior/item_move_close_and_attack
|
||||
required_distance = 3
|
||||
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT
|
||||
action_cooldown = 20
|
||||
///Sound to use
|
||||
var/attack_sound
|
||||
///Max attempts to make
|
||||
var/max_attempts = 3
|
||||
|
||||
|
||||
/datum/ai_behavior/item_move_close_and_attack/setup(datum/ai_controller/controller, aggro_list_key, target_key, throw_count_key)
|
||||
. = ..()
|
||||
controller.current_movement_target = controller.blackboard[target_key]
|
||||
|
||||
|
||||
/datum/ai_behavior/item_move_close_and_attack/perform(delta_time, datum/ai_controller/controller, aggro_list_key, target_key, throw_count_key)
|
||||
. = ..()
|
||||
var/obj/item/item_pawn = controller.pawn
|
||||
var/atom/throw_target = controller.blackboard[target_key]
|
||||
|
||||
item_pawn.visible_message(span_warning("[item_pawn] hurls towards [throw_target]!"))
|
||||
item_pawn.throw_at(throw_target, rand(4,5), 9)
|
||||
playsound(item_pawn.loc, attack_sound, 100, TRUE)
|
||||
controller.blackboard[throw_count_key]++
|
||||
if(controller.blackboard[throw_count_key] >= max_attempts)
|
||||
finish_action(controller, TRUE, target_key, throw_count_key)
|
||||
|
||||
/datum/ai_behavior/item_move_close_and_attack/finish_action(datum/ai_controller/controller, succeeded, aggro_list_key, target_key, throw_count_key)
|
||||
. = ..()
|
||||
var/atom/throw_target = controller.blackboard[target_key]
|
||||
|
||||
controller.blackboard -= target_key
|
||||
controller.blackboard[throw_count_key] = 0
|
||||
if(aggro_list_key)
|
||||
var/list/aggro_list = controller.blackboard[aggro_list_key]
|
||||
aggro_list[throw_target]--
|
||||
|
||||
/datum/ai_behavior/item_move_close_and_attack/ghostly
|
||||
attack_sound = 'sound/items/haunted/ghostitemattack.ogg'
|
||||
max_attempts = 4
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
if(found_seat)
|
||||
customer_pawn.say(pick(customer_data.found_seat_lines))
|
||||
controller.blackboard[BB_CUSTOMER_MY_SEAT] = found_seat
|
||||
controller.blackboard[BB_CUSTOMER_MY_SEAT] = WEAKREF(found_seat)
|
||||
attending_venue.linked_seats[found_seat] = customer_pawn
|
||||
finish_action(controller, TRUE)
|
||||
return
|
||||
@@ -47,7 +47,9 @@
|
||||
var/mob/living/simple_animal/robot_customer/customer_pawn = controller.pawn
|
||||
var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO]
|
||||
|
||||
if(get_turf(controller.blackboard[BB_CUSTOMER_MY_SEAT]) == get_turf(customer_pawn))
|
||||
var/datum/weakref/seat_ref = controller.blackboard[BB_CUSTOMER_MY_SEAT]
|
||||
var/obj/structure/holosign/robot_seat/seat_marker = seat_ref?.resolve()
|
||||
if(get_turf(seat_marker) == get_turf(customer_pawn))
|
||||
var/obj/structure/chair/my_seat = locate(/obj/structure/chair) in get_turf(customer_pawn)
|
||||
if(my_seat)
|
||||
controller.pawn.setDir(my_seat.dir) //Sit in your seat
|
||||
@@ -79,7 +81,9 @@
|
||||
var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO]
|
||||
customer_pawn.say(pick(customer_data.wait_for_food_lines))
|
||||
|
||||
if(get_turf(controller.blackboard[BB_CUSTOMER_MY_SEAT]) == get_turf(controller.pawn))
|
||||
var/datum/weakref/seat_ref = controller.blackboard[BB_CUSTOMER_MY_SEAT]
|
||||
var/obj/structure/holosign/robot_seat/seat_marker = seat_ref?.resolve()
|
||||
if(get_turf(seat_marker) == get_turf(controller.pawn))
|
||||
var/obj/structure/chair/my_seat = locate(/obj/structure/chair) in get_turf(controller.pawn)
|
||||
if(my_seat)
|
||||
controller.pawn.setDir(my_seat.dir) //Sit in your seat
|
||||
|
||||
@@ -67,9 +67,10 @@
|
||||
var/mob/living/simple_animal/robot_customer/customer = pawn
|
||||
var/datum/venue/attending_venue = blackboard[BB_CUSTOMER_ATTENDING_VENUE]
|
||||
var/datum/customer_data/customer_data = blackboard[BB_CUSTOMER_CUSTOMERINFO]
|
||||
attending_venue.mob_blacklist[greytider] += 1
|
||||
//Living mobs are tagged, so these will always be valid
|
||||
attending_venue.mob_blacklist[REF(greytider)] += 1
|
||||
|
||||
switch(attending_venue.mob_blacklist[greytider])
|
||||
switch(attending_venue.mob_blacklist[REF(greytider)])
|
||||
if(1)
|
||||
customer.say(customer_data.first_warning_line)
|
||||
return
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
controller.queue_behavior(/datum/ai_behavior/break_spine, BB_CUSTOMER_CURRENT_TARGET)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
var/obj/my_seat = controller.blackboard[BB_CUSTOMER_MY_SEAT]
|
||||
var/datum/weakref/seat_ref = controller.blackboard[BB_CUSTOMER_MY_SEAT]
|
||||
var/obj/structure/holosign/robot_seat/seat_marker = seat_ref?.resolve()
|
||||
|
||||
if(!my_seat) //We havn't got a seat yet! find one!
|
||||
if(!seat_marker) //We havn't got a seat yet! find one!
|
||||
controller.queue_behavior(/datum/ai_behavior/find_seat)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING
|
||||
|
||||
controller.current_movement_target = my_seat
|
||||
controller.current_movement_target = seat_marker
|
||||
|
||||
if(!controller.blackboard[BB_CUSTOMER_CURRENT_ORDER]) //We havn't ordered yet even ordered yet. go on! go over there and go do it!
|
||||
controller.queue_behavior(/datum/ai_behavior/order_food)
|
||||
|
||||
@@ -85,8 +85,11 @@
|
||||
|
||||
/datum/component/aura_healing/Destroy(force, silent)
|
||||
STOP_PROCESSING(SSaura_healing, src)
|
||||
var/alert_category = "aura_healing_[REF(src)]"
|
||||
|
||||
QDEL_LIST_ASSOC_VAL(current_alerts)
|
||||
for(var/mob/living/alert_holder in current_alerts)
|
||||
alert_holder.clear_alert(alert_category)
|
||||
current_alerts.Cut()
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -108,7 +111,7 @@
|
||||
if (!(candidate in current_alerts))
|
||||
var/atom/movable/screen/alert/aura_healing/alert = candidate.throw_alert(alert_category, /atom/movable/screen/alert/aura_healing, new_master = parent)
|
||||
alert.desc = "You are being healed by [parent]."
|
||||
current_alerts[candidate] = alert
|
||||
current_alerts += candidate
|
||||
|
||||
if (should_show_effect && candidate.health < candidate.maxHealth)
|
||||
new /obj/effect/temp_visual/heal(get_turf(candidate), healing_color)
|
||||
|
||||
@@ -38,4 +38,4 @@
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
H.physiology.damage_resistance += 100
|
||||
..()
|
||||
return ..()
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
var/skill_mod
|
||||
///Some gloves, generally ones that increase mobility, may have a minimum distance to fly. Rocket gloves are especially dangerous with this, be sure you'll hit your target or have a clear background if you miss, or else!
|
||||
var/min_distance
|
||||
///The throwdatum we're currently dealing with, if we need it
|
||||
var/datum/thrownthing/tackle
|
||||
///A wearkef to the throwdatum we're currently dealing with, if we need it
|
||||
var/datum/weakref/tackle_ref
|
||||
|
||||
/datum/component/tackler/Initialize(stamina_cost = 25, base_knockdown = 1 SECONDS, range = 4, speed = 1, skill_mod = 0, min_distance = min_distance)
|
||||
if(!iscarbon(parent))
|
||||
@@ -61,10 +61,10 @@
|
||||
UnregisterSignal(parent, list(COMSIG_MOB_CLICKON, COMSIG_MOVABLE_IMPACT, COMSIG_MOVABLE_MOVED, COMSIG_MOVABLE_POST_THROW))
|
||||
|
||||
///Store the thrownthing datum for later use
|
||||
/datum/component/tackler/proc/registerTackle(mob/living/carbon/user, datum/thrownthing/TT)
|
||||
/datum/component/tackler/proc/registerTackle(mob/living/carbon/user, datum/thrownthing/tackle)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
tackle = TT
|
||||
tackle_ref = WEAKREF(tackle)
|
||||
tackle.thrower = user
|
||||
|
||||
///See if we can tackle or not. If we can, leap!
|
||||
@@ -143,7 +143,9 @@
|
||||
/datum/component/tackler/proc/sack(mob/living/carbon/user, atom/hit)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/datum/thrownthing/tackle = tackle_ref?.resolve()
|
||||
if(!tackling || !tackle)
|
||||
tackle = null
|
||||
return
|
||||
|
||||
user.toggle_throw_mode()
|
||||
@@ -445,7 +447,7 @@
|
||||
|
||||
/datum/component/tackler/proc/resetTackle()
|
||||
tackling = FALSE
|
||||
QDEL_NULL(tackle)
|
||||
QDEL_NULL(tackle_ref)
|
||||
UnregisterSignal(parent, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
///A special case for splatting for handling windows
|
||||
@@ -526,7 +528,10 @@
|
||||
I.throw_at(get_ranged_target_turf(I, pick(GLOB.alldirs), range = dist), range = dist, speed = sp)
|
||||
I.visible_message(span_danger("[I] goes flying[sp > 3 ? " dangerously fast" : ""]!")) // standard embed speed
|
||||
|
||||
var/datum/thrownthing/tackle = tackle_ref?.resolve()
|
||||
|
||||
playsound(owner, 'sound/weapons/smash.ogg', 70, TRUE)
|
||||
if(tackle)
|
||||
tackle.finalize(hit=TRUE)
|
||||
resetTackle()
|
||||
|
||||
|
||||
@@ -145,7 +145,10 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
|
||||
new_dna.species = new species.type
|
||||
new_dna.species.species_traits = species.species_traits
|
||||
new_dna.real_name = real_name
|
||||
new_dna.mutations = mutations.Copy()
|
||||
// Mutations aren't gc managed, but they still aren't templates
|
||||
// Let's do a proper copy
|
||||
for(var/datum/mutation/human/mutation in mutations)
|
||||
new_dna.add_mutation(mutation, mutation.class, mutation.timeout)
|
||||
|
||||
//See mutation.dm for what 'class' does. 'time' is time till it removes itself in decimals. 0 for no timer
|
||||
/datum/dna/proc/add_mutation(mutation, class = MUT_OTHER, time)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
var/datum/mind/memorizer_mind
|
||||
///the action done to the target, see memory.dm in _DEFINES
|
||||
var/action
|
||||
///extra information used in the memories to more accurately describe what happened. Assoc list of key -> string identifying what kind of info it is, value is an atom or string identifying the detail.
|
||||
///extra information used in the memories to more accurately describe what happened. Assoc list of key -> string identifying what kind of info it is, value is a string identifying the detail.
|
||||
var/list/extra_info
|
||||
///mood of the person memorizing the event when it happend. can change the style.
|
||||
var/memorizer_mood
|
||||
@@ -24,6 +24,14 @@
|
||||
src.memorizer_mind = memorizer_mind
|
||||
src.memorizer = memorizer
|
||||
src.action = action
|
||||
//You can feed atoms in, but they're gonna be reduced to text
|
||||
for(var/key in extra_info)
|
||||
var/thing = extra_info[key]
|
||||
if(!isdatum(thing))
|
||||
continue
|
||||
var/datum/reduce_to_string = thing
|
||||
extra_info[key] = "[reduce_to_string]"
|
||||
|
||||
src.extra_info = extra_info
|
||||
src.memorizer_mood = memorizer_mood
|
||||
src.story_value = story_value
|
||||
|
||||
@@ -716,13 +716,13 @@
|
||||
* and gives them a fallback spell if no uplink was found
|
||||
*/
|
||||
/datum/mind/proc/try_give_equipment_fallback()
|
||||
var/datum/component/uplink/uplink
|
||||
var/uplink_exists
|
||||
var/datum/antagonist/traitor/traitor_datum = has_antag_datum(/datum/antagonist/traitor)
|
||||
if(traitor_datum)
|
||||
uplink = traitor_datum.uplink
|
||||
if(!uplink)
|
||||
uplink = find_syndicate_uplink(check_unlocked = TRUE)
|
||||
if(!uplink && !(locate(/obj/effect/proc_holder/spell/self/special_equipment_fallback) in spell_list))
|
||||
uplink_exists = traitor_datum.uplink_ref
|
||||
if(!uplink_exists)
|
||||
uplink_exists = find_syndicate_uplink(check_unlocked = TRUE)
|
||||
if(!uplink_exists && !(locate(/obj/effect/proc_holder/spell/self/special_equipment_fallback) in spell_list))
|
||||
AddSpell(new /obj/effect/proc_holder/spell/self/special_equipment_fallback(null, src))
|
||||
|
||||
/datum/mind/proc/take_uplink()
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
var/instability = 0 //instability the holder gets when the mutation is not native
|
||||
var/blocks = 4 //Amount of those big blocks with gene sequences
|
||||
var/difficulty = 8 //Amount of missing sequences. Sometimes it removes an entire pair for 2 points
|
||||
var/timed = FALSE //Boolean to easily check if we're going to self-destruct
|
||||
var/timeout //Time between mutation creation and removal. If this exists, we have a timer
|
||||
var/alias //'Mutation #49', decided every round to get some form of distinction between undiscovered mutations
|
||||
var/scrambled = FALSE //Wheter we can read it if it's active. To avoid cheesing with mutagen
|
||||
var/class //Decides player accesibility, sorta
|
||||
@@ -51,7 +51,7 @@
|
||||
class = class_
|
||||
if(timer)
|
||||
addtimer(CALLBACK(src, .proc/remove), timer)
|
||||
timed = TRUE
|
||||
timeout = timer
|
||||
if(copymut && istype(copymut, /datum/mutation/human))
|
||||
copy_mutation(copymut)
|
||||
update_valid_chromosome_list()
|
||||
|
||||
@@ -141,8 +141,6 @@
|
||||
|
||||
LAZYCLEARLIST(client_mobs_in_contents)
|
||||
|
||||
LAZYCLEARLIST(important_recursive_contents)//has to be before moveToNullspace() so that we can exit our spatial_grid cell if we're in it
|
||||
|
||||
. = ..()
|
||||
|
||||
for(var/movable_content in contents)
|
||||
@@ -150,6 +148,12 @@
|
||||
|
||||
moveToNullspace()
|
||||
|
||||
//This absolutely must be after moveToNullspace()
|
||||
//We rely on Entered and Exited to manage this list, and the copy of this list that is on any /atom/movable "Containers"
|
||||
//If we clear this before the nullspace move, a ref to this object will be hung in any of its movable containers
|
||||
LAZYCLEARLIST(important_recursive_contents)
|
||||
|
||||
|
||||
vis_locs = null //clears this atom out of all viscontents
|
||||
vis_contents.Cut()
|
||||
|
||||
@@ -818,9 +822,9 @@
|
||||
for(var/atom/movable/location as anything in get_nested_locs(src) + src)
|
||||
LAZYREMOVEASSOC(location.important_recursive_contents, RECURSIVE_CONTENTS_AREA_SENSITIVE, src)
|
||||
|
||||
///propogates new_client's mob through our nested contents, similar to other important_recursive_contents procs
|
||||
///propogates ourselves through our nested contents, similar to other important_recursive_contents procs
|
||||
///main difference is that client contents need to possibly duplicate recursive contents for the clients mob AND its eye
|
||||
/atom/movable/proc/enable_client_mobs_in_contents(client/new_client)
|
||||
/mob/proc/enable_client_mobs_in_contents()
|
||||
var/turf/our_turf = get_turf(src)
|
||||
|
||||
if(our_turf && SSspatial_grid.initialized)
|
||||
@@ -829,11 +833,10 @@
|
||||
SSspatial_grid.enter_pre_init_queue(src, RECURSIVE_CONTENTS_CLIENT_MOBS)
|
||||
|
||||
for(var/atom/movable/movable_loc as anything in get_nested_locs(src) + src)
|
||||
LAZYORASSOCLIST(movable_loc.important_recursive_contents, RECURSIVE_CONTENTS_CLIENT_MOBS, new_client.mob)
|
||||
|
||||
///Clears the clients channel of this movables important_recursive_contents list and all nested locs
|
||||
/atom/movable/proc/clear_important_client_contents(client/former_client)
|
||||
LAZYORASSOCLIST(movable_loc.important_recursive_contents, RECURSIVE_CONTENTS_CLIENT_MOBS, src)
|
||||
|
||||
///Clears the clients channel of this mob
|
||||
/mob/proc/clear_important_client_contents()
|
||||
var/turf/our_turf = get_turf(src)
|
||||
|
||||
if(our_turf && SSspatial_grid.initialized)
|
||||
@@ -842,7 +845,7 @@
|
||||
SSspatial_grid.remove_from_pre_init_queue(src, RECURSIVE_CONTENTS_CLIENT_MOBS)
|
||||
|
||||
for(var/atom/movable/movable_loc as anything in get_nested_locs(src) + src)
|
||||
LAZYREMOVEASSOC(movable_loc.important_recursive_contents, RECURSIVE_CONTENTS_CLIENT_MOBS, former_client.mob)
|
||||
LAZYREMOVEASSOC(movable_loc.important_recursive_contents, RECURSIVE_CONTENTS_CLIENT_MOBS, src)
|
||||
|
||||
///Sets the anchored var and returns if it was sucessfully changed or not.
|
||||
/atom/movable/proc/set_anchored(anchorvalue)
|
||||
|
||||
@@ -19,10 +19,6 @@
|
||||
var/obj/item/card/id/inserted_scan_id
|
||||
circuit = /obj/item/circuitboard/computer/bountypad
|
||||
|
||||
/obj/machinery/computer/piratepad_control/civilian/Initialize(mapload)
|
||||
. = ..()
|
||||
pad = /obj/machinery/piratepad/civilian
|
||||
|
||||
/obj/machinery/computer/piratepad_control/civilian/attackby(obj/item/I, mob/living/user, params)
|
||||
if(isidcard(I))
|
||||
if(id_insert(user, I, inserted_scan_id))
|
||||
@@ -33,7 +29,7 @@
|
||||
/obj/machinery/computer/piratepad_control/multitool_act(mob/living/user, obj/item/multitool/I)
|
||||
if(istype(I) && istype(I.buffer,/obj/machinery/piratepad/civilian))
|
||||
to_chat(user, span_notice("You link [src] with [I.buffer] in [I] buffer."))
|
||||
pad = I.buffer
|
||||
pad_ref = WEAKREF(I.buffer)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/piratepad_control/civilian/LateInitialize()
|
||||
@@ -41,10 +37,11 @@
|
||||
if(cargo_hold_id)
|
||||
for(var/obj/machinery/piratepad/civilian/C in GLOB.machines)
|
||||
if(C.cargo_hold_id == cargo_hold_id)
|
||||
pad = C
|
||||
pad_ref = WEAKREF(C)
|
||||
return
|
||||
else
|
||||
pad = locate() in range(4,src)
|
||||
var/obj/machinery/piratepad/civilian/pad = locate() in range(4,src)
|
||||
pad_ref = WEAKREF(pad)
|
||||
|
||||
/obj/machinery/computer/piratepad_control/civilian/recalc()
|
||||
if(sending)
|
||||
@@ -58,6 +55,7 @@
|
||||
playsound(loc, 'sound/machines/synth_no.ogg', 30 , TRUE)
|
||||
return FALSE
|
||||
status_report = "Civilian Bounty: "
|
||||
var/obj/machinery/piratepad/pad = pad_ref?.resolve()
|
||||
for(var/atom/movable/AM in get_turf(pad))
|
||||
if(AM == pad)
|
||||
continue
|
||||
@@ -83,6 +81,7 @@
|
||||
return FALSE
|
||||
var/datum/bounty/curr_bounty = inserted_scan_id.registered_account.civilian_bounty
|
||||
var/active_stack = 0
|
||||
var/obj/machinery/piratepad/pad = pad_ref?.resolve()
|
||||
for(var/atom/movable/AM in get_turf(pad))
|
||||
if(AM == pad)
|
||||
continue
|
||||
@@ -152,7 +151,7 @@
|
||||
/obj/machinery/computer/piratepad_control/civilian/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["points"] = points
|
||||
data["pad"] = pad ? TRUE : FALSE
|
||||
data["pad"] = pad_ref?.resolve() ? TRUE : FALSE
|
||||
data["sending"] = sending
|
||||
data["status_report"] = status_report
|
||||
data["id_inserted"] = inserted_scan_id
|
||||
@@ -178,7 +177,7 @@
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!pad)
|
||||
if(!pad_ref?.resolve())
|
||||
return
|
||||
if(!usr.canUseTopic(src, BE_CLOSE) || (machine_stat & (NOPOWER|BROKEN)))
|
||||
return
|
||||
|
||||
@@ -9,12 +9,17 @@
|
||||
var/mob/camera/ai_eye/remote/eyeobj
|
||||
var/mob/living/current_user = null
|
||||
var/list/networks = list("ss13")
|
||||
var/datum/action/innate/camera_off/off_action = new
|
||||
var/datum/action/innate/camera_jump/jump_action = new
|
||||
///Camera action button to move up a Z level
|
||||
var/datum/action/innate/camera_multiz_up/move_up_action = new
|
||||
///Camera action button to move down a Z level
|
||||
var/datum/action/innate/camera_multiz_down/move_down_action = new
|
||||
/// Typepath of the action button we use as "off"
|
||||
/// It's a typepath so subtypes can give it fun new names
|
||||
var/datum/action/innate/camera_off/off_action
|
||||
/// Typepath for jumping
|
||||
var/datum/action/innate/camera_jump/jump_action
|
||||
/// Typepath of the move up action
|
||||
var/datum/action/innate/camera_multiz_up/move_up_action
|
||||
/// Typepath of the move down action
|
||||
var/datum/action/innate/camera_multiz_down/move_down_action
|
||||
|
||||
/// List of all actions to give to a user when they're well, granted actions
|
||||
var/list/actions = list()
|
||||
///Should we supress any view changes?
|
||||
var/should_supress_view_changes = TRUE
|
||||
@@ -34,6 +39,17 @@
|
||||
if(lock_override & CAMERA_LOCK_CENTCOM)
|
||||
z_lock |= SSmapping.levels_by_trait(ZTRAIT_CENTCOM)
|
||||
|
||||
if(off_action)
|
||||
actions += new off_action(src)
|
||||
if(jump_action)
|
||||
actions += new jump_action(src)
|
||||
//Camera action button to move up a Z level
|
||||
if(move_up_action)
|
||||
actions += new move_up_action(src)
|
||||
//Camera action button to move down a Z level
|
||||
if(move_down_action)
|
||||
actions += new move_down_action(src)
|
||||
|
||||
/obj/machinery/computer/camera_advanced/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock)
|
||||
for(var/i in networks)
|
||||
networks -= i
|
||||
@@ -51,25 +67,8 @@
|
||||
eyeobj.origin = src
|
||||
|
||||
/obj/machinery/computer/camera_advanced/proc/GrantActions(mob/living/user)
|
||||
if(off_action)
|
||||
off_action.target = user
|
||||
off_action.Grant(user)
|
||||
actions += off_action
|
||||
|
||||
if(jump_action)
|
||||
jump_action.target = user
|
||||
jump_action.Grant(user)
|
||||
actions += jump_action
|
||||
|
||||
if(move_up_action)
|
||||
move_up_action.target = user
|
||||
move_up_action.Grant(user)
|
||||
actions += move_up_action
|
||||
|
||||
if(move_down_action)
|
||||
move_down_action.target = user
|
||||
move_down_action.Grant(user)
|
||||
actions += move_down_action
|
||||
for(var/datum/action/to_grant as anything in actions)
|
||||
to_grant.Grant(user)
|
||||
|
||||
/obj/machinery/proc/remove_eye_control(mob/living/user)
|
||||
CRASH("[type] does not implement ai eye handling")
|
||||
@@ -80,7 +79,6 @@
|
||||
for(var/V in actions)
|
||||
var/datum/action/A = V
|
||||
A.Remove(user)
|
||||
actions.Cut()
|
||||
for(var/V in eyeobj.visibleCameraChunks)
|
||||
var/datum/camerachunk/C = V
|
||||
C.remove(eyeobj)
|
||||
@@ -252,12 +250,11 @@
|
||||
button_icon_state = "camera_off"
|
||||
|
||||
/datum/action/innate/camera_off/Activate()
|
||||
if(!target || !isliving(target))
|
||||
if(!owner || !isliving(owner))
|
||||
return
|
||||
var/mob/living/C = target
|
||||
var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
|
||||
var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/console = remote_eye.origin
|
||||
console.remove_eye_control(target)
|
||||
console.remove_eye_control(owner)
|
||||
|
||||
/datum/action/innate/camera_jump
|
||||
name = "Jump To Camera"
|
||||
@@ -265,10 +262,9 @@
|
||||
button_icon_state = "camera_jump"
|
||||
|
||||
/datum/action/innate/camera_jump/Activate()
|
||||
if(!target || !isliving(target))
|
||||
if(!owner || !isliving(owner))
|
||||
return
|
||||
var/mob/living/C = target
|
||||
var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
|
||||
var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/origin = remote_eye.origin
|
||||
|
||||
var/list/L = list()
|
||||
@@ -300,8 +296,8 @@
|
||||
if(final)
|
||||
playsound(origin, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
|
||||
remote_eye.setLoc(get_turf(final))
|
||||
C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static)
|
||||
C.clear_fullscreen("flash", 3) //Shorter flash than normal since it's an ~~advanced~~ console!
|
||||
owner.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static)
|
||||
owner.clear_fullscreen("flash", 3) //Shorter flash than normal since it's an ~~advanced~~ console!
|
||||
else
|
||||
playsound(origin, 'sound/machines/terminal_prompt_deny.ogg', 25, FALSE)
|
||||
|
||||
@@ -311,14 +307,13 @@
|
||||
button_icon_state = "move_up"
|
||||
|
||||
/datum/action/innate/camera_multiz_up/Activate()
|
||||
if(!target || !isliving(target))
|
||||
if(!owner || !isliving(owner))
|
||||
return
|
||||
var/mob/living/user_mob = target
|
||||
var/mob/camera/ai_eye/remote/remote_eye = user_mob.remote_control
|
||||
var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control
|
||||
if(remote_eye.zMove(UP))
|
||||
to_chat(user_mob, span_notice("You move upwards."))
|
||||
to_chat(owner, span_notice("You move upwards."))
|
||||
else
|
||||
to_chat(user_mob, span_notice("You couldn't move upwards!"))
|
||||
to_chat(owner, span_notice("You couldn't move upwards!"))
|
||||
|
||||
/datum/action/innate/camera_multiz_down
|
||||
name = "Move down a floor"
|
||||
@@ -326,11 +321,10 @@
|
||||
button_icon_state = "move_down"
|
||||
|
||||
/datum/action/innate/camera_multiz_down/Activate()
|
||||
if(!target || !isliving(target))
|
||||
if(!owner || !isliving(owner))
|
||||
return
|
||||
var/mob/living/user_mob = target
|
||||
var/mob/camera/ai_eye/remote/remote_eye = user_mob.remote_control
|
||||
var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control
|
||||
if(remote_eye.zMove(DOWN))
|
||||
to_chat(user_mob, span_notice("You move downwards."))
|
||||
to_chat(owner, span_notice("You move downwards."))
|
||||
else
|
||||
to_chat(user_mob, span_notice("You couldn't move downwards!"))
|
||||
to_chat(owner, span_notice("You couldn't move downwards!"))
|
||||
|
||||
@@ -181,11 +181,12 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
ui.open()
|
||||
|
||||
/datum/crewmonitor/proc/show(mob/M, source)
|
||||
ui_sources[WEAKREF(M)] = source
|
||||
ui_sources[WEAKREF(M)] = WEAKREF(source)
|
||||
ui_interact(M)
|
||||
|
||||
/datum/crewmonitor/ui_host(mob/user)
|
||||
return ui_sources[WEAKREF(user)]
|
||||
var/datum/weakref/host_ref = ui_sources[WEAKREF(user)]
|
||||
return host_ref?.resolve()
|
||||
|
||||
/datum/crewmonitor/ui_data(mob/user)
|
||||
var/z = user.z
|
||||
|
||||
@@ -36,14 +36,10 @@
|
||||
/// Do we have someone paying to use this?
|
||||
var/paying_customer = FALSE //Ticked yes if passing inuse()
|
||||
|
||||
/// Who's pockets are we sifting through when we're used?
|
||||
var/datum/bank_account/account //payer's account.
|
||||
/// Who's paying?
|
||||
var/mob/living/carbon/human/H //The person using the console in each instance. Used for paying for the kiosk.
|
||||
var/datum/weakref/paying_ref //The person using the console in each instance. Used for paying for the kiosk.
|
||||
/// Who's getting scanned?
|
||||
var/mob/living/carbon/human/altPatient //If scanning someone else, this will be the target.
|
||||
/// Used to find the money.
|
||||
var/obj/item/card/id/C //the account of the person using the console.
|
||||
var/datum/weakref/patient_ref //If scanning someone else, this will be the target.
|
||||
|
||||
/obj/machinery/medical_kiosk/Initialize(mapload) //loaded subtype for mapping use
|
||||
. = ..()
|
||||
@@ -51,16 +47,20 @@
|
||||
scanner_wand = new/obj/item/scanner_wand(src)
|
||||
|
||||
/obj/machinery/medical_kiosk/proc/inuse() //Verifies that the user can use the interface, followed by showing medical information.
|
||||
if(C?.registered_account)
|
||||
account = C.registered_account
|
||||
if(account?.account_job?.paycheck_department == payment_department)
|
||||
var/mob/living/carbon/human/paying = paying_ref?.resolve()
|
||||
if(!paying)
|
||||
paying_ref = null
|
||||
return
|
||||
|
||||
var/obj/item/card/id/card = paying.get_idcard(TRUE)
|
||||
if(card?.registered_account?.account_job?.paycheck_department == payment_department)
|
||||
use_power(20)
|
||||
paying_customer = TRUE
|
||||
say("Hello, esteemed medical staff!")
|
||||
RefreshParts()
|
||||
return
|
||||
var/bonus_fee = pandemonium ? rand(10,30) : 0
|
||||
if(attempt_charge(src, H, bonus_fee) & COMPONENT_OBJ_CANCEL_CHARGE )
|
||||
if(attempt_charge(src, paying, bonus_fee) & COMPONENT_OBJ_CANCEL_CHARGE )
|
||||
return
|
||||
use_power(20)
|
||||
paying_customer = TRUE
|
||||
@@ -113,9 +113,10 @@
|
||||
span_notice("You press [O] into the side of [src], clicking into place."))
|
||||
//This will be the scanner returning scanner_wand's selected_target variable and assigning it to the altPatient var
|
||||
if(W.selected_target)
|
||||
if(!(altPatient == W.return_patient()))
|
||||
var/datum/weakref/target_ref = WEAKREF(W.return_patient())
|
||||
if(patient_ref != target_ref)
|
||||
clearScans()
|
||||
altPatient = W.return_patient()
|
||||
patient_ref = target_ref
|
||||
user.visible_message(span_notice("[W.return_patient()] has been set as the current patient."))
|
||||
W.selected_target = null
|
||||
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
|
||||
@@ -168,12 +169,13 @@
|
||||
if (ui)
|
||||
ui.close()
|
||||
return
|
||||
patient_distance = get_dist(src.loc,altPatient)
|
||||
if(altPatient == null)
|
||||
var/mob/living/carbon/human/patient = patient_ref?.resolve()
|
||||
patient_distance = get_dist(src.loc, patient)
|
||||
if(patient == null)
|
||||
say("Scanner reset.")
|
||||
altPatient = user
|
||||
patient_ref = WEAKREF(user)
|
||||
else if(patient_distance>5)
|
||||
altPatient = null
|
||||
patient_ref = null
|
||||
say("Patient out of range. Resetting biometrics.")
|
||||
clearScans()
|
||||
return
|
||||
@@ -183,19 +185,22 @@
|
||||
ui.open()
|
||||
icon_state = "[base_icon_state]_active"
|
||||
RefreshParts()
|
||||
H = user
|
||||
C = H.get_idcard(TRUE)
|
||||
var/mob/living/carbon/human/paying = user
|
||||
paying_ref = WEAKREF(paying)
|
||||
|
||||
/obj/machinery/medical_kiosk/ui_data(mob/living/carbon/human/user)
|
||||
var/mob/living/carbon/human/patient = patient_ref?.resolve()
|
||||
var/list/data = list()
|
||||
var/patient_name = altPatient.name
|
||||
if(!patient)
|
||||
return
|
||||
var/patient_name = patient.name
|
||||
var/patient_status = "Alive."
|
||||
var/max_health = altPatient.maxHealth
|
||||
var/total_health = altPatient.health
|
||||
var/brute_loss = altPatient.getBruteLoss()
|
||||
var/fire_loss = altPatient.getFireLoss()
|
||||
var/tox_loss = altPatient.getToxLoss()
|
||||
var/oxy_loss = altPatient.getOxyLoss()
|
||||
var/max_health = patient.maxHealth
|
||||
var/total_health = patient.health
|
||||
var/brute_loss = patient.getBruteLoss()
|
||||
var/fire_loss = patient.getFireLoss()
|
||||
var/tox_loss = patient.getToxLoss()
|
||||
var/oxy_loss = patient.getOxyLoss()
|
||||
var/chaos_modifier = 0
|
||||
|
||||
var/sickness = "Patient does not show signs of disease."
|
||||
@@ -203,18 +208,18 @@
|
||||
|
||||
var/bleed_status = "Patient is not currently bleeding."
|
||||
var/blood_status = " Patient either has no blood, or does not require it to function."
|
||||
var/blood_percent = round((altPatient.blood_volume / BLOOD_VOLUME_NORMAL)*100)
|
||||
var/blood_type = altPatient.dna.blood_type
|
||||
var/blood_percent = round((patient.blood_volume / BLOOD_VOLUME_NORMAL)*100)
|
||||
var/blood_type = patient.dna.blood_type
|
||||
var/blood_warning = " "
|
||||
|
||||
for(var/thing in altPatient.diseases) //Disease Information
|
||||
for(var/thing in patient.diseases) //Disease Information
|
||||
var/datum/disease/D = thing
|
||||
if(!(D.visibility_flags & HIDDEN_SCANNER))
|
||||
sickness = "Warning: Patient is harboring some form of viral disease. Seek further medical attention."
|
||||
sickness_data = "\nName: [D.name].\nType: [D.spread_text].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure_text]"
|
||||
|
||||
if(altPatient.has_dna()) //Blood levels Information
|
||||
if(altPatient.is_bleeding())
|
||||
if(patient.has_dna()) //Blood levels Information
|
||||
if(patient.is_bleeding())
|
||||
bleed_status = "Patient is currently bleeding!"
|
||||
if(blood_percent <= 80)
|
||||
blood_warning = " Patient has low blood levels. Seek a large meal, or iron supplements."
|
||||
@@ -223,12 +228,12 @@
|
||||
blood_status = "Patient blood levels are currently reading [blood_percent]%. Patient has [ blood_type] type blood. [blood_warning]"
|
||||
|
||||
var/trauma_status = "Patient is free of unique brain trauma."
|
||||
var/clone_loss = altPatient.getCloneLoss()
|
||||
var/brain_loss = altPatient.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
var/clone_loss = patient.getCloneLoss()
|
||||
var/brain_loss = patient.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
var/brain_status = "Brain patterns normal."
|
||||
if(LAZYLEN(altPatient.get_traumas()))
|
||||
if(LAZYLEN(patient.get_traumas()))
|
||||
var/list/trauma_text = list()
|
||||
for(var/t in altPatient.get_traumas())
|
||||
for(var/t in patient.get_traumas())
|
||||
var/datum/brain_trauma/trauma = t
|
||||
var/trauma_desc = ""
|
||||
switch(trauma.resilience)
|
||||
@@ -247,15 +252,15 @@
|
||||
var/addict_list = list()
|
||||
var/hallucination_status = "Patient is not hallucinating."
|
||||
|
||||
if(altPatient.reagents.reagent_list.len) //Chemical Analysis details.
|
||||
for(var/r in altPatient.reagents.reagent_list)
|
||||
if(patient.reagents.reagent_list.len) //Chemical Analysis details.
|
||||
for(var/r in patient.reagents.reagent_list)
|
||||
var/datum/reagent/reagent = r
|
||||
if(reagent.chemical_flags & REAGENT_INVISIBLE) //Don't show hidden chems
|
||||
continue
|
||||
chemical_list += list(list("name" = reagent.name, "volume" = round(reagent.volume, 0.01)))
|
||||
if(reagent.overdosed)
|
||||
overdose_list += list(list("name" = reagent.name))
|
||||
var/obj/item/organ/stomach/belly = altPatient.getorganslot(ORGAN_SLOT_STOMACH)
|
||||
var/obj/item/organ/stomach/belly = patient.getorganslot(ORGAN_SLOT_STOMACH)
|
||||
if(belly?.reagents.reagent_list.len) //include the stomach contents if it exists
|
||||
for(var/bile in belly.reagents.reagent_list)
|
||||
var/datum/reagent/bit = bile
|
||||
@@ -267,13 +272,13 @@
|
||||
var/bit_vol = bit.volume - belly.food_reagents[bit.type]
|
||||
if(bit_vol > 0)
|
||||
chemical_list += list(list("name" = bit.name, "volume" = round(bit_vol, 0.01)))
|
||||
for(var/datum/addiction/addiction_type as anything in altPatient.mind.active_addictions)
|
||||
for(var/datum/addiction/addiction_type as anything in patient.mind.active_addictions)
|
||||
addict_list += list(list("name" = initial(addiction_type.name)))
|
||||
|
||||
if (altPatient.hallucinating())
|
||||
if (patient.hallucinating())
|
||||
hallucination_status = "Subject appears to be hallucinating. Suggested treatments: bedrest, mannitol or psicodine."
|
||||
|
||||
if(altPatient.stat == DEAD || HAS_TRAIT(altPatient, TRAIT_FAKEDEATH) || ((brute_loss+fire_loss+tox_loss+oxy_loss+clone_loss) >= 200)) //Patient status checks.
|
||||
if(patient.stat == DEAD || HAS_TRAIT(patient, TRAIT_FAKEDEATH) || ((brute_loss+fire_loss+tox_loss+oxy_loss+clone_loss) >= 200)) //Patient status checks.
|
||||
patient_status = "Dead."
|
||||
if((brute_loss+fire_loss+tox_loss+oxy_loss+clone_loss) >= 80)
|
||||
patient_status = "Gravely Injured"
|
||||
@@ -357,6 +362,6 @@
|
||||
scan_active |= KIOSK_SCANNING_REAGENTS
|
||||
paying_customer = FALSE
|
||||
if("clearTarget")
|
||||
altPatient = null
|
||||
patient_ref = null
|
||||
clearScans()
|
||||
. = TRUE
|
||||
|
||||
@@ -254,7 +254,9 @@
|
||||
|
||||
/obj/effect/anomaly/bluespace/detonate()
|
||||
var/turf/T = pick(get_area_turfs(impact_area))
|
||||
if(T)
|
||||
if(!T)
|
||||
return
|
||||
|
||||
// Calculate new position (searches through beacons in world)
|
||||
var/obj/item/beacon/chosen
|
||||
var/list/possible = list()
|
||||
@@ -264,9 +266,10 @@
|
||||
if(possible.len > 0)
|
||||
chosen = pick(possible)
|
||||
|
||||
if(chosen)
|
||||
// Calculate previous position for transition
|
||||
if(!chosen)
|
||||
return
|
||||
|
||||
// Calculate previous position for transition
|
||||
var/turf/FROM = T // the turf of origin we're travelling FROM
|
||||
var/turf/TO = get_turf(chosen) // the turf of origin we're travelling TO
|
||||
|
||||
@@ -293,22 +296,13 @@
|
||||
A.forceMove(newloc)
|
||||
|
||||
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
|
||||
var/mob/M = A
|
||||
if(M.client)
|
||||
INVOKE_ASYNC(src, .proc/blue_effect, M)
|
||||
var/mob/give_sparkles = A
|
||||
if(give_sparkles.client)
|
||||
blue_effect(give_sparkles)
|
||||
|
||||
/obj/effect/anomaly/bluespace/proc/blue_effect(mob/M)
|
||||
var/obj/blueeffect = new /obj(src)
|
||||
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
blueeffect.icon = 'icons/effects/effects.dmi'
|
||||
blueeffect.icon_state = "shieldsparkles"
|
||||
blueeffect.layer = FLASH_LAYER
|
||||
blueeffect.plane = FULLSCREEN_PLANE
|
||||
blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
M.client.screen += blueeffect
|
||||
sleep(20)
|
||||
M.client.screen -= blueeffect
|
||||
qdel(blueeffect)
|
||||
/obj/effect/anomaly/bluespace/proc/blue_effect(mob/make_sparkle)
|
||||
make_sparkle.overlay_fullscreen("bluespace_flash", /atom/movable/screen/fullscreen/bluespace_sparkle, 1)
|
||||
addtimer(CALLBACK(make_sparkle, /mob/.proc/clear_fullscreen, "bluespace_flash"), 2 SECONDS)
|
||||
|
||||
/////////////////////
|
||||
|
||||
|
||||
@@ -202,8 +202,10 @@
|
||||
///////////////////////////////////////////////
|
||||
//FOAM EFFECT DATUM
|
||||
/datum/effect_system/foam_spread
|
||||
var/amount = 10 // the size of the foam spread.
|
||||
var/obj/chemholder
|
||||
/// the size of the foam spread.
|
||||
var/amount = 10
|
||||
/// Stupid hack alertm exists to hold chems for us
|
||||
var/atom/movable/chem_holder/chemholder
|
||||
effect_type = /obj/effect/particle_effect/foam
|
||||
var/metal = 0
|
||||
|
||||
@@ -221,14 +223,11 @@
|
||||
|
||||
/datum/effect_system/foam_spread/New()
|
||||
..()
|
||||
chemholder = new /obj()
|
||||
var/datum/reagents/R = new/datum/reagents(1000, REAGENT_HOLDER_INSTANT_REACT) //same as above
|
||||
chemholder.reagents = R
|
||||
R.my_atom = chemholder
|
||||
chemholder = new()
|
||||
chemholder.create_reagents(1000, REAGENT_HOLDER_INSTANT_REACT)
|
||||
|
||||
/datum/effect_system/foam_spread/Destroy()
|
||||
qdel(chemholder)
|
||||
chemholder = null
|
||||
QDEL_NULL(chemholder)
|
||||
return ..()
|
||||
|
||||
/datum/effect_system/foam_spread/set_up(amt=5, loca, datum/reagents/carry = null, metaltype = 0)
|
||||
|
||||
@@ -265,20 +265,18 @@
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread/chem
|
||||
var/obj/chemholder
|
||||
/// Evil evil hack so we have something to "hold" our reagents
|
||||
var/atom/movable/chem_holder/chemholder
|
||||
effect_type = /obj/effect/particle_effect/smoke/chem
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/New()
|
||||
..()
|
||||
chemholder = new /obj()
|
||||
var/datum/reagents/R = new (500, REAGENT_HOLDER_INSTANT_REACT) //This is a safety for now to prevent smoke generating more smoke as the smoke reagents react in the smoke. This is prevented naturally from happening even if this is off, but I want to be sure that any edge cases are prevented before I get a chance to rework smoke reactions (specifically adding water or reacting away stabilizing agent in the middle of it).
|
||||
chemholder.reagents = R
|
||||
|
||||
R.my_atom = chemholder
|
||||
chemholder = new()
|
||||
//This is a safety for now to prevent smoke generating more smoke as the smoke reagents react in the smoke. This is prevented naturally from happening even if this is off, but I want to be sure that any edge cases are prevented before I get a chance to rework smoke reactions (specifically adding water or reacting away stabilizing agent in the middle of it).
|
||||
chemholder.create_reagents(500, REAGENT_HOLDER_INSTANT_REACT)
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/Destroy()
|
||||
qdel(chemholder)
|
||||
chemholder = null
|
||||
QDEL_NULL(chemholder)
|
||||
return ..()
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/set_up(datum/reagents/carry = null, radius = 1, loca, silent = FALSE)
|
||||
|
||||
@@ -87,6 +87,8 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
var/slot_flags = 0
|
||||
pass_flags = PASSTABLE
|
||||
pressure_resistance = 4
|
||||
/// This var exists as a weird proxy "owner" ref
|
||||
/// It's used in a few places. Stop using it, and optimially replace all uses please
|
||||
var/obj/item/master = null
|
||||
|
||||
///Price of an item in a vending machine, overriding the base vending machine price. Define in terms of paycheck defines as opposed to raw numbers.
|
||||
@@ -243,7 +245,9 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
updateEmbedding()
|
||||
|
||||
/obj/item/Destroy()
|
||||
item_flags &= ~DROPDEL //prevent reqdels
|
||||
// This var exists as a weird proxy "owner" ref
|
||||
// It's used in a few places. Stop using it, and optimially replace all uses please
|
||||
master = null
|
||||
if(ismob(loc))
|
||||
var/mob/m = loc
|
||||
m.temporarilyRemoveItemFromInventory(src, TRUE)
|
||||
@@ -585,7 +589,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.Remove(user)
|
||||
if(item_flags & DROPDEL)
|
||||
if(item_flags & DROPDEL && !QDELETED(src))
|
||||
qdel(src)
|
||||
item_flags &= ~IN_INVENTORY
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_DROPPED, user)
|
||||
@@ -1054,7 +1058,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
return
|
||||
|
||||
/obj/item/proc/unembedded()
|
||||
if(item_flags & DROPDEL)
|
||||
if(item_flags & DROPDEL && !QDELETED(src))
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
@@ -1080,7 +1084,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
|
||||
|
||||
///In case we want to do something special (like self delete) upon failing to embed in something.
|
||||
/obj/item/proc/failedEmbed()
|
||||
if(item_flags & DROPDEL)
|
||||
if(item_flags & DROPDEL && !QDELETED(src))
|
||||
qdel(src)
|
||||
|
||||
///Called by the carbon throw_item() proc. Returns null if the item negates the throw, or a reference to the thing to suffer the throw else.
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
var/list/stored_data = list()
|
||||
var/current_channel
|
||||
|
||||
var/mob/living/simple_animal/bot/active_bot
|
||||
/// Weakref to the currently controlled bot
|
||||
var/datum/weakref/active_bot_ref
|
||||
var/list/botlist = list()
|
||||
|
||||
/obj/item/cartridge/engineering
|
||||
@@ -680,15 +681,16 @@
|
||||
var/parse = emoji_parse(":[href_list["emoji"]]:")
|
||||
to_chat(usr, parse)
|
||||
|
||||
var/mob/living/simple_animal/bot/active_bot = active_bot_ref?.resolve()
|
||||
|
||||
//Bot control section! Viciously ripped from radios for being laggy and terrible.
|
||||
if(href_list["op"])
|
||||
switch(href_list["op"])
|
||||
|
||||
if("control")
|
||||
active_bot = locate(href_list["bot"]) in GLOB.bots_list
|
||||
|
||||
active_bot_ref = WEAKREF(locate(href_list["bot"]) in GLOB.bots_list)
|
||||
if("botlist")
|
||||
active_bot = null
|
||||
active_bot_ref = null
|
||||
if("summon") //Args are in the correct order, they are stated here just as an easy reminder.
|
||||
active_bot.bot_control("summon", usr, host_pda.GetAccess())
|
||||
else //Forward all other bot commands to the bot itself!
|
||||
@@ -705,7 +707,22 @@
|
||||
|
||||
|
||||
/obj/item/cartridge/proc/bot_control()
|
||||
if(active_bot)
|
||||
var/mob/living/simple_animal/bot/active_bot = active_bot_ref?.resolve()
|
||||
if(!active_bot)
|
||||
menu += "<BR><A href='byond://?src=[REF(src)];op=botlist'>[PDAIMG(refresh)]Scan for active bots</A><BR><BR>"
|
||||
var/turf/current_turf = get_turf(src)
|
||||
var/zlevel = current_turf.z
|
||||
var/botcount = 0
|
||||
for(var/B in GLOB.bots_list) //Git da botz
|
||||
var/mob/living/simple_animal/bot/Bot = B
|
||||
if(!(Bot.bot_mode_flags & BOT_MODE_ON) || Bot.z != zlevel || !(Bot.bot_mode_flags & BOT_MODE_REMOTE_ENABLED) || !(Bot.bot_type in bot_access)) //Only non-emagged bots on the same Z-level are detected!
|
||||
continue //Also, the PDA must have access to the bot type.
|
||||
menu += "<A href='byond://?src=[REF(src)];op=control;bot=[REF(Bot)]'><b>[Bot.name]</b> ([Bot.get_mode()])<BR>"
|
||||
botcount++
|
||||
if(!botcount) //No bots at all? Lame.
|
||||
menu += "No bots found.<BR>"
|
||||
return menu
|
||||
|
||||
menu += "<B>[active_bot]</B><BR> Status: (<A href='byond://?src=[REF(src)];op=control;bot=[REF(active_bot)]'>[PDAIMG(refresh)]<i>refresh</i></A>)<BR>"
|
||||
menu += "Model: [active_bot.bot_type]<BR>"
|
||||
menu += "Location: [get_area(active_bot)]<BR>"
|
||||
@@ -743,20 +760,6 @@
|
||||
menu += "Keep an ID inserted to upload access codes upon summoning."
|
||||
|
||||
menu += "<HR><A href='byond://?src=[REF(src)];op=botlist'>[PDAIMG(back)]Return to bot list</A>"
|
||||
else
|
||||
menu += "<BR><A href='byond://?src=[REF(src)];op=botlist'>[PDAIMG(refresh)]Scan for active bots</A><BR><BR>"
|
||||
var/turf/current_turf = get_turf(src)
|
||||
var/zlevel = current_turf.z
|
||||
var/botcount = 0
|
||||
for(var/B in GLOB.bots_list) //Git da botz
|
||||
var/mob/living/simple_animal/bot/Bot = B
|
||||
if(!(Bot.bot_mode_flags & BOT_MODE_ON) || Bot.z != zlevel || !(Bot.bot_mode_flags & BOT_MODE_REMOTE_ENABLED) || !(Bot.bot_type in bot_access)) //Only non-emagged bots on the same Z-level are detected!
|
||||
continue //Also, the PDA must have access to the bot type.
|
||||
menu += "<A href='byond://?src=[REF(src)];op=control;bot=[REF(Bot)]'><b>[Bot.name]</b> ([Bot.get_mode()])<BR>"
|
||||
botcount++
|
||||
if(!botcount) //No bots at all? Lame.
|
||||
menu += "No bots found.<BR>"
|
||||
return
|
||||
|
||||
return menu
|
||||
|
||||
|
||||
@@ -37,11 +37,11 @@
|
||||
|
||||
/obj/item/flamethrower/Destroy()
|
||||
if(weldtool)
|
||||
qdel(weldtool)
|
||||
QDEL_NULL(weldtool)
|
||||
if(igniter)
|
||||
qdel(igniter)
|
||||
QDEL_NULL(igniter)
|
||||
if(ptank)
|
||||
qdel(ptank)
|
||||
QDEL_NULL(ptank)
|
||||
return ..()
|
||||
|
||||
/obj/item/flamethrower/process()
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
desc = "An industrial computer integrated with a camera-assisted rapid construction drone."
|
||||
networks = list("ss13")
|
||||
circuit = /obj/item/circuitboard/computer/base_construction
|
||||
off_action = new/datum/action/innate/camera_off/base_construction
|
||||
off_action = /datum/action/innate/camera_off/base_construction
|
||||
jump_action = null
|
||||
icon_screen = "mining"
|
||||
icon_keyboard = "rd_key"
|
||||
@@ -23,8 +23,6 @@
|
||||
var/list/structures = list()
|
||||
///Internal RCD. Some construction actions rely on having this.
|
||||
var/obj/item/construction/rcd/internal/internal_rcd
|
||||
///Actions given to the console user to help with base building. Actions are generally carried out at the location of the eyeobj
|
||||
var/list/datum/action/innate/construction_actions
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -38,10 +36,10 @@
|
||||
* Fill the construction_actios list with actions
|
||||
*
|
||||
* Instantiate each action object that we'll be giving to users of
|
||||
* this console, and put it in the construction actions list.
|
||||
* this console, and put it in the actions list
|
||||
*/
|
||||
/obj/machinery/computer/camera_advanced/base_construction/proc/populate_actions_list()
|
||||
construction_actions = list()
|
||||
return
|
||||
|
||||
/**
|
||||
* Reload materials used by the console
|
||||
@@ -81,11 +79,6 @@
|
||||
///Go through every action object in the construction_action list (which should be fully initialized by now) and grant it to the user.
|
||||
/obj/machinery/computer/camera_advanced/base_construction/GrantActions(mob/living/user)
|
||||
..()
|
||||
for (var/datum/action/innate/construction_action in construction_actions)
|
||||
if(construction_action)
|
||||
construction_action.target = src
|
||||
construction_action.Grant(user)
|
||||
actions += construction_action
|
||||
//When the eye is in use, make it visible to players so they know when someone is building.
|
||||
eyeobj.invisibility = 0
|
||||
|
||||
|
||||
@@ -15,13 +15,12 @@
|
||||
structures["turrets"] = 4
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/aux/populate_actions_list()
|
||||
construction_actions = list()
|
||||
construction_actions.Add(new /datum/action/innate/construction/switch_mode())//Action for switching the RCD's build modes
|
||||
construction_actions.Add(new /datum/action/innate/construction/build()) //Action for using the RCD
|
||||
construction_actions.Add(new /datum/action/innate/construction/airlock_type()) //Action for setting the airlock type
|
||||
construction_actions.Add(new /datum/action/innate/construction/window_type()) //Action for setting the window type
|
||||
construction_actions.Add(new /datum/action/innate/construction/place_structure/fan()) //Action for spawning fans
|
||||
construction_actions.Add(new /datum/action/innate/construction/place_structure/turret()) //Action for spawning turrets
|
||||
actions += new /datum/action/innate/construction/switch_mode(src) //Action for switching the RCD's build modes
|
||||
actions += new /datum/action/innate/construction/build(src) //Action for using the RCD
|
||||
actions += new /datum/action/innate/construction/airlock_type(src) //Action for setting the airlock type
|
||||
actions += new /datum/action/innate/construction/window_type(src) //Action for setting the window type
|
||||
actions += new /datum/action/innate/construction/place_structure/fan(src) //Action for spawning fans
|
||||
actions += new /datum/action/innate/construction/place_structure/turret(src) //Action for spawning turrets
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/aux/find_spawn_spot()
|
||||
//Aux base controller. Where the eyeobj will spawn.
|
||||
|
||||
@@ -11,6 +11,5 @@
|
||||
internal_rcd.matter = internal_rcd.max_matter
|
||||
|
||||
/obj/machinery/computer/camera_advanced/base_construction/centcom/populate_actions_list()
|
||||
construction_actions = list()
|
||||
construction_actions.Add(new /datum/action/innate/construction/switch_mode())//Action for switching the RCD's build modes
|
||||
construction_actions.Add(new /datum/action/innate/construction/build()) //Action for using the RCD
|
||||
actions += new /datum/action/innate/construction/switch_mode(src) //Action for switching the RCD's build modes
|
||||
actions += new /datum/action/innate/construction/build(src) //Action for using the RCD
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
AddElement(/datum/element/climbable, climb_time = crate_climb_time, climb_stun = 0)
|
||||
update_appearance()
|
||||
|
||||
/obj/structure/closet/crate/Destroy()
|
||||
QDEL_NULL(manifest)
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/crate/update_overlays()
|
||||
. = ..()
|
||||
if(broken)
|
||||
@@ -80,7 +84,7 @@
|
||||
|
||||
/obj/structure/closet/crate/open(mob/living/user, force = FALSE)
|
||||
. = ..()
|
||||
if(. && manifest)
|
||||
if(. && !QDELETED(manifest))
|
||||
to_chat(user, span_notice("The manifest is torn off [src]."))
|
||||
playsound(src, 'sound/items/poster_ripped.ogg', 75, TRUE)
|
||||
manifest.forceMove(get_turf(src))
|
||||
|
||||
@@ -35,6 +35,9 @@ GLOBAL_VAR(restart_counter)
|
||||
make_datum_references_lists() //initialises global lists for referencing frequently used datums (so that we only ever do it once)
|
||||
|
||||
GLOB.config_error_log = GLOB.world_manifest_log = GLOB.world_pda_log = GLOB.world_job_debug_log = GLOB.sql_error_log = GLOB.world_href_log = GLOB.world_runtime_log = GLOB.world_attack_log = GLOB.world_game_log = GLOB.world_econ_log = GLOB.world_shuttle_log = "data/logs/config_error.[GUID()].log" //temporary file used to record errors with loading config, moved to log directory once logging is set bl
|
||||
#ifdef REFERENCE_DOING_IT_LIVE
|
||||
GLOB.harddel_log = GLOB.world_game_log
|
||||
#endif
|
||||
|
||||
GLOB.revdata = new
|
||||
|
||||
@@ -147,6 +150,10 @@ GLOBAL_VAR(restart_counter)
|
||||
#ifdef UNIT_TESTS
|
||||
GLOB.test_log = "[GLOB.log_directory]/tests.log"
|
||||
start_log(GLOB.test_log)
|
||||
#endif
|
||||
#ifdef REFERENCE_DOING_IT_LIVE
|
||||
GLOB.harddel_log = "[GLOB.log_directory]/harddels.log"
|
||||
start_log(GLOB.harddel_log)
|
||||
#endif
|
||||
start_log(GLOB.world_game_log)
|
||||
start_log(GLOB.world_attack_log)
|
||||
|
||||
@@ -378,7 +378,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/sdql2_vv_all, new(null
|
||||
//print the key
|
||||
if(islist(key))
|
||||
recursive_list_print(output, key, datum_handler, atom_handler)
|
||||
else if(is_proper_datum(key) && (datum_handler || (isatom(key) && atom_handler)))
|
||||
else if(isdatum(key) && (datum_handler || (isatom(key) && atom_handler)))
|
||||
if(isatom(key) && atom_handler)
|
||||
output += atom_handler.Invoke(key)
|
||||
else
|
||||
@@ -392,7 +392,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/sdql2_vv_all, new(null
|
||||
var/value = input[key]
|
||||
if(islist(value))
|
||||
recursive_list_print(output, value, datum_handler, atom_handler)
|
||||
else if(is_proper_datum(value) && (datum_handler || (isatom(value) && atom_handler)))
|
||||
else if(isdatum(value) && (datum_handler || (isatom(value) && atom_handler)))
|
||||
if(isatom(value) && atom_handler)
|
||||
output += atom_handler.Invoke(value)
|
||||
else
|
||||
@@ -684,7 +684,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/sdql2_vv_all, new(null
|
||||
switch(query_tree[1])
|
||||
if("call")
|
||||
for(var/i in found)
|
||||
if(!is_proper_datum(i))
|
||||
if(!isdatum(i))
|
||||
continue
|
||||
world.SDQL_var(i, query_tree["call"][1], null, i, superuser, src)
|
||||
obj_count_finished++
|
||||
@@ -713,7 +713,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/sdql2_vv_all, new(null
|
||||
if("set" in query_tree)
|
||||
var/list/set_list = query_tree["set"]
|
||||
for(var/d in found)
|
||||
if(!is_proper_datum(d))
|
||||
if(!isdatum(d))
|
||||
continue
|
||||
SDQL_internal_vv(d, set_list)
|
||||
obj_count_finished++
|
||||
@@ -724,7 +724,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/sdql2_vv_all, new(null
|
||||
state = SDQL2_STATE_SWITCHING
|
||||
|
||||
/datum/sdql2_query/proc/SDQL_print(object, list/text_list, print_nulls = TRUE)
|
||||
if(is_proper_datum(object))
|
||||
if(isdatum(object))
|
||||
text_list += "<A HREF='?_src_=vars;[HrefToken(TRUE)];Vars=[REF(object)]'>[REF(object)]</A> : [object]"
|
||||
if(istype(object, /atom))
|
||||
var/atom/A = object
|
||||
@@ -1012,7 +1012,7 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/sdql2_vv_all, new(null
|
||||
var/static/list/exclude = list("usr", "src", "marked", "global", "MC", "FS", "CFG")
|
||||
var/long = start < expression.len
|
||||
var/datum/D
|
||||
if(is_proper_datum(object))
|
||||
if(isdatum(object))
|
||||
D = object
|
||||
|
||||
if (object == world && (!long || expression[start + 1] == ".") && !(expression[start] in exclude) && copytext(expression[start], 1, 3) != "SS") //3 == length("SS") + 1
|
||||
@@ -1201,9 +1201,6 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/sdql2_vv_all, new(null
|
||||
query_list += word
|
||||
return query_list
|
||||
|
||||
/proc/is_proper_datum(thing)
|
||||
return istype(thing, /datum) || istype(thing, /client)
|
||||
|
||||
/obj/effect/statclick/SDQL2_delete/Click()
|
||||
if(!usr.client?.holder)
|
||||
message_admins("[key_name_admin(usr)] non-holder clicked on a statclick! ([src])")
|
||||
|
||||
@@ -48,9 +48,11 @@
|
||||
log_reftracker("Finished searching datums")
|
||||
|
||||
//Warning, attempting to search clients like this will cause crashes if done on live. Watch yourself
|
||||
#ifndef REFERENCE_DOING_IT_LIVE
|
||||
for(var/client/thing) //clients
|
||||
DoSearchVar(thing, "Clients -> [thing.type]", search_time = starting_time)
|
||||
log_reftracker("Finished searching clients")
|
||||
#endif
|
||||
|
||||
log_reftracker("Completed search for references to a [type].")
|
||||
|
||||
|
||||
@@ -55,11 +55,11 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
|
||||
///name of the UI that will try to open, right now using a generic ui
|
||||
var/ui_name = "AntagInfoGeneric"
|
||||
///button to access antag interface
|
||||
var/datum/action/antag_info/info_button
|
||||
///weakref to button to access antag interface
|
||||
var/datum/weakref/info_button_ref
|
||||
|
||||
/// The HUD shown to teammates, created by `add_team_hud`
|
||||
var/datum/atom_hud/alternate_appearance/team_hud
|
||||
/// A weakref to the HUD shown to teammates, created by `add_team_hud`
|
||||
var/datum/weakref/team_hud_ref
|
||||
|
||||
/datum/antagonist/New()
|
||||
GLOB.antagonists += src
|
||||
@@ -69,7 +69,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
GLOB.antagonists -= src
|
||||
if(owner)
|
||||
LAZYREMOVE(owner.antag_datums, src)
|
||||
QDEL_NULL(team_hud)
|
||||
QDEL_NULL(team_hud_ref)
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
@@ -94,6 +94,8 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
remove_innate_effects(old_body)
|
||||
if(!soft_antag && old_body && old_body.stat != DEAD && !LAZYLEN(old_body.mind?.antag_datums))
|
||||
old_body.remove_from_current_living_antags()
|
||||
var/datum/action/antag_info/info_button = info_button_ref?.resolve()
|
||||
if(info_button)
|
||||
info_button.Remove(old_body)
|
||||
info_button.Grant(new_body)
|
||||
apply_innate_effects(new_body)
|
||||
@@ -138,6 +140,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
///Called by the add_antag_datum() mind proc after the instanced datum is added to the mind's antag_datums list.
|
||||
/datum/antagonist/proc/on_gain()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
var/datum/action/antag_info/info_button
|
||||
if(!owner)
|
||||
CRASH("[src] ran on_gain() without a mind")
|
||||
if(!owner.current)
|
||||
@@ -145,6 +148,7 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
if(ui_name)//in the future, this should entirely replace greet.
|
||||
info_button = new(src)
|
||||
info_button.Grant(owner.current)
|
||||
info_button_ref = WEAKREF(info_button)
|
||||
if(!silent)
|
||||
greet()
|
||||
if(ui_name)
|
||||
@@ -201,8 +205,8 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
LAZYREMOVE(owner.antag_datums, src)
|
||||
if(!LAZYLEN(owner.antag_datums) && !soft_antag)
|
||||
owner.current.remove_from_current_living_antags()
|
||||
if(info_button)
|
||||
QDEL_NULL(info_button)
|
||||
if(info_button_ref)
|
||||
QDEL_NULL(info_button_ref)
|
||||
if(!silent && owner.current)
|
||||
farewell()
|
||||
UnregisterSignal(owner, COMSIG_PRE_MINDSHIELD_IMPLANT)
|
||||
@@ -408,14 +412,14 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
/// Adds a HUD that will show you other members with the same antagonist.
|
||||
/// If an antag typepath is passed to `antag_to_check`, will check that, otherwise will use the source type.
|
||||
/datum/antagonist/proc/add_team_hud(mob/target, antag_to_check)
|
||||
QDEL_NULL(team_hud)
|
||||
QDEL_NULL(team_hud_ref)
|
||||
|
||||
team_hud = target.add_alt_appearance(
|
||||
team_hud_ref = WEAKREF(target.add_alt_appearance(
|
||||
/datum/atom_hud/alternate_appearance/basic/has_antagonist,
|
||||
"antag_team_hud_[REF(src)]",
|
||||
image(hud_icon, target, antag_hud_name),
|
||||
antag_to_check || type,
|
||||
)
|
||||
))
|
||||
|
||||
// Add HUDs that they couldn't see before
|
||||
for (var/datum/atom_hud/alternate_appearance/basic/has_antagonist/antag_hud as anything in GLOB.has_antagonist_huds)
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
icon_state = "gizmo_scan"
|
||||
inhand_icon_state = "silencer"
|
||||
var/mode = GIZMO_SCAN
|
||||
var/mob/living/marked = null
|
||||
var/datum/weakref/marked_target
|
||||
var/obj/machinery/abductor/console/console
|
||||
|
||||
/obj/item/abductor/gizmo/attack_self(mob/user)
|
||||
@@ -221,6 +221,7 @@
|
||||
to_chat(user, span_notice("You scan [target] and add [target.p_them()] to the database."))
|
||||
|
||||
/obj/item/abductor/gizmo/proc/mark(atom/target, mob/living/user)
|
||||
var/mob/living/marked = marked_target?.resolve()
|
||||
if(marked == target)
|
||||
to_chat(user, span_warning("This specimen is already marked!"))
|
||||
return
|
||||
@@ -236,12 +237,13 @@
|
||||
return
|
||||
to_chat(user, span_notice("You begin preparing [target] for transport..."))
|
||||
if(do_after(user, 100, target = target))
|
||||
marked = target
|
||||
marked_target = WEAKREF(target)
|
||||
to_chat(user, span_notice("You finish preparing [target] for transport."))
|
||||
|
||||
/obj/item/abductor/gizmo/Destroy()
|
||||
if(console)
|
||||
console.gizmo = null
|
||||
console = null
|
||||
. = ..()
|
||||
|
||||
|
||||
|
||||
@@ -2,13 +2,10 @@
|
||||
name = "Human Observation Console"
|
||||
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
|
||||
var/datum/action/innate/teleport_self/tele_self_action = new
|
||||
var/datum/action/innate/vest_mode_swap/vest_mode_action = new
|
||||
var/datum/action/innate/vest_disguise_swap/vest_disguise_action = new
|
||||
var/datum/action/innate/set_droppoint/set_droppoint_action = new
|
||||
var/obj/machinery/abductor/console/console
|
||||
/// We can't create our actions until after LateInitialize
|
||||
/// So we instead do it on the first call to GrantActions
|
||||
var/abduct_created = FALSE
|
||||
lock_override = TRUE
|
||||
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
@@ -16,6 +13,12 @@
|
||||
icon_keyboard = null
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
|
||||
/obj/machinery/computer/camera_advanced/abductor/Destroy()
|
||||
if(console)
|
||||
console.camera = null
|
||||
console = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/abductor/CreateEye()
|
||||
..()
|
||||
eyeobj.visible_icon = TRUE
|
||||
@@ -24,38 +27,15 @@
|
||||
eyeobj.invisibility = INVISIBILITY_OBSERVER
|
||||
|
||||
/obj/machinery/computer/camera_advanced/abductor/GrantActions(mob/living/carbon/user)
|
||||
if(!abduct_created)
|
||||
actions += new /datum/action/innate/teleport_in(console.pad)
|
||||
actions += new /datum/action/innate/teleport_out(console)
|
||||
actions += new /datum/action/innate/teleport_self(console.pad)
|
||||
actions += new /datum/action/innate/vest_mode_swap(console)
|
||||
actions += new /datum/action/innate/vest_disguise_swap(console)
|
||||
actions += new /datum/action/innate/set_droppoint(console)
|
||||
..()
|
||||
|
||||
if(tele_in_action)
|
||||
tele_in_action.target = console.pad
|
||||
tele_in_action.Grant(user)
|
||||
actions += tele_in_action
|
||||
|
||||
if(tele_out_action)
|
||||
tele_out_action.target = console
|
||||
tele_out_action.Grant(user)
|
||||
actions += tele_out_action
|
||||
|
||||
if(tele_self_action)
|
||||
tele_self_action.target = console.pad
|
||||
tele_self_action.Grant(user)
|
||||
actions += tele_self_action
|
||||
|
||||
if(vest_mode_action)
|
||||
vest_mode_action.target = console
|
||||
vest_mode_action.Grant(user)
|
||||
actions += vest_mode_action
|
||||
|
||||
if(vest_disguise_action)
|
||||
vest_disguise_action.target = console
|
||||
vest_disguise_action.Grant(user)
|
||||
actions += vest_disguise_action
|
||||
|
||||
if(set_droppoint_action)
|
||||
set_droppoint_action.target = console
|
||||
set_droppoint_action.Grant(user)
|
||||
actions += set_droppoint_action
|
||||
|
||||
/obj/machinery/computer/camera_advanced/abductor/proc/IsScientist(mob/living/carbon/human/H)
|
||||
return HAS_TRAIT(H, TRAIT_ABDUCTOR_SCIENTIST_TRAINING)
|
||||
|
||||
|
||||
@@ -34,6 +34,21 @@
|
||||
. = ..()
|
||||
possible_gear = get_abductor_gear()
|
||||
|
||||
/obj/machinery/abductor/console/Destroy()
|
||||
if(gizmo)
|
||||
gizmo.console = null
|
||||
gizmo = null
|
||||
if(experiment)
|
||||
experiment.console = null
|
||||
experiment = null
|
||||
if(pad)
|
||||
pad.console = null
|
||||
pad = null
|
||||
if(camera)
|
||||
camera.console = null
|
||||
camera = null
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* get_abductor_gear: Returns a list of a filtered abductor gear sorted by categories
|
||||
*/
|
||||
@@ -95,7 +110,7 @@
|
||||
data["credits"] = experiment.credits
|
||||
data["pad"] = pad ? TRUE : FALSE
|
||||
if(pad)
|
||||
data["gizmo"] = gizmo && gizmo.marked ? TRUE : FALSE
|
||||
data["gizmo"] = gizmo && gizmo.marked_target?.resolve() ? TRUE : FALSE
|
||||
data["vest"] = vest ? TRUE : FALSE
|
||||
if(vest)
|
||||
data["vest_mode"] = vest.mode
|
||||
@@ -143,8 +158,9 @@
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/abductor/console/proc/TeleporterRetrieve()
|
||||
if(pad && gizmo?.marked)
|
||||
pad.Retrieve(gizmo.marked)
|
||||
var/mob/living/marked = gizmo.marked_target?.resolve()
|
||||
if(pad && marked)
|
||||
pad.Retrieve(marked)
|
||||
|
||||
/obj/machinery/abductor/console/proc/TeleporterSend()
|
||||
if(pad)
|
||||
@@ -192,6 +208,7 @@
|
||||
for(var/obj/machinery/abductor/pad/p in GLOB.machines)
|
||||
if(p.team_number == team_number)
|
||||
pad = p
|
||||
pad.console = src
|
||||
break
|
||||
|
||||
for(var/obj/machinery/abductor/experiment/e in GLOB.machines)
|
||||
|
||||
@@ -15,6 +15,12 @@
|
||||
var/message_cooldown = 0
|
||||
var/breakout_time = 450
|
||||
|
||||
/obj/machinery/abductor/experiment/Destroy()
|
||||
if(console)
|
||||
console.experiment = null
|
||||
console = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/abductor/experiment/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat != CONSCIOUS || HAS_TRAIT(user, TRAIT_UI_BLOCKED) || !Adjacent(user) || !target.Adjacent(user) || !ishuman(target))
|
||||
return
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "alien-pad-idle"
|
||||
var/turf/teleport_target
|
||||
var/obj/machinery/abductor/console/console
|
||||
|
||||
/obj/machinery/abductor/pad/Destroy()
|
||||
if(console)
|
||||
console.pad = null
|
||||
console = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/abductor/pad/proc/Warp(mob/living/target)
|
||||
if(!target.buckled)
|
||||
|
||||
@@ -263,7 +263,7 @@
|
||||
for(var/obj/I in all_items) //Check for wanted items
|
||||
if(istype(I, /obj/item/photo))
|
||||
var/obj/item/photo/P = I
|
||||
if(P.picture && (target.current in P.picture.mobs_seen) && !(target.current in P.picture.dead_seen)) //Does the picture exist and is the target in it and is the target not dead
|
||||
if(P.picture && (WEAKREF(target.current) in P.picture.mobs_seen) && !(WEAKREF(target.current) in P.picture.dead_seen)) //Does the picture exist and is the target in it and is the target not dead
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
return
|
||||
|
||||
if(ishuman(A))
|
||||
if(A in drained_mobs)
|
||||
//Humans are tagged, so this is fine
|
||||
if(REF(A) in drained_mobs)
|
||||
to_chat(src, span_revenwarning("[A]'s soul is dead and empty.") )
|
||||
else if(in_range(src, A))
|
||||
Harvest(A)
|
||||
@@ -97,7 +98,7 @@
|
||||
to_chat(src, span_revennotice("[target]'s soul has been considerably weakened and will yield no more essence for the time being."))
|
||||
target.visible_message(span_warning("[target] slumps onto the ground."), \
|
||||
span_revenwarning("Violets lights, dancing in your vision, getting clo--"))
|
||||
drained_mobs.Add(target)
|
||||
drained_mobs += REF(target)
|
||||
target.death(0)
|
||||
else
|
||||
to_chat(src, span_revenwarning("[target ? "[target] has":"[target.p_theyve(TRUE)]"] been drawn out of your grasp. The link has been broken."))
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
var/list/traitor_flavor
|
||||
|
||||
///reference to the uplink this traitor was given, if they were.
|
||||
var/datum/component/uplink/uplink
|
||||
var/datum/weakref/uplink_ref
|
||||
|
||||
/// The uplink handler that this traitor belongs to.
|
||||
var/datum/uplink_handler/uplink_handler
|
||||
@@ -40,7 +40,8 @@
|
||||
if(give_uplink)
|
||||
owner.give_uplink(silent = TRUE, antag_datum = src)
|
||||
|
||||
uplink = owner.find_syndicate_uplink()
|
||||
var/datum/component/uplink/uplink = owner.find_syndicate_uplink()
|
||||
uplink_ref = WEAKREF(uplink)
|
||||
if(uplink)
|
||||
if(uplink_handler)
|
||||
uplink.uplink_handler = uplink_handler
|
||||
@@ -63,8 +64,6 @@
|
||||
uplink_items += item
|
||||
uplink_handler.extra_purchasable += create_uplink_sales(uplink_sale_count, /datum/uplink_category/discounts, -1, uplink_items)
|
||||
|
||||
RegisterSignal(uplink, COMSIG_PARENT_QDELETING, .proc/on_uplink_lost)
|
||||
|
||||
if(give_objectives)
|
||||
forge_traitor_objectives()
|
||||
|
||||
@@ -78,10 +77,6 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/traitor/proc/on_uplink_lost(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
uplink = null
|
||||
|
||||
/datum/antagonist/traitor/on_removal()
|
||||
owner.special_role = null
|
||||
return ..()
|
||||
@@ -181,6 +176,7 @@
|
||||
component.delete_if_from_source(src)
|
||||
|
||||
/datum/antagonist/traitor/ui_static_data(mob/user)
|
||||
var/datum/component/uplink/uplink = uplink_ref?.resolve()
|
||||
var/list/data = list()
|
||||
data["has_codewords"] = should_give_codewords
|
||||
if(should_give_codewords)
|
||||
|
||||
@@ -13,6 +13,11 @@
|
||||
var/obj/item/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device
|
||||
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
|
||||
|
||||
/obj/item/onetankbomb/Destroy()
|
||||
bombassembly = null
|
||||
bombtank = null
|
||||
return ..()
|
||||
|
||||
/obj/item/onetankbomb/IsSpecialAssembly()
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -19,6 +19,18 @@
|
||||
var/static/rotation_flags = ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_FLIP | ROTATION_VERBS
|
||||
AddComponent(/datum/component/simple_rotation, rotation_flags)
|
||||
|
||||
/obj/item/assembly_holder/Destroy()
|
||||
QDEL_NULL(a_left)
|
||||
QDEL_NULL(a_right)
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly_holder/Exited(atom/movable/gone, direction)
|
||||
. = ..()
|
||||
if(gone == a_left)
|
||||
a_left = null
|
||||
else if(gone == a_right)
|
||||
a_right = null
|
||||
|
||||
/obj/item/assembly_holder/IsAssemblyHolder()
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -89,6 +89,11 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/bluespace_vendor, 30)
|
||||
icon_state = "[base_icon]_open"
|
||||
return ..()
|
||||
|
||||
/obj/machinery/bluespace_vendor/Exited(atom/movable/gone, direction)
|
||||
if(gone == internal_tank)
|
||||
internal_tank = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/bluespace_vendor/process()
|
||||
if(mode == BS_MODE_OPEN)
|
||||
return
|
||||
|
||||
@@ -496,7 +496,7 @@ GLOBAL_LIST_INIT(gas_id_to_canister, init_gas_id_to_canister())
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/take_damage(damage_amount, damage_type = BRUTE, damage_flag = "", sound_effect = TRUE, attack_dir, armour_penetration = 0)
|
||||
. = ..()
|
||||
if(!.)
|
||||
if(!. || QDELETED(src))
|
||||
return
|
||||
SSair.start_processing_machine(src)
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
var/order_id = 0
|
||||
var/errors = 0
|
||||
|
||||
/obj/item/paper/fluff/jobs/cargo/manifest/New(atom/A, id, cost)
|
||||
..()
|
||||
/obj/item/paper/fluff/jobs/cargo/manifest/Initialize(mapload, id, cost)
|
||||
. = ..()
|
||||
order_id = id
|
||||
order_cost = cost
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
return P
|
||||
|
||||
/datum/supply_order/proc/generateManifest(obj/container, owner, packname, cost) //generates-the-manifests.
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/P = new(container, id, cost)
|
||||
var/obj/item/paper/fluff/jobs/cargo/manifest/P = new(null, id, cost)
|
||||
|
||||
var/station_name = (P.errors & MANIFEST_ERROR_NAME) ? new_station_name() : station_name()
|
||||
|
||||
|
||||
@@ -509,6 +509,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
var/announce_join = mob.client?.prefs?.read_preference(/datum/preference/toggle/broadcast_login_logout)
|
||||
if (!stealth_admin)
|
||||
deadchat_broadcast(" has disconnected.", "<b>[mob][mob.get_realname_string()]</b>", follow_target = mob, turf_target = get_turf(mob), message_type = DEADCHAT_LOGIN_LOGOUT, admin_only=!announce_join)
|
||||
mob.become_uncliented()
|
||||
|
||||
GLOB.clients -= src
|
||||
GLOB.directory -= ckey
|
||||
@@ -542,10 +543,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
send2adminchat("Server", "[cheesy_message] (No admins online)")
|
||||
QDEL_LIST_ASSOC_VAL(char_render_holders)
|
||||
|
||||
if(movingmob != null)
|
||||
LAZYREMOVE(movingmob.client_mobs_in_contents, mob)
|
||||
movingmob = null
|
||||
|
||||
active_mousedown_item = null
|
||||
SSambience.remove_ambience_client(src)
|
||||
SSmouse_entered.hovers -= src
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
|
||||
/obj/item/clothing/suit/hooded/Destroy()
|
||||
. = ..()
|
||||
qdel(hood)
|
||||
hood = null
|
||||
QDEL_NULL(hood)
|
||||
|
||||
/obj/item/clothing/suit/hooded/proc/MakeHood()
|
||||
if(!hood)
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
/obj/machinery/computer/piratepad_control
|
||||
name = "cargo hold control terminal"
|
||||
var/status_report = "Ready for delivery."
|
||||
var/obj/machinery/piratepad/pad
|
||||
var/datum/weakref/pad_ref
|
||||
var/warmup_time = 100
|
||||
var/sending = FALSE
|
||||
var/points = 0
|
||||
@@ -328,7 +328,7 @@
|
||||
. = ..()
|
||||
if (istype(I) && istype(I.buffer,/obj/machinery/piratepad))
|
||||
to_chat(user, span_notice("You link [src] with [I.buffer] in [I] buffer."))
|
||||
pad = I.buffer
|
||||
pad_ref = WEAKREF(I.buffer)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/piratepad_control/LateInitialize()
|
||||
@@ -336,10 +336,11 @@
|
||||
if(cargo_hold_id)
|
||||
for(var/obj/machinery/piratepad/P in GLOB.machines)
|
||||
if(P.cargo_hold_id == cargo_hold_id)
|
||||
pad = P
|
||||
pad_ref = WEAKREF(P)
|
||||
return
|
||||
else
|
||||
pad = locate() in range(4,src)
|
||||
var/obj/machinery/piratepad/pad = locate() in range(4, src)
|
||||
pad_ref = WEAKREF(pad)
|
||||
|
||||
/obj/machinery/computer/piratepad_control/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
@@ -350,7 +351,7 @@
|
||||
/obj/machinery/computer/piratepad_control/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["points"] = points
|
||||
data["pad"] = pad ? TRUE : FALSE
|
||||
data["pad"] = pad_ref?.resolve() ? TRUE : FALSE
|
||||
data["sending"] = sending
|
||||
data["status_report"] = status_report
|
||||
return data
|
||||
@@ -359,7 +360,7 @@
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(!pad)
|
||||
if(!pad_ref?.resolve())
|
||||
return
|
||||
|
||||
switch(action)
|
||||
@@ -380,6 +381,7 @@
|
||||
status_report = "Predicted value: "
|
||||
var/value = 0
|
||||
var/datum/export_report/ex = new
|
||||
var/obj/machinery/piratepad/pad = pad_ref?.resolve()
|
||||
for(var/atom/movable/AM in get_turf(pad))
|
||||
if(AM == pad)
|
||||
continue
|
||||
@@ -402,6 +404,7 @@
|
||||
return
|
||||
|
||||
var/datum/export_report/ex = new
|
||||
var/obj/machinery/piratepad/pad = pad_ref?.resolve()
|
||||
|
||||
for(var/atom/movable/AM in get_turf(pad))
|
||||
if(AM == pad)
|
||||
@@ -447,6 +450,7 @@
|
||||
return
|
||||
sending = TRUE
|
||||
status_report = "Sending... "
|
||||
var/obj/machinery/piratepad/pad = pad_ref?.resolve()
|
||||
pad.visible_message(span_notice("[pad] starts charging up."))
|
||||
pad.icon_state = pad.warmup_state
|
||||
sending_timer = addtimer(CALLBACK(src,.proc/send),warmup_time, TIMER_STOPPABLE)
|
||||
@@ -458,6 +462,7 @@
|
||||
status_report = "Ready for delivery."
|
||||
if(custom_report)
|
||||
status_report = custom_report
|
||||
var/obj/machinery/piratepad/pad = pad_ref?.resolve()
|
||||
pad.icon_state = pad.idle_state
|
||||
deltimer(sending_timer)
|
||||
|
||||
|
||||
@@ -422,8 +422,12 @@
|
||||
eat(user)
|
||||
|
||||
/datum/spacevine_controller
|
||||
///Canonical list of all the vines we "own"
|
||||
var/list/obj/structure/spacevine/vines
|
||||
///Queue of vines to process
|
||||
var/list/growth_queue
|
||||
//List of currently processed vines, on this level to prevent runtime tomfoolery
|
||||
var/list/obj/structure/spacevine/queue_end
|
||||
var/spread_multiplier = 5
|
||||
var/spread_cap = 30
|
||||
var/list/vine_mutations_list
|
||||
@@ -432,9 +436,16 @@
|
||||
/datum/spacevine_controller/New(turf/location, list/muts, potency, production, datum/round_event/event = null)
|
||||
vines = list()
|
||||
growth_queue = list()
|
||||
<<<<<<< HEAD
|
||||
var/obj/structure/spacevine/SV = spawn_spacevine_piece(location, null, muts)
|
||||
if (event)
|
||||
event.announce_to_ghosts(SV)
|
||||
=======
|
||||
queue_end = list()
|
||||
var/obj/structure/spacevine/vine = spawn_spacevine_piece(location, null, muts)
|
||||
if(event)
|
||||
event.announce_to_ghosts(vine)
|
||||
>>>>>>> f8aad14ae87 (Harddel Fix Pack #42 + Better Live Reftracking Support (#63877))
|
||||
START_PROCESSING(SSobj, src)
|
||||
vine_mutations_list = list()
|
||||
init_subtypes(/datum/spacevine_mutation/, vine_mutations_list)
|
||||
@@ -459,9 +470,13 @@
|
||||
|
||||
/datum/spacevine_controller/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
vines.Cut()
|
||||
growth_queue.Cut()
|
||||
queue_end.Cut()
|
||||
return ..()
|
||||
|
||||
/datum/spacevine_controller/proc/spawn_spacevine_piece(turf/location, obj/structure/spacevine/parent, list/muts)
|
||||
<<<<<<< HEAD
|
||||
var/obj/structure/spacevine/SV = new(location)
|
||||
growth_queue += SV
|
||||
vines += SV
|
||||
@@ -469,6 +484,14 @@
|
||||
if(muts && muts.len)
|
||||
for(var/datum/spacevine_mutation/M in muts)
|
||||
M.add_mutation_to_vinepiece(SV)
|
||||
=======
|
||||
var/obj/structure/spacevine/vine = new(location)
|
||||
growth_queue += vine
|
||||
vines += vine
|
||||
vine.master = src
|
||||
for(var/datum/spacevine_mutation/mutation in muts)
|
||||
mutation.add_mutation_to_vinepiece(vine)
|
||||
>>>>>>> f8aad14ae87 (Harddel Fix Pack #42 + Better Live Reftracking Support (#63877))
|
||||
if(parent)
|
||||
SV.mutations |= parent.mutations
|
||||
var/parentcolor = parent.atom_colours[FIXED_COLOUR_PRIORITY]
|
||||
@@ -482,6 +505,7 @@
|
||||
location.Entered(SV, null)
|
||||
return SV
|
||||
|
||||
<<<<<<< HEAD
|
||||
/datum/spacevine_controller/proc/VineDestroyed(obj/structure/spacevine/S)
|
||||
S.master = null
|
||||
vines -= S
|
||||
@@ -492,15 +516,28 @@
|
||||
KZ.set_potency(mutativeness * 10)
|
||||
KZ.set_production(11 - (spread_cap / initial(spread_cap)) * 5) //Reverts spread_cap formula so resulting seed gets original production stat or equivalent back.
|
||||
qdel(src)
|
||||
=======
|
||||
/datum/spacevine_controller/proc/VineDestroyed(obj/structure/spacevine/vine)
|
||||
vine.master = null
|
||||
vines -= vine
|
||||
growth_queue -= vine
|
||||
queue_end -= vine
|
||||
if(length(vines))
|
||||
return
|
||||
var/obj/item/seeds/kudzu/seed = new(vine.loc)
|
||||
seed.mutations |= vine.mutations
|
||||
seed.set_potency(mutativeness * 10)
|
||||
seed.set_production(11 - (spread_cap / initial(spread_cap)) * 5) //Reverts spread_cap formula so resulting seed gets original production stat or equivalent back.
|
||||
qdel(src)
|
||||
>>>>>>> f8aad14ae87 (Harddel Fix Pack #42 + Better Live Reftracking Support (#63877))
|
||||
|
||||
/datum/spacevine_controller/process(delta_time)
|
||||
if(!LAZYLEN(vines))
|
||||
var/vine_count = length(vines)
|
||||
if(!vine_count)
|
||||
qdel(src) //space vines exterminated. Remove the controller
|
||||
return
|
||||
if(!growth_queue)
|
||||
qdel(src) //Sanity check
|
||||
return
|
||||
|
||||
<<<<<<< HEAD
|
||||
var/length = round(clamp(delta_time * 0.5 * vines.len / spread_multiplier, 1, spread_cap))
|
||||
var/i = 0
|
||||
var/list/obj/structure/spacevine/queue_end = list()
|
||||
@@ -521,9 +558,30 @@
|
||||
|
||||
SV.spread()
|
||||
if(i >= length)
|
||||
=======
|
||||
var/spread_max = round(clamp(delta_time * 0.5 * vine_count / spread_multiplier, 1, spread_cap))
|
||||
var/amount_processed = 0
|
||||
for(var/obj/structure/spacevine/vine as anything in growth_queue)
|
||||
growth_queue -= vine
|
||||
queue_end += vine
|
||||
for(var/datum/spacevine_mutation/mutation in vine.mutations)
|
||||
mutation.process_mutation(vine)
|
||||
|
||||
if(vine.energy >= 2) //If tile is fully grown
|
||||
vine.entangle_mob()
|
||||
else if(DT_PROB(10, delta_time)) //If tile isn't fully grown
|
||||
vine.grow()
|
||||
|
||||
vine.spread()
|
||||
|
||||
amount_processed++
|
||||
if(amount_processed >= spread_max)
|
||||
>>>>>>> f8aad14ae87 (Harddel Fix Pack #42 + Better Live Reftracking Support (#63877))
|
||||
break
|
||||
|
||||
growth_queue = growth_queue + queue_end
|
||||
//We can only do so much work per process, but we still want to process everything at some point
|
||||
//So we shift the queue a bit
|
||||
growth_queue += queue_end
|
||||
|
||||
/obj/structure/spacevine/proc/grow()
|
||||
if(!energy)
|
||||
|
||||
@@ -40,9 +40,17 @@
|
||||
seed_modifier = round(seed.potency / 25)
|
||||
var/obj/item/stack/cotton = new cotton_type(user.loc, 1 + seed_modifier)
|
||||
var/old_cotton_amount = cotton.amount
|
||||
for(var/obj/item/stack/ST in user.loc)
|
||||
if(ST != cotton && istype(ST, cotton_type) && ST.amount < ST.max_amount)
|
||||
ST.attackby(cotton, user)
|
||||
for(var/obj/item/stack/potential_stack in user.loc)
|
||||
if(QDELETED(potential_stack))
|
||||
continue
|
||||
if(potential_stack == cotton)
|
||||
continue
|
||||
if(!istype(potential_stack, cotton_type))
|
||||
continue
|
||||
if(potential_stack.amount >= potential_stack.max_amount)
|
||||
continue
|
||||
potential_stack.attackby(cotton, user)
|
||||
|
||||
if(cotton.amount > old_cotton_amount)
|
||||
to_chat(user, span_notice("You add the newly-formed [cotton_name] to the stack. It now contains [cotton.amount] [cotton_name]."))
|
||||
qdel(src)
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
mutated_seed = new mutated_seed
|
||||
for(var/datum/plant_gene/trait/trait in parent.myseed.genes)
|
||||
if((trait.mutability_flags & PLANT_GENE_MUTATABLE) && trait.can_add(mutated_seed))
|
||||
mutated_seed.genes += trait
|
||||
mutated_seed.genes += trait.Copy()
|
||||
t_prod = new t_prod(output_loc, mutated_seed)
|
||||
t_prod.transform = initial(t_prod.transform)
|
||||
t_prod.transform *= TRANSFORM_USING_VARIABLE(t_prod.seed.potency, 100) + 0.5
|
||||
|
||||
@@ -43,11 +43,10 @@
|
||||
charges--
|
||||
if(!charges)
|
||||
var/turf/T = get_turf(src)
|
||||
T.visible_message(span_warning("The cover and contents of [src] start shifting and changing!"))
|
||||
T.visible_message(span_warning("The cover and contents of [src] start shifting and changing! It slips out of your hands!"))
|
||||
|
||||
new /obj/item/book/manual/random(T)
|
||||
qdel(src)
|
||||
var/obj/item/book/manual/random/book = new(T)
|
||||
user.put_in_active_hand(book)
|
||||
|
||||
/obj/item/language_manual/codespeak_manual
|
||||
name = "codespeak manual"
|
||||
|
||||
@@ -874,10 +874,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
observetarget = null
|
||||
client?.perspective = initial(client.perspective)
|
||||
sight = initial(sight)
|
||||
if(target)
|
||||
UnregisterSignal(target, COMSIG_MOVABLE_Z_CHANGED)
|
||||
if(target.observers)
|
||||
target.observers -= src
|
||||
UNSETEMPTY(target.observers)
|
||||
LAZYREMOVE(target.observers, src)
|
||||
|
||||
/mob/dead/observer/verb/observe()
|
||||
set name = "Observe"
|
||||
@@ -920,8 +919,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
RegisterSignal(mob_eye, COMSIG_MOVABLE_Z_CHANGED, .proc/on_observing_z_changed)
|
||||
if(mob_eye.hud_used)
|
||||
client.screen = list()
|
||||
LAZYINITLIST(mob_eye.observers)
|
||||
mob_eye.observers |= src
|
||||
LAZYOR(mob_eye.observers, src)
|
||||
mob_eye.hud_used.show_hud(mob_eye.hud_used.hud_version, src)
|
||||
observetarget = mob_eye
|
||||
|
||||
|
||||
@@ -434,7 +434,7 @@
|
||||
dna.temporary_mutations.Remove(mut)
|
||||
continue
|
||||
for(var/datum/mutation/human/HM in dna.mutations)
|
||||
if(HM?.timed)
|
||||
if(HM?.timeout)
|
||||
dna.remove_mutation(HM.type)
|
||||
|
||||
/*
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
remove_from_all_data_huds()
|
||||
GLOB.mob_living_list -= src
|
||||
QDEL_LAZYLIST(diseases)
|
||||
QDEL_LIST(surgeries)
|
||||
return ..()
|
||||
|
||||
/mob/living/onZImpact(turf/T, levels, message = TRUE)
|
||||
|
||||
@@ -44,7 +44,8 @@
|
||||
radiomod = ";" //AIs will, by default, state their laws on the internal radio.
|
||||
///Used as a fake multitoool in tcomms machinery
|
||||
var/obj/item/multitool/aiMulti
|
||||
var/mob/living/simple_animal/bot/Bot
|
||||
///Weakref to the bot the ai's commanding right now
|
||||
var/datum/weakref/bot_ref
|
||||
var/tracking = FALSE //this is 1 if the AI is currently tracking somebody, but the track has not yet been completed.
|
||||
var/datum/effect_system/spark_spread/spark_system //So they can initialize sparks whenever
|
||||
|
||||
@@ -222,7 +223,7 @@
|
||||
QDEL_NULL(alert_control)
|
||||
malfhack = null
|
||||
current = null
|
||||
Bot = null
|
||||
bot_ref = null
|
||||
controlled_equipment = null
|
||||
linked_core = null
|
||||
apc_override = null
|
||||
@@ -503,16 +504,16 @@
|
||||
to_chat(src, span_danger("Selected location is not visible."))
|
||||
|
||||
/mob/living/silicon/ai/proc/call_bot(turf/waypoint)
|
||||
|
||||
if(!Bot)
|
||||
var/mob/living/simple_animal/bot/bot = bot_ref?.resolve()
|
||||
if(!bot)
|
||||
return
|
||||
|
||||
if(Bot.calling_ai && Bot.calling_ai != src) //Prevents an override if another AI is controlling this bot.
|
||||
if(bot.calling_ai && bot.calling_ai != src) //Prevents an override if another AI is controlling this bot.
|
||||
to_chat(src, span_danger("Interface error. Unit is already in use."))
|
||||
return
|
||||
to_chat(src, span_notice("Sending command to bot..."))
|
||||
call_bot_cooldown = world.time + CALL_BOT_COOLDOWN
|
||||
Bot.call_bot(src, waypoint)
|
||||
bot.call_bot(src, waypoint)
|
||||
call_bot_cooldown = 0
|
||||
|
||||
/mob/living/silicon/ai/proc/alarm_triggered(datum/source, alarm_type, area/source_area)
|
||||
|
||||
@@ -58,20 +58,23 @@
|
||||
if(!is_interactable(usr))
|
||||
return
|
||||
|
||||
var/mob/living/simple_animal/bot/bot
|
||||
switch(action)
|
||||
if("callbot") //Command a bot to move to a selected location.
|
||||
if(owner.call_bot_cooldown > world.time)
|
||||
to_chat(usr, span_danger("Error: Your last call bot command is still processing, please wait for the bot to finish calculating a route."))
|
||||
return
|
||||
owner.Bot = locate(params["ref"]) in GLOB.bots_list
|
||||
if(!owner.Bot || !(owner.Bot.bot_mode_flags & BOT_MODE_REMOTE_ENABLED) || owner.control_disabled)
|
||||
bot = locate(params["ref"]) in GLOB.bots_list
|
||||
owner.bot_ref = WEAKREF(bot)
|
||||
if(!bot || !(bot.bot_mode_flags & BOT_MODE_REMOTE_ENABLED) || owner.control_disabled)
|
||||
return
|
||||
owner.waypoint_mode = TRUE
|
||||
to_chat(usr, span_notice("Set your waypoint by clicking on a valid location free of obstructions."))
|
||||
. = TRUE
|
||||
if("interface") //Remotely connect to a bot!
|
||||
owner.Bot = locate(params["ref"]) in GLOB.bots_list
|
||||
if(!owner.Bot || !(owner.Bot.bot_mode_flags & BOT_MODE_REMOTE_ENABLED) || owner.control_disabled)
|
||||
bot = locate(params["ref"]) in GLOB.bots_list
|
||||
owner.bot_ref = WEAKREF(bot)
|
||||
if(!bot || !(bot.bot_mode_flags & BOT_MODE_REMOTE_ENABLED) || owner.control_disabled)
|
||||
return
|
||||
owner.Bot.attack_ai(usr)
|
||||
bot.attack_ai(usr)
|
||||
. = TRUE
|
||||
|
||||
@@ -148,6 +148,7 @@
|
||||
QDEL_NULL(inv1)
|
||||
QDEL_NULL(inv2)
|
||||
QDEL_NULL(inv3)
|
||||
QDEL_NULL(hands)
|
||||
QDEL_NULL(spark_system)
|
||||
QDEL_NULL(alert_control)
|
||||
cell = null
|
||||
|
||||
@@ -43,7 +43,10 @@
|
||||
/mob/living/simple_animal/robot_customer/Destroy()
|
||||
var/datum/venue/attending_venue = ai_controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE]
|
||||
attending_venue.current_visitors -= src
|
||||
attending_venue.linked_seats[ai_controller.blackboard[BB_CUSTOMER_MY_SEAT]] = null
|
||||
var/datum/weakref/seat_ref = ai_controller.blackboard[BB_CUSTOMER_MY_SEAT]
|
||||
var/obj/structure/holosign/robot_seat/our_seat = seat_ref?.resolve()
|
||||
if(attending_venue.linked_seats[our_seat])
|
||||
attending_venue.linked_seats[our_seat] = null
|
||||
QDEL_NULL(hud_to_show_on_hover)
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
|
||||
footstep_type = FOOTSTEP_MOB_SHOE
|
||||
|
||||
/mob/living/simple_animal/hostile/boss/paper_wizard/Destroy()
|
||||
QDEL_LIST(copies)
|
||||
return ..()
|
||||
|
||||
//Summon Ability
|
||||
//Lets the wizard summon his art to fight for him
|
||||
@@ -126,13 +129,18 @@
|
||||
loot = list()
|
||||
var/mob/living/simple_animal/hostile/boss/paper_wizard/original
|
||||
|
||||
/mob/living/simple_animal/hostile/boss/paper_wizard/copy/Destroy()
|
||||
if(original)
|
||||
original.copies -= src
|
||||
original = null
|
||||
return ..()
|
||||
|
||||
//Hit a fake? eat pain!
|
||||
/mob/living/simple_animal/hostile/boss/paper_wizard/copy/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
if(amount > 0) //damage
|
||||
if(original)
|
||||
original.minimum_distance = 3
|
||||
original.retreat_distance = 3
|
||||
original.copies -= src
|
||||
for(var/c in original.copies)
|
||||
qdel(c)
|
||||
for(var/mob/living/L in range(5,src))
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
/mob/Login()
|
||||
if(!client)
|
||||
return FALSE
|
||||
canon_client = client
|
||||
add_to_player_list()
|
||||
lastKnownIP = client.address
|
||||
computer_id = client.computer_id
|
||||
@@ -62,8 +63,6 @@
|
||||
if(!client)
|
||||
return FALSE
|
||||
|
||||
//We do this here to prevent hanging refs from ghostize or whatever, since if we were in another mob before this'll take care of it
|
||||
clear_important_client_contents(client)
|
||||
enable_client_mobs_in_contents(client)
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_MOB_LOGIN)
|
||||
|
||||
@@ -4,17 +4,11 @@
|
||||
SStgui.on_logout(src)
|
||||
unset_machine()
|
||||
remove_from_player_list()
|
||||
clear_client_in_contents()
|
||||
..()
|
||||
|
||||
if(loc)
|
||||
loc.on_log(FALSE)
|
||||
|
||||
if(client)
|
||||
for(var/foo in client.player_details.post_logout_callbacks)
|
||||
var/datum/callback/CB = foo
|
||||
CB.Invoke()
|
||||
|
||||
clear_important_client_contents(client)
|
||||
become_uncliented()
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -1054,6 +1054,9 @@
|
||||
if(oldname == newname)
|
||||
log_message("[src] failed name change as the new name was the same as the old one: [oldname]", LOG_OWNERSHIP)
|
||||
return FALSE
|
||||
if(!istext(newname) && !isnull(newname))
|
||||
stack_trace("[src] attempted to change its name from [oldname] to the non string value [newname]")
|
||||
return FALSE
|
||||
|
||||
log_message("[src] name changed from [oldname] to [newname]", LOG_OWNERSHIP)
|
||||
|
||||
@@ -1339,11 +1342,22 @@
|
||||
SIGNAL_HANDLER
|
||||
set_active_storage(null)
|
||||
|
||||
///clears the client mob in our client_mobs_in_contents list
|
||||
/mob/proc/clear_client_in_contents()
|
||||
if(client?.movingmob)
|
||||
LAZYREMOVE(client.movingmob.client_mobs_in_contents, src)
|
||||
client.movingmob = null
|
||||
/// Cleanup proc that's called when a mob loses a client, either through client destroy or logout
|
||||
/// Logout happens post client del, so we can't just copypaste this there. This keeps things clean and consistent
|
||||
/mob/proc/become_uncliented()
|
||||
if(!canon_client)
|
||||
return
|
||||
|
||||
for(var/foo in canon_client.player_details.post_logout_callbacks)
|
||||
var/datum/callback/CB = foo
|
||||
CB.Invoke()
|
||||
|
||||
if(canon_client?.movingmob)
|
||||
LAZYREMOVE(canon_client.movingmob.client_mobs_in_contents, src)
|
||||
canon_client.movingmob = null
|
||||
|
||||
clear_important_client_contents()
|
||||
canon_client = null
|
||||
|
||||
///Shows a tgui window with memories
|
||||
/mob/verb/memory()
|
||||
|
||||
@@ -17,6 +17,13 @@
|
||||
throwforce = 10
|
||||
blocks_emissive = EMISSIVE_BLOCK_GENERIC
|
||||
pass_flags_self = PASSMOB
|
||||
/// The current client inhabiting this mob. Managed by login/logout
|
||||
/// This exists so we can do cleanup in logout for occasions where a client was transfere rather then destroyed
|
||||
/// We need to do this because the mob on logout never actually has a reference to client
|
||||
/// We also need to clear this var/do other cleanup in client/Destroy, since that happens before logout
|
||||
/// HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
|
||||
var/client/canon_client
|
||||
|
||||
var/shift_to_open_context_menu = TRUE
|
||||
|
||||
///when this be added to vis_contents of something it inherit something.plane, important for visualisation of mob in openspace.
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
|
||||
/obj/item/modular_computer/Destroy()
|
||||
wipe_program(forced = TRUE)
|
||||
for(var/datum/computer_file/program/idle as anything in idle_threads)
|
||||
idle.kill_program(TRUE)
|
||||
idle_threads.Cut()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
for(var/port in all_components)
|
||||
var/obj/item/computer_hardware/component = all_components[port]
|
||||
|
||||
@@ -15,25 +15,19 @@
|
||||
tgui_id = "NtosConfiguration"
|
||||
program_icon = "cog"
|
||||
|
||||
var/obj/item/modular_computer/movable = null
|
||||
|
||||
|
||||
/datum/computer_file/program/computerconfig/ui_data(mob/user)
|
||||
movable = computer
|
||||
var/obj/item/computer_hardware/hard_drive/hard_drive = movable.all_components[MC_HDD]
|
||||
var/obj/item/computer_hardware/battery/battery_module = movable.all_components[MC_CELL]
|
||||
if(!istype(movable))
|
||||
movable = null
|
||||
|
||||
// No computer connection, we can't get data from that.
|
||||
if(!movable)
|
||||
if(!computer)
|
||||
return 0
|
||||
|
||||
var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
|
||||
var/obj/item/computer_hardware/battery/battery_module = computer.all_components[MC_CELL]
|
||||
|
||||
var/list/data = get_header_data()
|
||||
|
||||
data["disk_size"] = hard_drive.max_capacity
|
||||
data["disk_used"] = hard_drive.used_capacity
|
||||
data["power_usage"] = movable.last_power_usage
|
||||
data["power_usage"] = computer.last_power_usage
|
||||
data["battery_exists"] = battery_module ? 1 : 0
|
||||
if(battery_module?.battery)
|
||||
data["battery_rating"] = battery_module.battery.maxcharge
|
||||
@@ -43,8 +37,8 @@
|
||||
data["battery"] = list("max" = battery_module.battery.maxcharge, "charge" = round(battery_module.battery.charge))
|
||||
|
||||
var/list/all_entries[0]
|
||||
for(var/I in movable.all_components)
|
||||
var/obj/item/computer_hardware/H = movable.all_components[I]
|
||||
for(var/I in computer.all_components)
|
||||
var/obj/item/computer_hardware/H = computer.all_components[I]
|
||||
all_entries.Add(list(list(
|
||||
"name" = H.name,
|
||||
"desc" = H.desc,
|
||||
@@ -63,7 +57,7 @@
|
||||
return
|
||||
switch(action)
|
||||
if("PC_toggle_component")
|
||||
var/obj/item/computer_hardware/H = movable.find_hardware_by_name(params["name"])
|
||||
var/obj/item/computer_hardware/H = computer.find_hardware_by_name(params["name"])
|
||||
if(H && istype(H))
|
||||
H.enabled = !H.enabled
|
||||
. = TRUE
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
var/download_completion = FALSE //GQ of downloaded data.
|
||||
var/download_netspeed = 0
|
||||
var/downloaderror = ""
|
||||
var/obj/item/modular_computer/my_computer = null
|
||||
var/emagged = FALSE
|
||||
var/list/main_repo
|
||||
var/list/antag_repo
|
||||
@@ -130,9 +129,7 @@
|
||||
return FALSE
|
||||
|
||||
/datum/computer_file/program/ntnetdownload/ui_data(mob/user)
|
||||
my_computer = computer
|
||||
|
||||
if(!istype(my_computer))
|
||||
if(!istype(computer))
|
||||
return
|
||||
var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD]
|
||||
var/list/access = card_slot?.GetAccess()
|
||||
@@ -150,7 +147,7 @@
|
||||
data["downloadspeed"] = download_netspeed
|
||||
data["downloadcompletion"] = round(download_completion, 0.1)
|
||||
|
||||
var/obj/item/computer_hardware/hard_drive/hard_drive = my_computer.all_components[MC_HDD]
|
||||
var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD]
|
||||
data["disk_size"] = hard_drive.max_capacity
|
||||
data["disk_used"] = hard_drive.used_capacity
|
||||
data["emagged"] = emagged
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
program_icon = "plug"
|
||||
|
||||
var/has_alert = 0
|
||||
var/obj/structure/cable/attached_wire
|
||||
var/obj/machinery/power/apc/local_apc
|
||||
var/datum/weakref/attached_wire_ref
|
||||
var/datum/weakref/local_apc_ref
|
||||
var/list/history = list()
|
||||
var/record_size = 60
|
||||
var/record_interval = 50
|
||||
@@ -38,19 +38,22 @@
|
||||
|
||||
/datum/computer_file/program/power_monitor/proc/search() //keep in sync with /obj/machinery/computer/monitor's version
|
||||
var/turf/T = get_turf(computer)
|
||||
attached_wire = locate(/obj/structure/cable) in T
|
||||
if(attached_wire)
|
||||
attached_wire_ref = WEAKREF(locate(/obj/structure/cable) in T)
|
||||
if(attached_wire_ref)
|
||||
return
|
||||
var/area/A = get_area(computer) //if the computer isn't directly connected to a wire, attempt to find the APC powering it to pull it's powernet instead
|
||||
if(!A)
|
||||
return
|
||||
local_apc = A.apc
|
||||
var/obj/machinery/power/apc/local_apc = WEAKREF(A.apc)
|
||||
if(!local_apc)
|
||||
return
|
||||
if(!local_apc.terminal) //this really shouldn't happen without badminnery.
|
||||
local_apc = null
|
||||
local_apc_ref = WEAKREF(local_apc)
|
||||
|
||||
/datum/computer_file/program/power_monitor/proc/get_powernet() //keep in sync with /obj/machinery/computer/monitor's version
|
||||
var/obj/structure/cable/attached_wire = attached_wire_ref?.resolve()
|
||||
var/obj/machinery/power/apc/local_apc = local_apc_ref?.resolve()
|
||||
if(attached_wire || (local_apc?.terminal))
|
||||
return attached_wire ? attached_wire.powernet : local_apc.terminal.powernet
|
||||
return FALSE
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
program_icon = "robot"
|
||||
///Number of simple robots on-station.
|
||||
var/botcount = 0
|
||||
///Used to find the location of the user for the purposes of summoning robots.
|
||||
var/mob/current_user
|
||||
///Access granted by the used to summon robots.
|
||||
var/list/current_access = list()
|
||||
|
||||
@@ -33,12 +31,11 @@
|
||||
data["access_on_card"] = id_card ? id_card.access : null
|
||||
|
||||
botcount = 0
|
||||
current_user = user
|
||||
|
||||
for(var/mob/living/simple_animal/bot/simple_bot as anything in GLOB.bots_list)
|
||||
if(simple_bot.z != zlevel || !(simple_bot.bot_mode_flags & BOT_MODE_REMOTE_ENABLED)) //Only non-emagged bots on the same Z-level are detected!
|
||||
continue
|
||||
if(computer && !simple_bot.check_access(current_user)) // Only check Bots we can access)
|
||||
if(computer && !simple_bot.check_access(user)) // Only check Bots we can access)
|
||||
continue
|
||||
var/list/newbot = list(
|
||||
"name" = simple_bot.name,
|
||||
@@ -71,10 +68,11 @@
|
||||
|
||||
return data
|
||||
|
||||
/datum/computer_file/program/robocontrol/ui_act(action, list/params)
|
||||
/datum/computer_file/program/robocontrol/ui_act(action, list/params, datum/tgui/ui)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/mob/current_user = ui.user
|
||||
var/obj/item/computer_hardware/card_slot/card_slot
|
||||
var/obj/item/card/id/id_card
|
||||
if(computer)
|
||||
|
||||
@@ -14,12 +14,6 @@
|
||||
size = 5
|
||||
tgui_id = "NtosRobotact"
|
||||
program_icon = "terminal"
|
||||
///A typed reference to the computer, specifying the borg tablet type
|
||||
var/obj/item/modular_computer/tablet/integrated/tablet
|
||||
|
||||
/datum/computer_file/program/robotact/Destroy()
|
||||
tablet = null
|
||||
return ..()
|
||||
|
||||
/datum/computer_file/program/robotact/run_program(mob/living/user)
|
||||
if(!istype(computer, /obj/item/modular_computer/tablet/integrated))
|
||||
@@ -27,7 +21,7 @@
|
||||
return FALSE
|
||||
. = ..()
|
||||
if(.)
|
||||
tablet = computer
|
||||
var/obj/item/modular_computer/tablet/integrated/tablet = computer
|
||||
if(tablet.device_theme == "syndicate")
|
||||
program_icon_state = "command-syndicate"
|
||||
return TRUE
|
||||
@@ -37,6 +31,10 @@
|
||||
var/list/data = get_header_data()
|
||||
if(!iscyborg(user))
|
||||
return data
|
||||
|
||||
//Implied, since we can't run on non tablets
|
||||
var/obj/item/modular_computer/tablet/integrated/tablet = computer
|
||||
|
||||
var/mob/living/silicon/robot/borgo = tablet.borgo
|
||||
|
||||
data["name"] = borgo.name
|
||||
@@ -80,6 +78,8 @@
|
||||
if(!iscyborg(user))
|
||||
return data
|
||||
var/mob/living/silicon/robot/borgo = user
|
||||
//Implied
|
||||
var/obj/item/modular_computer/tablet/integrated/tablet = computer
|
||||
|
||||
data["Laws"] = borgo.laws.get_law_list(TRUE, TRUE, FALSE)
|
||||
data["borgLog"] = tablet.borglog
|
||||
@@ -90,7 +90,8 @@
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
//Implied type, memes
|
||||
var/obj/item/modular_computer/tablet/integrated/tablet = computer
|
||||
var/mob/living/silicon/robot/borgo = tablet.borgo
|
||||
|
||||
switch(action)
|
||||
@@ -149,7 +150,9 @@
|
||||
* law changes and borg log additions.
|
||||
*/
|
||||
/datum/computer_file/program/robotact/proc/force_full_update()
|
||||
if(tablet)
|
||||
if(!istype(computer, /obj/item/modular_computer/tablet/integrated))
|
||||
return
|
||||
var/obj/item/modular_computer/tablet/integrated/tablet = computer
|
||||
var/datum/tgui/active_ui = SStgui.get_open_ui(tablet.borgo, src)
|
||||
if(active_ui)
|
||||
active_ui.send_full_update()
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
program_icon = "eye"
|
||||
|
||||
var/list/network = list("ss13")
|
||||
var/obj/machinery/camera/active_camera
|
||||
/// Weakref to the active camera
|
||||
var/datum/weakref/camera_ref
|
||||
/// The turf where the camera was last updated.
|
||||
var/turf/last_camera_turf
|
||||
var/list/concurrent_users = list()
|
||||
@@ -92,6 +93,7 @@
|
||||
var/list/data = get_header_data()
|
||||
data["network"] = network
|
||||
data["activeCamera"] = null
|
||||
var/obj/machinery/camera/active_camera = camera_ref?.resolve()
|
||||
if(active_camera)
|
||||
data["activeCamera"] = list(
|
||||
name = active_camera.c_tag,
|
||||
@@ -121,7 +123,7 @@
|
||||
var/c_tag = params["name"]
|
||||
var/list/cameras = get_available_cameras()
|
||||
var/obj/machinery/camera/selected_camera = cameras[c_tag]
|
||||
active_camera = selected_camera
|
||||
camera_ref = WEAKREF(selected_camera)
|
||||
playsound(src, get_sfx("terminal_type"), 25, FALSE)
|
||||
|
||||
if(!selected_camera)
|
||||
@@ -141,10 +143,11 @@
|
||||
user.client.clear_map(map_name)
|
||||
// Turn off the console
|
||||
if(length(concurrent_users) == 0 && is_living)
|
||||
active_camera = null
|
||||
camera_ref = null
|
||||
playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE)
|
||||
|
||||
/datum/computer_file/program/secureye/proc/update_active_camera_screen()
|
||||
var/obj/machinery/camera/active_camera = camera_ref?.resolve()
|
||||
// Show static if can't use the camera
|
||||
if(!active_camera?.can_use())
|
||||
show_camera_static()
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/on_remove(obj/item/modular_computer/remove_from, mob/user)
|
||||
remove_from.shutdown_computer()
|
||||
for(var/datum/computer_file/program/program in stored_files)
|
||||
program.computer = null
|
||||
|
||||
/obj/item/computer_hardware/hard_drive/proc/install_default_programs()
|
||||
store_file(new/datum/computer_file/program/computerconfig(src)) // Computer configuration utility, allows hardware control and displays more info than status bar
|
||||
|
||||
@@ -22,6 +22,16 @@
|
||||
var/list/ticket_holders = list()
|
||||
var/list/obj/item/ticket_machine_ticket/tickets = list()
|
||||
|
||||
/obj/machinery/ticket_machine/Initialize(mapload)
|
||||
. = ..()
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/ticket_machine/Destroy()
|
||||
for(var/obj/item/ticket_machine_ticket/ticket in tickets)
|
||||
ticket.source = null
|
||||
tickets.Cut()
|
||||
return ..()
|
||||
|
||||
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/ticket_machine, 32)
|
||||
|
||||
/obj/machinery/ticket_machine/multitool_act(mob/living/user, obj/item/I)
|
||||
@@ -46,10 +56,6 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/ticket_machine, 32)
|
||||
tickets.Cut()
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/ticket_machine/Initialize(mapload)
|
||||
. = ..()
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/ticket_machine/proc/increment()
|
||||
if(current_number > ticket_number)
|
||||
return
|
||||
@@ -178,21 +184,21 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/ticket_machine, 32)
|
||||
if(ticket_number >= max_number)
|
||||
to_chat(user,span_warning("Ticket supply depleted, please refill this unit with a hand labeller refill cartridge!"))
|
||||
return
|
||||
if((user in ticket_holders) && !(obj_flags & EMAGGED))
|
||||
var/user_ref = REF(user)
|
||||
if((user_ref in ticket_holders) && !(obj_flags & EMAGGED))
|
||||
to_chat(user, span_warning("You already have a ticket!"))
|
||||
return
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 100, FALSE)
|
||||
ticket_number ++
|
||||
ticket_number++
|
||||
to_chat(user, span_notice("You take a ticket from [src], looks like you're ticket number #[ticket_number]..."))
|
||||
var/obj/item/ticket_machine_ticket/theirticket = new /obj/item/ticket_machine_ticket(get_turf(src))
|
||||
theirticket.name = "Ticket #[ticket_number]"
|
||||
theirticket.maptext = MAPTEXT(ticket_number)
|
||||
theirticket.saved_maptext = MAPTEXT(ticket_number)
|
||||
theirticket.ticket_number = ticket_number
|
||||
theirticket.source = src
|
||||
theirticket.owner = user
|
||||
theirticket.owner_ref = user_ref
|
||||
user.put_in_hands(theirticket)
|
||||
ticket_holders += user
|
||||
ticket_holders += user_ref
|
||||
tickets += theirticket
|
||||
if(obj_flags & EMAGGED) //Emag the machine to destroy the HOP's life.
|
||||
ready = FALSE
|
||||
@@ -214,9 +220,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/ticket_machine, 32)
|
||||
resistance_flags = FLAMMABLE
|
||||
max_integrity = 50
|
||||
var/saved_maptext = null
|
||||
var/mob/living/carbon/owner
|
||||
var/owner_ref // A ref to our owner. Doesn't need to be weak because mobs have unique refs
|
||||
var/obj/machinery/ticket_machine/source
|
||||
var/ticket_number
|
||||
|
||||
/obj/item/ticket_machine_ticket/attack_hand(mob/user, list/modifiers)
|
||||
. = ..()
|
||||
@@ -233,9 +238,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/ticket_machine, 32)
|
||||
update_appearance()
|
||||
|
||||
/obj/item/ticket_machine_ticket/Destroy()
|
||||
if(owner && source)
|
||||
source.ticket_holders -= owner
|
||||
source.tickets[ticket_number] = null
|
||||
owner = null
|
||||
if(source)
|
||||
source.ticket_holders -= owner_ref
|
||||
source.tickets -= src
|
||||
source = null
|
||||
return ..()
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/datum/picture
|
||||
var/picture_name = "picture"
|
||||
var/picture_desc = "This is a picture."
|
||||
/// List of weakrefs pointing at mobs that appear in this photo
|
||||
var/list/mobs_seen = list()
|
||||
/// List of weakrefs pointing at dead mobs that appear in this photo
|
||||
var/list/dead_seen = list()
|
||||
var/caption
|
||||
var/icon/picture_image
|
||||
@@ -20,9 +22,11 @@
|
||||
if(!isnull(desc))
|
||||
picture_desc = desc
|
||||
if(!isnull(mobs_spotted))
|
||||
mobs_seen = mobs_spotted
|
||||
for(var/mob/seen as anything in mobs_spotted)
|
||||
mobs_seen += WEAKREF(seen)
|
||||
if(!isnull(dead_spotted))
|
||||
dead_seen = dead_spotted
|
||||
for(var/mob/seen as anything in dead_spotted)
|
||||
dead_seen += WEAKREF(seen)
|
||||
if(!isnull(image))
|
||||
picture_image = image
|
||||
if(!isnull(icon))
|
||||
|
||||
@@ -35,8 +35,13 @@
|
||||
|
||||
if(!P.see_ghosts) ///Dont bother with this last bit if we can't see ghosts
|
||||
return
|
||||
for(var/i in P.mobs_seen) //Any ghosts in the pic? its a haunted photo ooooo~
|
||||
if(isobserver(i))
|
||||
for(var/datum/weakref/seen_ref in P.mobs_seen) //Any ghosts in the pic? its a haunted photo ooooo~
|
||||
var/mob/seen = seen_ref.resolve()
|
||||
if(!seen)
|
||||
P.mobs_seen -= seen_ref
|
||||
continue
|
||||
if(!isobserver(seen))
|
||||
continue
|
||||
set_custom_materials(list(/datum/material/hauntium = 2000))
|
||||
break
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
new_light = new /obj/machinery/light/small/built(loc)
|
||||
new_light.setDir(dir)
|
||||
transfer_fingerprints_to(new_light)
|
||||
if(cell)
|
||||
if(!QDELETED(cell))
|
||||
new_light.cell = cell
|
||||
cell.forceMove(new_light)
|
||||
cell = null
|
||||
|
||||
@@ -38,8 +38,7 @@
|
||||
*/
|
||||
/obj/item/gun/medbeam/proc/LoseTarget()
|
||||
if(active)
|
||||
qdel(current_beam)
|
||||
current_beam = null
|
||||
QDEL_NULL(current_beam)
|
||||
active = FALSE
|
||||
on_beam_release(current_target)
|
||||
current_target = null
|
||||
@@ -51,6 +50,7 @@
|
||||
*/
|
||||
/obj/item/gun/medbeam/proc/beam_died()
|
||||
SIGNAL_HANDLER
|
||||
current_beam = null
|
||||
active = FALSE //skip qdelling the beam again if we're doing this proc, because
|
||||
if(isliving(loc))
|
||||
to_chat(loc, span_warning("You lose control of the beam!"))
|
||||
@@ -87,7 +87,7 @@
|
||||
last_check = world.time
|
||||
|
||||
if(!los_check(loc, current_target))
|
||||
qdel(current_beam)//this will give the target lost message
|
||||
QDEL_NULL(current_beam)//this will give the target lost message
|
||||
return
|
||||
|
||||
if(current_target)
|
||||
|
||||
@@ -1992,6 +1992,10 @@
|
||||
reagents = new /datum/reagents(max_vol, flags)
|
||||
reagents.my_atom = src
|
||||
|
||||
/atom/movable/chem_holder
|
||||
name = "This atom exists to hold chems. If you can see this, make an issue report"
|
||||
desc = "God this is stupid"
|
||||
|
||||
#undef REAGENT_TRANSFER_AMOUNT
|
||||
#undef REAGENT_PURITY
|
||||
|
||||
|
||||
@@ -27,8 +27,10 @@
|
||||
use_power = IDLE_POWER_USE
|
||||
circuit = /obj/item/circuitboard/machine/experimentor
|
||||
var/recentlyExperimented = 0
|
||||
var/mob/trackedIan
|
||||
var/mob/trackedRuntime
|
||||
/// Weakref to the first ian we can find at init
|
||||
var/datum/weakref/tracked_ian_ref
|
||||
/// Weakref to the first runtime we can find at init
|
||||
var/datum/weakref/tracked_runtime_ref
|
||||
var/badThingCoeff = 0
|
||||
var/resetTime = 15
|
||||
var/cloneMode = FALSE
|
||||
@@ -72,8 +74,8 @@
|
||||
/obj/machinery/rnd/experimentor/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
trackedIan = locate(/mob/living/simple_animal/pet/dog/corgi/ian) in GLOB.mob_living_list
|
||||
trackedRuntime = locate(/mob/living/simple_animal/pet/cat/runtime) in GLOB.mob_living_list
|
||||
tracked_ian_ref = WEAKREF(locate(/mob/living/simple_animal/pet/dog/corgi/ian) in GLOB.mob_living_list)
|
||||
tracked_runtime_ref = WEAKREF(locate(/mob/living/simple_animal/pet/cat/runtime) in GLOB.mob_living_list)
|
||||
SetTypeReactions()
|
||||
|
||||
critical_items_typecache = typecacheof(list(
|
||||
@@ -477,9 +479,10 @@
|
||||
if(globalMalf > 16 && globalMalf < 35)
|
||||
visible_message(span_warning("[src] melts [exp_on], ian-izing the air around it!"))
|
||||
throwSmoke(loc)
|
||||
if(trackedIan)
|
||||
throwSmoke(trackedIan.loc)
|
||||
trackedIan.forceMove(loc)
|
||||
var/mob/living/tracked_ian = tracked_ian_ref?.resolve()
|
||||
if(tracked_ian)
|
||||
throwSmoke(tracked_ian.loc)
|
||||
tracked_ian.forceMove(loc)
|
||||
investigate_log("Experimentor has stolen Ian!", INVESTIGATE_EXPERIMENTOR) //...if anyone ever fixes it...
|
||||
else
|
||||
new /mob/living/simple_animal/pet/dog/corgi(loc)
|
||||
@@ -494,9 +497,10 @@
|
||||
if(globalMalf > 51 && globalMalf < 75)
|
||||
visible_message(span_warning("[src] encounters a run-time error!"))
|
||||
throwSmoke(loc)
|
||||
if(trackedRuntime)
|
||||
throwSmoke(trackedRuntime.loc)
|
||||
trackedRuntime.forceMove(drop_location())
|
||||
var/mob/living/tracked_runtime = tracked_runtime_ref?.resolve()
|
||||
if(tracked_runtime)
|
||||
throwSmoke(tracked_runtime.loc)
|
||||
tracked_runtime.forceMove(drop_location())
|
||||
investigate_log("Experimentor has stolen Runtime!", INVESTIGATE_EXPERIMENTOR)
|
||||
else
|
||||
new /mob/living/simple_animal/pet/cat(loc)
|
||||
|
||||
@@ -30,13 +30,6 @@
|
||||
desc = "A computer used for remotely handling slimes."
|
||||
networks = list("ss13")
|
||||
circuit = /obj/item/circuitboard/computer/xenobiology
|
||||
var/datum/action/innate/slime_place/slime_place_action
|
||||
var/datum/action/innate/slime_pick_up/slime_up_action
|
||||
var/datum/action/innate/feed_slime/feed_slime_action
|
||||
var/datum/action/innate/monkey_recycle/monkey_recycle_action
|
||||
var/datum/action/innate/slime_scan/scan_action
|
||||
var/datum/action/innate/feed_potion/potion_action
|
||||
var/datum/action/innate/hotkey_help/hotkey_help
|
||||
|
||||
var/obj/machinery/monkey_recycler/connected_recycler
|
||||
var/list/stored_slimes
|
||||
@@ -51,13 +44,14 @@
|
||||
|
||||
/obj/machinery/computer/camera_advanced/xenobio/Initialize(mapload)
|
||||
. = ..()
|
||||
slime_place_action = new
|
||||
slime_up_action = new
|
||||
feed_slime_action = new
|
||||
monkey_recycle_action = new
|
||||
scan_action = new
|
||||
potion_action = new
|
||||
hotkey_help = new
|
||||
actions += new /datum/action/innate/slime_place(src)
|
||||
actions += new /datum/action/innate/slime_pick_up(src)
|
||||
actions += new /datum/action/innate/feed_slime(src)
|
||||
actions += new /datum/action/innate/monkey_recycle(src)
|
||||
actions += new /datum/action/innate/slime_scan(src)
|
||||
actions += new /datum/action/innate/feed_potion(src)
|
||||
actions += new /datum/action/innate/hotkey_help(src)
|
||||
|
||||
stored_slimes = list()
|
||||
for(var/obj/machinery/monkey_recycler/recycler in GLOB.monkey_recyclers)
|
||||
if(get_area(recycler.loc) == get_area(loc))
|
||||
@@ -91,42 +85,6 @@
|
||||
|
||||
/obj/machinery/computer/camera_advanced/xenobio/GrantActions(mob/living/user)
|
||||
..()
|
||||
|
||||
if(slime_up_action)
|
||||
slime_up_action.target = src
|
||||
slime_up_action.Grant(user)
|
||||
actions += slime_up_action
|
||||
|
||||
if(slime_place_action)
|
||||
slime_place_action.target = src
|
||||
slime_place_action.Grant(user)
|
||||
actions += slime_place_action
|
||||
|
||||
if(feed_slime_action)
|
||||
feed_slime_action.target = src
|
||||
feed_slime_action.Grant(user)
|
||||
actions += feed_slime_action
|
||||
|
||||
if(monkey_recycle_action)
|
||||
monkey_recycle_action.target = src
|
||||
monkey_recycle_action.Grant(user)
|
||||
actions += monkey_recycle_action
|
||||
|
||||
if(scan_action)
|
||||
scan_action.target = src
|
||||
scan_action.Grant(user)
|
||||
actions += scan_action
|
||||
|
||||
if(potion_action)
|
||||
potion_action.target = src
|
||||
potion_action.Grant(user)
|
||||
actions += potion_action
|
||||
|
||||
if(hotkey_help)
|
||||
hotkey_help.target = src
|
||||
hotkey_help.Grant(user)
|
||||
actions += hotkey_help
|
||||
|
||||
RegisterSignal(user, COMSIG_XENO_SLIME_CLICK_CTRL, .proc/XenoSlimeClickCtrl)
|
||||
RegisterSignal(user, COMSIG_XENO_TURF_CLICK_CTRL, .proc/XenoTurfClickCtrl)
|
||||
RegisterSignal(user, COMSIG_XENO_MONKEY_CLICK_CTRL, .proc/XenoMonkeyClickCtrl)
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
move_up_action = null
|
||||
move_down_action = null
|
||||
|
||||
var/datum/action/innate/shuttledocker_rotate/rotate_action = new
|
||||
var/datum/action/innate/shuttledocker_place/place_action = new
|
||||
var/shuttleId = ""
|
||||
var/shuttlePortId = ""
|
||||
var/shuttlePortName = "custom location"
|
||||
@@ -29,6 +27,8 @@
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/Initialize(mapload)
|
||||
. = ..()
|
||||
GLOB.navigation_computers += src
|
||||
actions += new /datum/action/innate/shuttledocker_rotate(src)
|
||||
actions += new /datum/action/innate/shuttledocker_place(src)
|
||||
|
||||
if(!mapload)
|
||||
connect_to_shuttle(SSshuttle.get_containing_shuttle(src))
|
||||
@@ -68,19 +68,9 @@
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/GrantActions(mob/living/user)
|
||||
if(jumpto_ports.len)
|
||||
jump_action = new /datum/action/innate/camera_jump/shuttle_docker
|
||||
actions += new /datum/action/innate/camera_jump/shuttle_docker(src)
|
||||
..()
|
||||
|
||||
if(rotate_action)
|
||||
rotate_action.target = user
|
||||
rotate_action.Grant(user)
|
||||
actions += rotate_action
|
||||
|
||||
if(place_action)
|
||||
place_action.target = user
|
||||
place_action.Grant(user)
|
||||
actions += place_action
|
||||
|
||||
/obj/machinery/computer/camera_advanced/shuttle_docker/CreateEye()
|
||||
shuttle_port = SSshuttle.getShuttle(shuttleId)
|
||||
if(QDELETED(shuttle_port))
|
||||
@@ -321,10 +311,9 @@
|
||||
button_icon_state = "mech_cycle_equip_off"
|
||||
|
||||
/datum/action/innate/shuttledocker_rotate/Activate()
|
||||
if(QDELETED(target) || !isliving(target))
|
||||
if(QDELETED(owner) || !isliving(owner))
|
||||
return
|
||||
var/mob/living/C = target
|
||||
var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
|
||||
var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
|
||||
origin.rotateLandingSpot()
|
||||
|
||||
@@ -334,22 +323,20 @@
|
||||
button_icon_state = "mech_zoom_off"
|
||||
|
||||
/datum/action/innate/shuttledocker_place/Activate()
|
||||
if(QDELETED(target) || !isliving(target))
|
||||
if(QDELETED(owner) || !isliving(owner))
|
||||
return
|
||||
var/mob/living/C = target
|
||||
var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
|
||||
var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/origin = remote_eye.origin
|
||||
origin.placeLandingSpot(target)
|
||||
origin.placeLandingSpot(owner)
|
||||
|
||||
/datum/action/innate/camera_jump/shuttle_docker
|
||||
name = "Jump to Location"
|
||||
button_icon_state = "camera_jump"
|
||||
|
||||
/datum/action/innate/camera_jump/shuttle_docker/Activate()
|
||||
if(QDELETED(target) || !isliving(target))
|
||||
if(QDELETED(owner) || !isliving(owner))
|
||||
return
|
||||
var/mob/living/C = target
|
||||
var/mob/camera/ai_eye/remote/remote_eye = C.remote_control
|
||||
var/mob/camera/ai_eye/remote/remote_eye = owner.remote_control
|
||||
var/obj/machinery/computer/camera_advanced/shuttle_docker/console = remote_eye.origin
|
||||
|
||||
playsound(console, 'sound/machines/terminal_prompt_deny.ogg', 25, FALSE)
|
||||
@@ -382,7 +369,7 @@
|
||||
if(isnull(selected))
|
||||
playsound(console, 'sound/machines/terminal_prompt_deny.ogg', 25, FALSE)
|
||||
return
|
||||
if(QDELETED(src) || QDELETED(target) || !isliving(target))
|
||||
if(QDELETED(src) || QDELETED(owner) || !isliving(owner))
|
||||
return
|
||||
playsound(src, "terminal_type", 25, FALSE)
|
||||
var/turf/T = get_turf(L[selected])
|
||||
@@ -390,6 +377,6 @@
|
||||
return
|
||||
playsound(console, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
|
||||
remote_eye.setLoc(T)
|
||||
to_chat(target, span_notice("Jumped to [selected]."))
|
||||
C.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static)
|
||||
C.clear_fullscreen("flash", 3)
|
||||
to_chat(owner, span_notice("Jumped to [selected]."))
|
||||
owner.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static)
|
||||
owner.clear_fullscreen("flash", 3)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user