conflicts? apparently?

This commit is contained in:
Purpose
2018-10-10 18:53:22 +01:00
357 changed files with 9759 additions and 6358 deletions
+1 -1
View File
@@ -42,7 +42,7 @@
//This is the icon for fire on turfs, also helps for nurturing small fires until they are full tile
/obj/effect/hotspot
anchored = 1
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
unacidable = 1//So you can't melt fire with acid.
icon = 'icons/effects/fire.dmi'
icon_state = "1"
+3 -3
View File
@@ -250,7 +250,7 @@
var/atmos_overlay = get_atmos_overlay_by_name(atmos_overlay_type)
if(atmos_overlay)
overlays -= atmos_overlay
mouse_opacity = 1
mouse_opacity = MOUSE_OPACITY_ICON
atmos_overlay = get_atmos_overlay_by_name(new_overlay_type)
if(atmos_overlay)
@@ -267,12 +267,12 @@
/turf/simulated/proc/tile_graphic()
if(air.toxins > MOLES_PLASMA_VISIBLE)
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
return "plasma"
var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in air.trace_gases
if(sleeping_agent && (sleeping_agent.moles > 1))
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
return "sleeping_agent"
return null
+2
View File
@@ -54,6 +54,8 @@
// LAVA_PROTECT used on the flags_2 variable for both SUIT and HEAD items, and stops lava damage. Must be present in both to stop lava damage.
#define LAVA_PROTECT_2 2048
#define OVERLAY_QUEUED_2 4096
//Reagent flags
#define REAGENT_NOREACT 1
+1
View File
@@ -27,6 +27,7 @@
#define GAS_PIPE_VISIBLE_LAYER 2.47
#define GAS_FILTER_LAYER 2.48
#define GAS_PUMP_LAYER 2.49
#define CONVEYOR_LAYER 2.495
#define LOW_OBJ_LAYER 2.5
#define LOW_SIGIL_LAYER 2.52
#define SIGIL_LAYER 2.54
+10 -1
View File
@@ -373,4 +373,13 @@
#define RETURN_TO_LOBBY 2
//Melting Temperatures for various specific objects
#define GIRDER_MELTING_TEMP 5000
#define GIRDER_MELTING_TEMP 5000
// Area selection defines
#define AREASELECT_CORNERA "corner A"
#define AREASELECT_CORNERB "corner B"
//https://secure.byond.com/docs/ref/info.html#/atom/var/mouse_opacity
#define MOUSE_OPACITY_TRANSPARENT 0
#define MOUSE_OPACITY_ICON 1
#define MOUSE_OPACITY_OPAQUE 2
+12
View File
@@ -132,6 +132,18 @@
#define EMOTE_VISUAL 1 //A mob emote is visual
#define EMOTE_SOUND 2 //A mob emote is sound
#define STATUS_UPDATE_HEALTH 1
#define STATUS_UPDATE_STAT 2
#define STATUS_UPDATE_CANMOVE 4
#define STATUS_UPDATE_STAMINA 8
#define STATUS_UPDATE_BLIND 16
#define STATUS_UPDATE_BLURRY 32
#define STATUS_UPDATE_NEARSIGHTED 64
#define STATUS_UPDATE_DRUGGY 128
#define STATUS_UPDATE_NONE 0
#define STATUS_UPDATE_ALL (~0)
//Human sub-species
#define isshadowling(A) (is_species(A, /datum/species/shadow/ling))
#define isshadowlinglesser(A) (is_species(A, /datum/species/shadow/ling/lesser))
+4 -1
View File
@@ -1,3 +1,6 @@
#define SOLID 1
#define LIQUID 2
#define GAS 3
#define GAS 3
#define REAGENT_OVERDOSE_EFFECT 1
#define REAGENT_OVERDOSE_FLAGS 2
+23
View File
@@ -14,6 +14,10 @@
//prevents distinguishing identical timers with the wait variable
#define TIMER_NO_HASH_WAIT 16
//Loops the timer repeatedly until qdeleted
//In most cases you want a subsystem instead
#define TIMER_LOOP 32
#define TIMER_NO_INVOKE_WARNING 600 //number of byond ticks that are allowed to pass before the timer subsystem thinks it hung on something
#define TIMER_ID_NULL -1
@@ -120,3 +124,22 @@
#define RUNLEVEL_POSTGAME 8
#define RUNLEVELS_DEFAULT (RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME)
#define COMPILE_OVERLAYS(A)\
if (TRUE) {\
var/list/ad = A.add_overlays;\
var/list/rm = A.remove_overlays;\
var/list/po = A.priority_overlays;\
if(LAZYLEN(rm)){\
A.overlays -= rm;\
rm.Cut();\
}\
if(LAZYLEN(ad)){\
A.overlays |= ad;\
ad.Cut();\
}\
if(LAZYLEN(po)){\
A.overlays |= po;\
}\
A.flags_2 &= ~OVERLAY_QUEUED_2;\
}
+1 -1
View File
@@ -185,4 +185,4 @@
return "[key_name(src)] ([mob.x],[mob.y],[mob.z])"
//this is only used here (for now)
#undef RUST_G
#undef RUST_G
+29
View File
@@ -9,6 +9,35 @@
* Misc
*/
// binary search sorted insert
// IN: Object to be inserted
// LIST: List to insert object into
// TYPECONT: The typepath of the contents of the list
// COMPARE: The variable on the objects to compare
#define BINARY_INSERT(IN, LIST, TYPECONT, COMPARE) \
var/__BIN_CTTL = length(LIST);\
if(!__BIN_CTTL) {\
LIST += IN;\
} else {\
var/__BIN_LEFT = 1;\
var/__BIN_RIGHT = __BIN_CTTL;\
var/__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
var/##TYPECONT/__BIN_ITEM;\
while(__BIN_LEFT < __BIN_RIGHT) {\
__BIN_ITEM = LIST[__BIN_MID];\
if(__BIN_ITEM.##COMPARE <= IN.##COMPARE) {\
__BIN_LEFT = __BIN_MID + 1;\
} else {\
__BIN_RIGHT = __BIN_MID;\
};\
__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
};\
__BIN_ITEM = LIST[__BIN_MID];\
__BIN_MID = __BIN_ITEM.##COMPARE > IN.##COMPARE ? __BIN_MID : __BIN_MID + 1;\
LIST.Insert(__BIN_MID, IN);\
}
//Returns a list in plain english as a string
/proc/english_list(var/list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
var/total = input.len
+3 -4
View File
@@ -255,8 +255,8 @@ This is always put in the attack log.
add_attack_logs(user, M, what_done, custom_level)
return
var/user_str = key_name_log(user)
var/target_str = key_name_log(target)
var/user_str = key_name_log(user) + COORD(user)
var/target_str = key_name_log(target) + COORD(target)
if(istype(user))
user.create_attack_log("<font color='red'>Attacked [target_str]: [what_done]</font>")
@@ -265,7 +265,6 @@ This is always put in the attack log.
log_attack(user_str, target_str, what_done)
var/loglevel = ATKLOG_MOST
if(!isnull(custom_level))
loglevel = custom_level
else if(istype(target))
@@ -503,4 +502,4 @@ This is always put in the attack log.
var/list/viewrangelist = splittext(view, "x")
viewX = text2num(viewrangelist[1])
viewY = text2num(viewrangelist[2])
return list(viewX, viewY)
return list(viewX, viewY)
+87 -16
View File
@@ -1785,28 +1785,99 @@ var/mob/dview/dview_mob = new
for(var/type in types)
var/typename = "[type]"
var/static/list/TYPES_SHORTCUTS = list(
//longest paths comes first - otherwise they get shadowed by the more generic ones
/obj/effect/decal/cleanable = "CLEANABLE",
/obj/item/radio/headset = "HEADSET",
/obj/item/clothing/head/helmet/space = "SPESSHELMET",
/obj/item/book/manual = "MANUAL",
/obj/item/reagent_containers/food/drinks = "DRINK", //longest paths comes first
/obj/item/reagent_containers/food = "FOOD",
/obj/item/reagent_containers = "REAGENT_CONTAINERS",
/obj/item = "WEAPON",
/obj/machinery/atmospherics = "ATMOS_MECH",
/obj/machinery/portable_atmospherics = "PORT_ATMOS",
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack = "MECHA_MISSILE_RACK",
/obj/item/mecha_parts/mecha_equipment = "MECHA_EQUIP",
/obj/item/organ = "ORGAN",
/obj/item = "ITEM",
/obj/machinery = "MACHINERY",
/obj/effect = "EFFECT",
/obj/item/ammo_casing = "AMMO",
/obj/item/book/manual = "MANUAL",
/obj/item/borg/upgrade = "BORG_UPGRADE",
/obj/item/cartridge = "PDA_CART",
/obj/item/clothing/head/helmet/space = "SPESSHELMET",
/obj/item/clothing/head = "HEAD",
/obj/item/clothing/under = "UNIFORM",
/obj/item/clothing/shoes = "SHOES",
/obj/item/clothing/suit = "SUIT",
/obj/item/clothing/gloves = "GLOVES",
/obj/item/clothing/mask/cigarette = "CIGARRETE", // oof
/obj/item/clothing/mask = "MASK",
/obj/item/clothing/glasses = "GLASSES",
/obj/item/clothing = "CLOTHING",
/obj/item/grenade/clusterbuster = "CLUSTERBUSTER",
/obj/item/grenade = "GRENADE",
/obj/item/gun = "GUN",
/obj/item/implant = "IMPLANT",
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack = "MECHA_MISSILE_RACK",
/obj/item/mecha_parts/mecha_equipment/weapon = "MECHA_WEAPON",
/obj/item/mecha_parts/mecha_equipment = "MECHA_EQUIP",
/obj/item/melee = "MELEE",
/obj/item/mmi = "MMI",
/obj/item/nullrod = "NULLROD",
/obj/item/organ/external = "EXT_ORG",
/obj/item/organ/internal/cyberimp = "CYBERIMP",
/obj/item/organ/internal = "INT_ORG",
/obj/item/organ = "ORGAN",
/obj/item/pda = "PDA",
/obj/item/projectile = "PROJ",
/obj/item/radio/headset = "HEADSET",
/obj/item/reagent_containers/glass/beaker = "BEAKER",
/obj/item/reagent_containers/glass/bottle = "BOTTLE",
/obj/item/reagent_containers/food/pill/patch = "PATCH",
/obj/item/reagent_containers/food/pill = "PILL",
/obj/item/reagent_containers/food/drinks = "DRINK",
/obj/item/reagent_containers/food = "FOOD",
/obj/item/reagent_containers/syringe = "SYRINGE",
/obj/item/reagent_containers = "REAGENT_CONTAINERS",
/obj/item/robot_parts = "ROBOT_PARTS",
/obj/item/seeds = "SEED",
/obj/item/slime_extract = "SLIME_CORE",
/obj/item/spacepod_equipment/weaponry = "POD_WEAPON",
/obj/item/spacepod_equipment = "POD_EQUIP",
/obj/item/stack/sheet/mineral = "MINERAL",
/obj/item/stack/sheet = "SHEET",
/obj/item/stack/tile = "TILE",
/obj/item/stack = "STACK",
/obj/item/stock_parts/cell = "POWERCELL",
/obj/item/stock_parts = "STOCK_PARTS",
/obj/item/storage/firstaid = "FIRSTAID",
/obj/item/storage = "STORAGE",
/obj/item/tank = "GAS_TANK",
/obj/item/toy/crayon = "CRAYON",
/obj/item/toy = "TOY",
/obj/item = "ITEM",
/obj/machinery/atmospherics = "ATMOS_MACH",
/obj/machinery/computer = "CONSOLE",
/obj/machinery/door/airlock = "AIRLOCK",
/obj/machinery/door = "DOOR",
/obj/machinery/kitchen_machine = "KITCHEN",
/obj/machinery/portable_atmospherics/canister = "CANISTER",
/obj/machinery/portable_atmospherics = "PORT_ATMOS",
/obj/machinery/power = "POWER",
/obj/machinery/telecomms = "TCOMMS",
/obj/machinery = "MACHINERY",
/obj/mecha = "MECHA",
/obj/structure/closet/crate = "CRATE",
/obj/structure/closet = "CLOSET",
/obj/structure/statue = "STATUE",
/obj/structure/chair = "CHAIR", // oh no
/obj/structure/stool/bed = "BED",
/obj/structure/stool = "STOOL",
/obj/structure/table = "TABLE",
/obj/structure = "STRUCTURE",
/obj/vehicle = "VEHICLE",
/obj = "O",
/datum = "D",
/turf/simulated/floor = "FLOOR",
/turf/simulated/wall = "WALL",
/turf/simulated/floor = "SIM_FLOOR",
/turf/simulated/wall = "SIM_WALL",
/turf/unsimulated/floor = "UNSIM_FLOOR",
/turf/unsimulated/wall = "UNSIM_WALL",
/turf = "T",
/mob/living/carbon/alien = "XENO",
/mob/living/carbon/human = "HUMAN",
/mob/living/carbon = "CARBON",
/mob/living/silicon/robot = "CYBORG",
/mob/living/silicon/ai = "AI",
/mob/living/silicon = "SILICON",
/mob/living/simple_animal/bot = "BOT",
/mob/living/simple_animal = "SIMPLE",
/mob/living = "LIVING",
/mob = "M"
+2 -1
View File
@@ -11,7 +11,8 @@
*/
/mob/living/silicon/ai/DblClickOn(var/atom/A, params)
if(client.click_intercept)
client.click_intercept.InterceptClickOn(src, params, A)
// Not doing a click intercept here, because otherwise we double-tap with the `ClickOn` proc.
// But we return here since we don't want to do regular dblclick handling
return
if(control_disabled || stat) return
+1 -1
View File
@@ -392,7 +392,7 @@
icon = 'icons/mob/screen_full.dmi'
icon_state = "passage0"
plane = CLICKCATCHER_PLANE
mouse_opacity = 2
mouse_opacity = MOUSE_OPACITY_OPAQUE
screen_loc = "CENTER-7,CENTER-7"
/obj/screen/click_catcher/Click(location, control, params)
+1 -1
View File
@@ -89,7 +89,7 @@
icon_state = "default"
name = "Alert"
desc = "Something seems to have gone wrong with this alert, so report this bug please"
mouse_opacity = 1
mouse_opacity = MOUSE_OPACITY_ICON
var/timeout = 0 //If set to a number, this alert will clear itself after that many deciseconds
var/severity = 0
var/alerttooltipstyle = ""
+1 -1
View File
@@ -54,7 +54,7 @@
icon_state = "default"
screen_loc = "CENTER-7,CENTER-7"
layer = FULLSCREEN_LAYER
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/severity = 0
/obj/screen/fullscreen/Destroy()
+32 -2
View File
@@ -26,7 +26,7 @@
/obj/screen/text
icon = null
icon_state = null
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
screen_loc = "CENTER-7,CENTER-7"
maptext_height = 480
maptext_width = 480
@@ -275,8 +275,38 @@
/obj/screen/inventory
var/slot_id //The indentifier for the slot. It has nothing to do with ID cards.
var/list/object_overlays = list()
layer = 19
/obj/screen/inventory/MouseEntered()
..()
add_overlays()
/obj/screen/inventory/MouseExited()
..()
cut_overlay(object_overlays)
object_overlays.Cut()
/obj/screen/inventory/proc/add_overlays()
var/mob/user = hud.mymob
if(hud && user && slot_id)
var/obj/item/holding = user.get_active_hand()
if(!holding || user.get_item_by_slot(slot_id))
return
var/image/item_overlay = image(holding)
item_overlay.alpha = 92
if(!user.can_equip(holding, slot_id, disable_warning = TRUE))
item_overlay.color = "#ff0000"
else
item_overlay.color = "#00ff00"
object_overlays += item_overlay
add_overlay(object_overlays)
/obj/screen/inventory/Click()
// At this point in client Click() code we have passed the 1/10 sec check and little else
// We don't even know if it's a middle click
@@ -379,7 +409,7 @@
icon = 'icons/mob/guardian.dmi'
icon_state = "base"
screen_loc = ui_health
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/obj/screen/healthdoll
name = "health doll"
+2 -1
View File
@@ -1,6 +1,7 @@
/mob/dead/observer/DblClickOn(var/atom/A, var/params)
if(client.click_intercept)
client.click_intercept.InterceptClickOn(src, params, A)
// Not doing a click intercept here, because otherwise we double-tap with the `ClickOn` proc.
// But we return here since we don't want to do regular dblclick handling
return
if(can_reenter_corpse && mind && mind.current)
-20
View File
@@ -2,7 +2,6 @@ var/global/datum/controller/process/npcai/npcai_master
/datum/controller/process/npcai
var/current_cycle
var/saved_voice = 0
/datum/controller/process/npcai/setup()
name = "npc ai"
@@ -36,25 +35,6 @@ var/global/datum/controller/process/npcai/npcai_master
catchBadType(M)
simple_animal_list -= M
if(ticker.current_state == GAME_STATE_FINISHED && !saved_voice)
var/mob/living/carbon/human/interactive/M = safepick(snpc_list)
if(M)
M.saveVoice()
saved_voice = 1
for(last_object in snpc_list)
var/mob/living/carbon/human/interactive/M = last_object
if(istype(M) && !QDELETED(M))
try
if(!M.alternateProcessing || M.forceProcess)
M.doProcess()
catch(var/exception/e)
catchException(e, M)
SCHECK
else
catchBadType(M)
snpc_list -= M
current_cycle++
-119
View File
@@ -1,119 +0,0 @@
var/global/datum/controller/process/npcpool/npc_master
/datum/controller/process/npcpool
var/list/canBeUsed = list()
var/list/canBeUsed_non = list()
var/list/needsDelegate = list()
var/list/needsAssistant = list()
var/list/needsHelp_non = list()
var/list/botPool_l = list() //list of all npcs using the pool
var/list/botPool_l_non = list() //list of all non SNPC mobs using the pool
/datum/controller/process/npcpool/setup()
name = "npc pool"
schedule_interval = 100
start_delay = 17
log_startup_progress("NPC pool ticker starting up.")
/datum/controller/process/npcpool/copyStateFrom(var/datum/controller/process/npcpool/target)
canBeUsed = target.canBeUsed
canBeUsed_non = target.canBeUsed_non
needsDelegate = target.needsDelegate
needsAssistant = target.needsAssistant
needsHelp_non = target.needsHelp_non
botPool_l = target.botPool_l
botPool_l_non = target.botPool_l_non
DECLARE_GLOBAL_CONTROLLER(npcpool, npc_master)
/datum/controller/process/npcpool/proc/insertBot(toInsert)
if(istype(toInsert, /mob/living/carbon/human/interactive))
botPool_l |= toInsert
/datum/controller/process/npcpool/proc/removeBot(toRemove)
botPool_l -= toRemove
/datum/controller/process/npcpool/statProcess()
..()
stat(null, "T [botPool_l.len + botPool_l_non.len] | D [needsDelegate.len] | A [needsAssistant.len + needsHelp_non.len] | U [canBeUsed.len + canBeUsed_non.len]")
/datum/controller/process/npcpool/doWork()
//bot delegation and coordination systems
//General checklist/Tasks for delegating a task or coordinating it (for SNPCs)
// 1. Bot proximity to task target: if too far, delegate, if close, coordinate
// 2. Bot Health/status: check health with bots in local area, if their health is higher, delegate task to them, else coordinate
// 3. Process delegation: if a bot (or bots) has been delegated, assign them to the task.
// 4. Process coordination: if a bot(or bots) has been asked to coordinate, assign them to help.
// 5. Do all assignments: goes through the delegated/coordianted bots and assigns the right variables/tasks to them.
listclearnulls(canBeUsed)
//SNPC handling
for(var/mob/living/carbon/human/interactive/check in botPool_l)
if(!check)
botPool_l -= check
continue
var/checkInRange = view(SNPC_MAX_RANGE_FIND, check)
if(!(locate(check.TARGET) in checkInRange))
needsDelegate |= check
else if(check.IsDeadOrIncap(0))
needsDelegate |= check
else if(check.doing & SNPC_FIGHTING)
needsAssistant |= check
else
canBeUsed |= check
SCHECK
if(needsDelegate.len)
needsDelegate -= pick(needsDelegate) // cheapo way to make sure stuff doesn't pingpong around in the pool forever. delegation runs seperately to each loop so it will work much smoother
for(var/mob/living/carbon/human/interactive/check in needsDelegate)
if(!check)
needsDelegate -= check
continue
if(canBeUsed.len)
var/mob/living/carbon/human/interactive/candidate = pick(canBeUsed)
var/facCount = 0
var/helpProb = 0
for(var/C in check.faction)
for(var/D in candidate.faction)
if(D == C)
helpProb = min(100, helpProb + 25)
facCount++
if(facCount == 1 && helpProb > 0)
helpProb = 100
if(prob(helpProb))
if(candidate.takeDelegate(check))
needsDelegate -= check
canBeUsed -= candidate
candidate.change_eye_color(255, 0, 0)
SCHECK
if(needsAssistant.len)
needsAssistant -= pick(needsAssistant)
for(var/mob/living/carbon/human/interactive/check in needsAssistant)
if(!check)
needsAssistant -= check
continue
if(canBeUsed.len)
var/mob/living/carbon/human/interactive/candidate = pick(canBeUsed)
var/facCount = 0
var/helpProb = 0
for(var/C in check.faction)
for(var/D in candidate.faction)
if(D == C)
helpProb = min(100, helpProb + 25)
facCount++
if(facCount == 1 && helpProb > 0)
helpProb = 100
if(prob(helpProb))
if(candidate.takeDelegate(check, 0))
needsAssistant -= check
canBeUsed -= candidate
candidate.change_eye_color(255, 255, 0)
SCHECK
+3 -3
View File
@@ -363,19 +363,19 @@ SUBSYSTEM_DEF(air)
plmaster.icon = 'icons/effects/tile_effects.dmi'
plmaster.icon_state = "plasma"
plmaster.layer = FLY_LAYER
plmaster.mouse_opacity = 0
plmaster.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
slmaster = new /obj/effect/overlay()
slmaster.icon = 'icons/effects/tile_effects.dmi'
slmaster.icon_state = "sleeping_agent"
slmaster.layer = FLY_LAYER
slmaster.mouse_opacity = 0
slmaster.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
icemaster = new /obj/effect/overlay()
icemaster.icon = 'icons/turf/overlays.dmi'
icemaster.icon_state = "snowfloor"
icemaster.layer = TURF_LAYER + 0.1
icemaster.mouse_opacity = 0
icemaster.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
#undef SSAIR_PIPENETS
#undef SSAIR_ATMOSMACHINERY
+24
View File
@@ -0,0 +1,24 @@
SUBSYSTEM_DEF(npcai)
name = "NPC AI" // Simple AI controller, isolated from the SNPC one (NPCPool).
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
priority = FIRE_PRIORITY_NPC
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/simple_animal_list = list()
/datum/controller/subsystem/npcai/stat_entry()
..("SimAnimals:[simple_animal_list.len]")
/datum/controller/subsystem/npcai/fire(resumed = FALSE)
if(!resumed)
src.simple_animal_list = simple_animal_list.Copy()
for(var/mob/living/simple_animal/M in simple_animal_list)
if(istype(M) && !QDELETED(M))
if(!M.client && M.stat == CONSCIOUS)
M.process_ai()
if(MC_TICK_CHECK)
return
else
simple_animal_list -= M
/datum/controller/subsystem/npcai/Recover()
simple_animal_list = SSnpcai.simple_animal_list
+127
View File
@@ -0,0 +1,127 @@
#define PROCESSING_NPCS 0
#define PROCESSING_DELEGATES 1
#define PROCESSING_ASSISTANTS 2
SUBSYSTEM_DEF(npcpool)
name = "NPC Pool"
flags = SS_POST_FIRE_TIMING|SS_NO_INIT|SS_BACKGROUND
priority = FIRE_PRIORITY_NPC
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
var/list/canBeUsed = list()
var/list/needsDelegate = list()
var/list/needsAssistant = list()
var/list/processing = list()
var/list/currentrun = list()
var/stage
/datum/controller/subsystem/npcpool/stat_entry()
..("NPCS:[processing.len]|D:[needsDelegate.len]|A:[needsAssistant.len]|U:[canBeUsed.len]")
/datum/controller/subsystem/npcpool/proc/stop_processing(mob/living/carbon/human/interactive/I)
processing -= I
currentrun -= I
needsDelegate -= I
canBeUsed -= I
needsAssistant -= I
/datum/controller/subsystem/npcpool/fire(resumed = FALSE)
//bot delegation and coordination systems
//General checklist/Tasks for delegating a task or coordinating it (for SNPCs)
// 1. Bot proximity to task target: if too far, delegate, if close, coordinate
// 2. Bot Health/status: check health with bots in local area, if their health is higher, delegate task to them, else coordinate
// 3. Process delegation: if a bot (or bots) has been delegated, assign them to the task.
// 4. Process coordination: if a bot(or bots) has been asked to coordinate, assign them to help.
// 5. Do all assignments: goes through the delegated/coordianted bots and assigns the right variables/tasks to them.
if (!resumed)
currentrun = processing.Copy()
stage = PROCESSING_NPCS
//cache for sanic speed (lists are references anyways)
var/list/cachecurrentrun = currentrun
var/list/cachecanBeUsed = canBeUsed
if(stage == PROCESSING_NPCS)
while(cachecurrentrun.len)
var/mob/living/carbon/human/interactive/thing = cachecurrentrun[cachecurrentrun.len]
--cachecurrentrun.len
thing.InteractiveProcess()
var/checkInRange = view(SNPC_MAX_RANGE_FIND,thing)
if(thing.IsDeadOrIncap(FALSE) || !(locate(thing.TARGET) in checkInRange))
needsDelegate += thing
else if(thing.doing & SNPC_FIGHTING)
needsAssistant += thing
else
cachecanBeUsed += thing
if (MC_TICK_CHECK)
return
stage = PROCESSING_DELEGATES
cachecurrentrun = needsDelegate //localcache
currentrun = cachecurrentrun
if(stage == PROCESSING_DELEGATES)
while(cachecurrentrun.len && cachecanBeUsed.len)
var/mob/living/carbon/human/interactive/check = cachecurrentrun[cachecurrentrun.len]
var/mob/living/carbon/human/interactive/candidate = cachecanBeUsed[cachecanBeUsed.len]
--cachecurrentrun.len
var/helpProb = 0
var/list/chfac = check.faction
var/list/canfac = candidate.faction
var/facCount = LAZYLEN(chfac) * LAZYLEN(canfac)
for(var/C in chfac)
if(C in canfac)
helpProb = min(100,helpProb + 25)
if(helpProb >= 100)
break
if(facCount == 1 && helpProb)
helpProb = 100
if(prob(helpProb) && candidate.takeDelegate(check))
--cachecanBeUsed.len
candidate.change_eye_color(255, 0, 0)
candidate.update_icons()
if(MC_TICK_CHECK)
return
stage = PROCESSING_ASSISTANTS
cachecurrentrun = needsAssistant //localcache
currentrun = cachecurrentrun
//no need for the stage check
while(cachecurrentrun.len && cachecanBeUsed.len)
var/mob/living/carbon/human/interactive/check = cachecurrentrun[cachecurrentrun.len]
var/mob/living/carbon/human/interactive/candidate = cachecanBeUsed[cachecanBeUsed.len]
--cachecurrentrun.len
var/helpProb = 0
var/list/chfac = check.faction
var/list/canfac = candidate.faction
var/facCount = LAZYLEN(chfac) * LAZYLEN(canfac)
for(var/C in chfac)
if(C in canfac)
helpProb = min(100,helpProb + 25)
if(helpProb >= 100)
break
if(facCount == 1 && helpProb)
helpProb = 100
if(prob(helpProb) && candidate.takeDelegate(check,FALSE))
--cachecanBeUsed.len
candidate.change_eye_color(255, 255, 0)
candidate.update_icons()
if(!cachecurrentrun.len || MC_TICK_CHECK) //don't change SS state if it isn't necessary
return
/datum/controller/subsystem/npcpool/Recover()
processing = SSnpcpool.processing
+212
View File
@@ -0,0 +1,212 @@
SUBSYSTEM_DEF(overlays)
name = "Overlay"
flags = SS_TICKER
wait = 1
priority = FIRE_PRIORITY_OVERLAYS
init_order = INIT_ORDER_OVERLAY
var/list/queue
var/list/stats
var/list/overlay_icon_state_caches
var/list/overlay_icon_cache
/datum/controller/subsystem/overlays/PreInit()
overlay_icon_state_caches = list()
overlay_icon_cache = list()
queue = list()
stats = list()
/datum/controller/subsystem/overlays/Initialize()
initialized = TRUE
fire(mc_check = FALSE)
return ..()
/datum/controller/subsystem/overlays/stat_entry()
..("Ov:[length(queue)]")
/datum/controller/subsystem/overlays/Recover()
overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches
overlay_icon_cache = SSoverlays.overlay_icon_cache
queue = SSoverlays.queue
/datum/controller/subsystem/overlays/fire(resumed = FALSE, mc_check = TRUE)
var/list/queue = src.queue
var/static/count = 0
if(count)
var/c = count
count = 0 //so if we runtime on the Cut, we don't try again.
queue.Cut(1, c + 1)
for(var/thing in queue)
count++
if(thing)
var/atom/A = thing
COMPILE_OVERLAYS(A)
if(mc_check)
if(MC_TICK_CHECK)
break
else
CHECK_TICK
if(count)
queue.Cut(1, count + 1)
count = 0
/proc/iconstate2appearance(icon, iconstate)
var/static/image/stringbro = new()
var/list/icon_states_cache = SSoverlays.overlay_icon_state_caches
var/list/cached_icon = icon_states_cache[icon]
if(cached_icon)
var/cached_appearance = cached_icon["[iconstate]"]
if(cached_appearance)
return cached_appearance
stringbro.icon = icon
stringbro.icon_state = iconstate
if(!cached_icon) //not using the macro to save an associated lookup
cached_icon = list()
icon_states_cache[icon] = cached_icon
var/cached_appearance = stringbro.appearance
cached_icon["[iconstate]"] = cached_appearance
return cached_appearance
/proc/icon2appearance(icon)
var/static/image/iconbro = new()
var/list/icon_cache = SSoverlays.overlay_icon_cache
. = icon_cache[icon]
if(!.)
iconbro.icon = icon
. = iconbro.appearance
icon_cache[icon] = .
/atom/proc/build_appearance_list(old_overlays)
var/static/image/appearance_bro = new()
var/list/new_overlays = list()
if(!islist(old_overlays))
old_overlays = list(old_overlays)
for(var/overlay in old_overlays)
if(!overlay)
continue
if(istext(overlay))
new_overlays += iconstate2appearance(icon, overlay)
else if(isicon(overlay))
new_overlays += icon2appearance(overlay)
else
if(isloc(overlay))
var/atom/A = overlay
if(A.flags_2 & OVERLAY_QUEUED_2)
COMPILE_OVERLAYS(A)
appearance_bro.appearance = overlay //this works for images and atoms too!
if(!ispath(overlay))
var/image/I = overlay
appearance_bro.dir = I.dir
new_overlays += appearance_bro.appearance
return new_overlays
#define NOT_QUEUED_ALREADY (!(flags_2 & OVERLAY_QUEUED_2))
#define QUEUE_FOR_COMPILE flags_2 |= OVERLAY_QUEUED_2; SSoverlays.queue += src;
/atom/proc/cut_overlays(priority = FALSE)
LAZYINITLIST(priority_overlays)
LAZYINITLIST(remove_overlays)
LAZYINITLIST(add_overlays)
remove_overlays = overlays.Copy()
add_overlays.Cut()
if(priority)
priority_overlays.Cut()
//If not already queued for work and there are overlays to remove
if(NOT_QUEUED_ALREADY && remove_overlays.len)
QUEUE_FOR_COMPILE
/atom/proc/cut_overlay(list/overlays, priority)
if(!overlays)
return
overlays = build_appearance_list(overlays)
LAZYINITLIST(add_overlays) //always initialized after this point
LAZYINITLIST(priority_overlays)
LAZYINITLIST(remove_overlays)
var/a_len = add_overlays.len
var/r_len = remove_overlays.len
var/p_len = priority_overlays.len
remove_overlays += overlays
add_overlays -= overlays
if(priority)
var/list/cached_priority = priority_overlays
LAZYREMOVE(cached_priority, overlays)
var/fa_len = add_overlays.len
var/fr_len = remove_overlays.len
var/fp_len = priority_overlays.len
//If not already queued and there is work to be done
if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len || fp_len != p_len))
QUEUE_FOR_COMPILE
/atom/proc/add_overlay(list/overlays, priority = FALSE)
if(!overlays)
return
overlays = build_appearance_list(overlays)
LAZYINITLIST(add_overlays) //always initialized after this point
LAZYINITLIST(priority_overlays)
var/a_len = add_overlays.len
var/p_len = priority_overlays.len
if(priority)
priority_overlays += overlays //or in the image. Can we use [image] = image?
var/fp_len = priority_overlays.len
if(NOT_QUEUED_ALREADY && fp_len != p_len)
QUEUE_FOR_COMPILE
else
add_overlays += overlays
var/fa_len = add_overlays.len
if(NOT_QUEUED_ALREADY && fa_len != a_len)
QUEUE_FOR_COMPILE
/atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom
if(!other)
if(cut_old)
cut_overlays()
return
var/list/cached_other = other.overlays.Copy()
if(cached_other)
if(cut_old || !LAZYLEN(overlays))
remove_overlays = overlays
add_overlays = cached_other
if(NOT_QUEUED_ALREADY)
QUEUE_FOR_COMPILE
else if(cut_old)
cut_overlays()
#undef NOT_QUEUED_ALREADY
#undef QUEUE_FOR_COMPILE
//TODO: Better solution for these?
/image/proc/add_overlay(x)
overlays |= x
/image/proc/cut_overlay(x)
overlays -= x
/image/proc/cut_overlays(x)
overlays.Cut()
/image/proc/copy_overlays(atom/other, cut_old)
if(!other)
if(cut_old)
cut_overlays()
return
var/list/cached_other = other.overlays.Copy()
if(cached_other)
if(cut_old || !overlays.len)
overlays = cached_other
else
overlays |= cached_other
else if(cut_old)
cut_overlays()
+1 -1
View File
@@ -35,7 +35,7 @@ SUBSYSTEM_DEF(tickets)
message_adminTicket("<span class='adminticket'>Tickets [report] have been open for over [ADMIN_TICKET_TIMEOUT / 600] minutes. Changing status to stale.</span>")
/datum/controller/subsystem/tickets/stat_entry()
..("Tickets: [allTickets.len]")
..("Tickets: [LAZYLEN(allTickets)]")
/datum/controller/subsystem/tickets/proc/checkStaleness()
var/stales = list()
+108 -102
View File
@@ -1,5 +1,5 @@
#define BUCKET_LEN (world.fps*1*60) //how many ticks should we keep in the bucket. (1 minutes worth)
#define BUCKET_POS(timer) ((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) % BUCKET_LEN) + 1)
#define BUCKET_POS(timer) ((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) % BUCKET_LEN)||BUCKET_LEN)
#define TIMER_MAX (world.time + TICKS2DS(min(BUCKET_LEN-(SStimer.practical_offset-DS2TICKS(world.time - SStimer.head_offset))-1, BUCKET_LEN-1)))
#define TIMER_ID_MAX (2**24) //max float with integer precision
@@ -71,6 +71,7 @@ SUBSYSTEM_DEF(timer)
for(var/I in second_queue)
log_world(get_timer_debug_string(I))
var/cut_start_index = 1
var/next_clienttime_timer_index = 0
var/len = length(clienttime_timers)
@@ -90,11 +91,17 @@ SUBSYSTEM_DEF(timer)
ctime_timer.spent = REALTIMEOFDAY
callBack.InvokeAsync()
qdel(ctime_timer)
if(ctime_timer.flags & TIMER_LOOP)
ctime_timer.spent = 0
clienttime_timers.Insert(ctime_timer, 1)
cut_start_index++
else
qdel(ctime_timer)
if(next_clienttime_timer_index)
clienttime_timers.Cut(1,next_clienttime_timer_index+1)
clienttime_timers.Cut(cut_start_index,next_clienttime_timer_index+1)
if(MC_TICK_CHECK)
return
@@ -197,8 +204,22 @@ SUBSYSTEM_DEF(timer)
bucket_count -= length(spent)
for(var/spent_timer in spent)
qdel(spent_timer)
for(var/i in spent)
var/datum/timedevent/qtimer = i
if(QDELETED(qtimer))
bucket_count++
continue
if(!(qtimer.flags & TIMER_LOOP))
qdel(qtimer)
else
bucket_count++
qtimer.spent = 0
qtimer.bucketEject()
if(qtimer.flags & TIMER_CLIENT_TIME)
qtimer.timeToRun = REALTIMEOFDAY + qtimer.wait
else
qtimer.timeToRun = world.time + qtimer.wait
qtimer.bucketJoin()
spent.len = 0
@@ -294,6 +315,7 @@ SUBSYSTEM_DEF(timer)
var/id
var/datum/callback/callBack
var/timeToRun
var/wait
var/hash
var/list/flags
var/spent = 0 //time we ran the timer.
@@ -302,14 +324,19 @@ SUBSYSTEM_DEF(timer)
var/datum/timedevent/next
var/datum/timedevent/prev
/datum/timedevent/New(datum/callback/callBack, timeToRun, flags, hash)
/datum/timedevent/New(datum/callback/callBack, wait, flags, hash)
var/static/nextid = 1
id = TIMER_ID_NULL
src.callBack = callBack
src.timeToRun = timeToRun
src.wait = wait
src.flags = flags
src.hash = hash
if(flags & TIMER_CLIENT_TIME)
timeToRun = REALTIMEOFDAY + wait
else
timeToRun = world.time + wait
if(flags & TIMER_UNIQUE)
SStimer.hashes[hash] = src
@@ -321,68 +348,15 @@ SUBSYSTEM_DEF(timer)
nextid++
SStimer.timer_id_dict[id] = src
name = "Timer: [id] (\ref[src]), TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
name = "Timer: [id] (\ref[src]), TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT", "TIMER_LOOP")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
if((timeToRun < world.time || timeToRun < SStimer.head_offset) && !(flags & TIMER_CLIENT_TIME))
CRASH("Invalid timer state: Timer created that would require a backtrack to run (addtimer would never let this happen): [SStimer.get_timer_debug_string(src)]")
if(callBack.object != GLOBAL_PROC)
if(callBack.object != GLOBAL_PROC && !QDESTROYING(callBack.object))
LAZYADD(callBack.object.active_timers, src)
var/list/L
if(flags & TIMER_CLIENT_TIME)
L = SStimer.clienttime_timers
else if(timeToRun >= TIMER_MAX)
L = SStimer.second_queue
if(L)
//binary search sorted insert
var/cttl = length(L)
if(cttl)
var/left = 1
var/right = cttl
var/mid = (left+right) >> 1 //rounded divide by two for hedgehogs
var/datum/timedevent/item
while(left < right)
item = L[mid]
if(item.timeToRun <= timeToRun)
left = mid+1
else
right = mid
mid = (left+right) >> 1
item = L[mid]
mid = item.timeToRun > timeToRun ? mid : mid+1
L.Insert(mid, src)
else
L += src
return
//get the list of buckets
var/list/bucket_list = SStimer.bucket_list
//calculate our place in the bucket list
var/bucket_pos = BUCKET_POS(src)
//get the bucket for our tick
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
SStimer.bucket_count++
//empty bucket, we will just add ourselves
if(!bucket_head)
bucket_list[bucket_pos] = src
return
//other wise, lets do a simplified linked list add.
if(!bucket_head.prev)
bucket_head.prev = bucket_head
next = bucket_head
prev = bucket_head.prev
next.prev = src
prev.next = src
bucketJoin()
/datum/timedevent/Destroy()
..()
@@ -406,31 +380,7 @@ SUBSYSTEM_DEF(timer)
if(!spent)
spent = world.time
var/bucketpos = BUCKET_POS(src)
var/datum/timedevent/buckethead
var/list/bucket_list = SStimer.bucket_list
if(bucketpos > 0)
buckethead = bucket_list[bucketpos]
if(buckethead == src)
bucket_list[bucketpos] = next
SStimer.bucket_count--
else if(timeToRun < TIMER_MAX || next || prev)
SStimer.bucket_count--
else
var/l = length(SStimer.second_queue)
SStimer.second_queue -= src
if(l == length(SStimer.second_queue))
SStimer.bucket_count--
if(prev == next && next)
next.prev = null
prev.next = null
else
if(prev)
prev.next = next
if(next)
next.prev = prev
bucketEject()
else
if(prev && prev.next == src)
prev.next = next
@@ -440,6 +390,66 @@ SUBSYSTEM_DEF(timer)
prev = null
return QDEL_HINT_IWILLGC
/datum/timedevent/proc/bucketEject()
var/bucketpos = BUCKET_POS(src)
var/list/bucket_list = SStimer.bucket_list
var/list/second_queue = SStimer.second_queue
var/datum/timedevent/buckethead
if(bucketpos > 0)
buckethead = bucket_list[bucketpos]
if(buckethead == src)
bucket_list[bucketpos] = next
SStimer.bucket_count--
else if(timeToRun < TIMER_MAX || next || prev)
SStimer.bucket_count--
else
var/l = length(second_queue)
second_queue -= src
if(l == length(second_queue))
SStimer.bucket_count--
if(prev != next)
prev.next = next
next.prev = prev
else
if(prev)
prev.next = null
if(next)
next.prev = null
prev = next = null
/datum/timedevent/proc/bucketJoin()
var/list/L
if(flags & TIMER_CLIENT_TIME)
L = SStimer.clienttime_timers
else if(timeToRun >= TIMER_MAX)
L = SStimer.second_queue
if(L)
BINARY_INSERT(src, L, datum/timedevent, timeToRun)
return
//get the list of buckets
var/list/bucket_list = SStimer.bucket_list
//calculate our place in the bucket list
var/bucket_pos = BUCKET_POS(src)
//get the bucket for our tick
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
SStimer.bucket_count++
//empty bucket, we will just add ourselves
if(!bucket_head)
bucket_list[bucket_pos] = src
return
//other wise, lets do a simplified linked list add.
if(!bucket_head.prev)
bucket_head.prev = bucket_head
next = bucket_head
prev = bucket_head.prev
next.prev = src
prev.next = src
/datum/timedevent/proc/getcallingtype()
. = "ERROR"
if(callBack.object == GLOBAL_PROC)
@@ -452,13 +462,12 @@ SUBSYSTEM_DEF(timer)
CRASH("addtimer called without a callback")
if(wait < 0)
stack_trace("addtimer called with a negative wait. Converting to 0")
stack_trace("addtimer called with a negative wait. Converting to [world.tick_lag]")
//alot of things add short timers on themselves in their destroy, we ignore those cases
if(wait >= 1 && callback && callback.object && callback.object != GLOBAL_PROC && QDELETED(callback.object))
stack_trace("addtimer called with a callback assigned to a qdeleted object")
if(callback.object != GLOBAL_PROC && QDELETED(callback.object) && !QDESTROYING(callback.object))
stack_trace("addtimer called with a callback assigned to a qdeleted object. In the future such timers will not be supported and may refuse to run or run with a 0 wait")
wait = max(wait, 0)
wait = max(CEILING(wait, world.tick_lag), world.tick_lag)
if(wait >= INFINITY)
CRASH("Attempted to create timer with INFINITY delay")
@@ -468,9 +477,9 @@ SUBSYSTEM_DEF(timer)
if(flags & TIMER_UNIQUE)
var/list/hashlist
if(flags & TIMER_NO_HASH_WAIT)
hashlist = list(callback.object, "([callback.object.UID()])", callback.delegate, flags & TIMER_CLIENT_TIME)
hashlist = list(callback.object, "(\ref[callback.object])", callback.delegate, flags & TIMER_CLIENT_TIME)
else
hashlist = list(callback.object, "([callback.object.UID()])", callback.delegate, wait, flags & TIMER_CLIENT_TIME)
hashlist = list(callback.object, "(\ref[callback.object])", callback.delegate, wait, flags & TIMER_CLIENT_TIME)
hashlist += callback.arguments
hash = hashlist.Join("|||||||")
@@ -486,13 +495,10 @@ SUBSYSTEM_DEF(timer)
if(hash_timer.flags & TIMER_STOPPABLE)
. = hash_timer.id
return
else if(flags & TIMER_OVERRIDE)
stack_trace("TIMER_OVERRIDE used without TIMER_UNIQUE")
var/timeToRun = world.time + wait
if(flags & TIMER_CLIENT_TIME)
timeToRun = REALTIMEOFDAY + wait
var/datum/timedevent/timer = new(callback, timeToRun, flags, hash)
var/datum/timedevent/timer = new(callback, wait, flags, hash)
return timer.id
/proc/deltimer(id)
@@ -515,4 +521,4 @@ SUBSYSTEM_DEF(timer)
#undef BUCKET_LEN
#undef BUCKET_POS
#undef TIMER_MAX
#undef TIMER_ID_MAX
#undef TIMER_ID_MAX
+1 -1
View File
@@ -85,7 +85,7 @@
debug_variables(SSmobs)
feedback_add_details("admin_verb","DMob")
if("NPC AI")
debug_variables(npcai_master)
debug_variables(SSnpcai)
feedback_add_details("admin_verb","DNPCAI")
if("Shuttle")
debug_variables(SSshuttle)
+1 -1
View File
@@ -111,7 +111,7 @@
X.pixel_y = Pixel_y
/obj/effect/ebeam
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
anchored = 1
var/datum/beam/owner
+31
View File
@@ -0,0 +1,31 @@
/datum/click_intercept
var/client/holder = null
var/list/obj/screen/buttons = list()
/datum/click_intercept/New(client/C)
create_buttons()
enter(C)
return ..()
/datum/click_intercept/Destroy()
holder.screen -= buttons
holder.click_intercept = null
holder.show_popup_menus = TRUE
holder = null
QDEL_LIST(buttons)
return ..()
/datum/click_intercept/proc/enter(client/C)
holder = C
holder.click_intercept = src
holder.show_popup_menus = FALSE
holder.screen += buttons
/datum/click_intercept/proc/quit()
qdel(src)
/datum/click_intercept/proc/create_buttons()
return
/datum/click_intercept/proc/InterceptClickOn(user,params,atom/object)
return
+1 -1
View File
@@ -31,7 +31,7 @@
/datum/proc/vv_get_var(var_name)
switch(var_name)
if("attack_log")
if("attack_log", "debug_log")
return debug_variable(var_name, vars[var_name], 0, src, sanitize = FALSE)
if("vars")
return debug_variable(var_name, list(), 0, src)
+1 -2
View File
@@ -24,7 +24,6 @@
to_chat(affected_mob, "<span class='danger'>Your stomach stings painfully.</span>")
if(prob(20))
affected_mob.adjustToxLoss(2)
affected_mob.updatehealth()
if(4)
if(prob(10))
affected_mob.visible_message("<span class='danger'>[affected_mob] buzzes.</span>", \
@@ -37,4 +36,4 @@
new /mob/living/simple_animal/hostile/poison/bees(affected_mob.loc)
//if(5)
//Plus if you die, you explode into bees
return
return
-3
View File
@@ -25,7 +25,6 @@
to_chat(affected_mob, "<span class='danger'>You don't feel like yourself.</span>")
if(prob(5))
affected_mob.adjustBrainLoss(1)
affected_mob.updatehealth()
if(3)
if(prob(2))
affected_mob.emote("stare")
@@ -33,7 +32,6 @@
affected_mob.emote("drool")
if(prob(10) && affected_mob.getBrainLoss()<=98)//shouldn't retard you to death now
affected_mob.adjustBrainLoss(2)
affected_mob.updatehealth()
if(prob(2))
to_chat(affected_mob, "<span class='danger'>Your try to remember something important...but can't.</span>")
@@ -44,7 +42,6 @@
affected_mob.emote("drool")
if(prob(15) && affected_mob.getBrainLoss()<=98) //shouldn't retard you to death now
affected_mob.adjustBrainLoss(3)
affected_mob.updatehealth()
if(prob(2))
to_chat(affected_mob, "<span class='danger'>Strange buzzing fills your head, removing all thoughts.</span>")
if(prob(3))
+1 -2
View File
@@ -41,7 +41,6 @@
to_chat(affected_mob, "<span class='danger'>Your stomach hurts.</span>")
if(prob(20))
affected_mob.adjustToxLoss(2)
affected_mob.updatehealth()
if(4)
if(!transformed && !carrier)
//Save original dna for when the disease is cured.
@@ -69,4 +68,4 @@
affected_mob.domutcheck()
to_chat(affected_mob, "<span class='notice'>You feel more like yourself.</span>")
return ..()
return ..()
-2
View File
@@ -31,7 +31,6 @@
to_chat(affected_mob, "<span class='danger'>Your stomach hurts.</span>")
if(prob(20))
affected_mob.adjustToxLoss(1)
affected_mob.updatehealth()
if(3)
if(affected_mob.lying && prob(15))
@@ -50,5 +49,4 @@
to_chat(affected_mob, "<span class='danger'>Your stomach hurts.</span>")
if(prob(20))
affected_mob.adjustToxLoss(1)
affected_mob.updatehealth()
return
+1 -3
View File
@@ -18,7 +18,6 @@
if(2)
if(prob(45))
affected_mob.adjustToxLoss(5)
affected_mob.updatehealth()
if(prob(1))
affected_mob.emote("sneeze")
if(3)
@@ -32,7 +31,6 @@
if(prob(10))
affected_mob.emote("cough")
affected_mob.adjustToxLoss(5)
affected_mob.updatehealth()
if(5)
to_chat(affected_mob, "<span class='danger'>Your body feels as if it's trying to rip itself open...</span>")
if(prob(50))
@@ -50,4 +48,4 @@
cure_chance = 10
agent = "gibbis"
spread_flags = NON_CONTAGIOUS
disease_flags = CURABLE
disease_flags = CURABLE
+1 -3
View File
@@ -19,7 +19,6 @@
if(2)
if(prob(45))
affected_mob.adjustToxLoss(5)
affected_mob.updatehealth()
if(prob(1))
to_chat(affected_mob, "<span class='danger'>You feel strange...</span>")
if(3)
@@ -35,8 +34,7 @@
to_chat(affected_mob, "<span class='danger'>You feel a burning beat inside...</span>")
if(prob(20))
affected_mob.adjustToxLoss(5)
affected_mob.updatehealth()
if(5)
to_chat(affected_mob, "<span class='danger'>Your body is unable to contain the Rhumba Beat...</span>")
if(prob(50))
affected_mob.gib()
affected_mob.gib()
+2 -2
View File
@@ -29,7 +29,7 @@
for(var/I in callees)
var/obj/machinery/hologram/holopad/H = I
if(!QDELETED(H) && !(H.stat & NOPOWER))
if(!QDELETED(H) && !(H.stat & NOPOWER) && H.anchored)
dialed_holopads += H
var/area/area = get_area(H)
LAZYADD(H.holo_calls, src)
@@ -159,7 +159,7 @@
/datum/holocall/proc/Check()
for(var/I in dialed_holopads)
var/obj/machinery/hologram/holopad/H = I
if((H.stat & NOPOWER))
if((H.stat & NOPOWER) || !H.anchored)
ConnectionFailure(H)
if(QDELETED(src))
+233 -274
View File
@@ -47,7 +47,7 @@
var/role_alt_title
var/datum/job/assigned_job
var/list/kills=list()
var/list/kills = list()
var/list/datum/objective/objectives = list()
var/list/datum/objective/special_verbs = list()
@@ -78,9 +78,8 @@
//zealot_master is a reference to the mob that converted them into a zealot (for ease of investigation and such)
var/mob/living/carbon/human/zealot_master = null
/datum/mind/New(var/key)
src.key = key
/datum/mind/New(new_key)
key = new_key
/datum/mind/Destroy()
ticker.minds -= src
@@ -122,19 +121,15 @@
/datum/mind/proc/wipe_memory()
memory = null
/datum/mind/proc/show_memory(mob/recipient, window=1)
/datum/mind/proc/show_memory(mob/recipient, window = 1)
if(!recipient)
recipient = current
var/output = "<B>[current.real_name]'s Memories:</B><HR>"
output += memory
if(objectives.len)
output += "<HR><B>Objectives:</B>"
var/obj_count = 1
for(var/datum/objective/objective in objectives)
output += "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
obj_count++
output += "<HR><B>Objectives:</B><BR>"
output += gen_objective_text()
if(job_objectives.len)
output += "<HR><B>Job Objectives:</B><UL>"
@@ -145,17 +140,213 @@
obj_count++
output += "</UL>"
if(window)
recipient << browse(output,"window=memory")
recipient << browse(output, "window=memory")
else
to_chat(recipient, "<i>[output]</i>")
/datum/mind/proc/gen_objective_text(admin = FALSE)
. = ""
var/obj_count = 1
for(var/datum/objective/objective in objectives)
. += "<b>Objective #[obj_count]</b>: [objective.explanation_text]"
if(admin)
. += " <a href='?src=[UID()];obj_edit=\ref[objective]'>Edit</a> " // Edit
. += "<a href='?src=[UID()];obj_delete=\ref[objective]'>Delete</a> " // Delete
. += "<a href='?src=[UID()];obj_completed=\ref[objective]'>" // Mark Completed
. += "<font color=[objective.completed ? "green" : "red"]>Toggle Completion</font>"
. += "</a>"
. += "<br>"
obj_count++
/datum/mind/proc/_memory_edit_header(gamemode, list/alt)
. = gamemode
if(ticker.mode.config_tag == gamemode || (LAZYLEN(alt) && (ticker.mode.config_tag in alt)))
. = uppertext(.)
. = "<i><b>[.]</b></i>: "
/datum/mind/proc/_memory_edit_role_enabled(role)
. = "|Disabled in Prefs"
if(current && current.client && (role in current.client.prefs.be_special))
. = "|Enabled in Prefs"
/datum/mind/proc/memory_edit_implant(mob/living/carbon/human/H)
if(ismindshielded(H))
. = "Mindshield Implant:<a href='?src=[UID()];implant=remove'>Remove</a>|<b><font color='green'>Implanted</font></b></br>"
else
. = "Mindshield Implant:<b>No Implant</b>|<a href='?src=[UID()];implant=add'>Implant [H.p_them()]!</a></br>"
/datum/mind/proc/memory_edit_revolution(mob/living/carbon/human/H)
. = _memory_edit_header("revolution")
if(ismindshielded(H))
. += "<b>NO</b>|headrev|rev"
else if(src in ticker.mode.head_revolutionaries)
. += "<a href='?src=[UID()];revolution=clear'>no</a>|<b><font color='red'>HEADREV</font></b>|<a href='?src=[UID()];revolution=rev'>rev</a>"
. += "<br>Flash: <a href='?src=[UID()];revolution=flash'>give</a>"
var/list/L = current.get_contents()
var/obj/item/flash/flash = locate() in L
if(flash)
if(!flash.broken)
. += "|<a href='?src=[UID()];revolution=takeflash'>take</a>."
else
. += "|<a href='?src=[UID()];revolution=takeflash'>take</a>|<a href='?src=[UID()];revolution=repairflash'>repair</a>."
else
. += "."
. += " <a href='?src=[UID()];revolution=reequip'>Reequip</a> (gives traitor uplink)."
if(objectives.len==0)
. += "<br>Objectives are empty! <a href='?src=[UID()];revolution=autoobjectives'>Set to kill all heads</a>."
else if(src in ticker.mode.revolutionaries)
. += "<a href='?src=[UID()];revolution=clear'>no</a>|<a href='?src=[UID()];revolution=headrev'>headrev</a>|<b><font color='red'>REV</font></b>"
else
. += "<b>NO</b>|<a href='?src=[UID()];revolution=headrev'>headrev</a>|<a href='?src=[UID()];revolution=rev'>rev</a>"
. += _memory_edit_role_enabled(ROLE_REV)
/datum/mind/proc/memory_edit_cult(mob/living/carbon/human/H)
. = _memory_edit_header("cult")
if(ismindshielded(H))
. += "<B>NO</B>|cultist"
else if(src in ticker.mode.cult)
. += "<a href='?src=[UID()];cult=clear'>no</a>|<b><font color='red'>CULTIST</font></b>"
. += "<br>Give <a href='?src=[UID()];cult=tome'>tome</a>|<a href='?src=[UID()];cult=equip'>equip</a>."
else
. += "<b>NO</b>|<a href='?src=[UID()];cult=cultist'>cultist</a>"
. += _memory_edit_role_enabled(ROLE_CULTIST)
/datum/mind/proc/memory_edit_wizard(mob/living/carbon/human/H)
. = _memory_edit_header("wizard")
if(src in ticker.mode.wizards)
. += "<b><font color='red'>WIZARD</font></b>|<a href='?src=[UID()];wizard=clear'>no</a>"
. += "<br><a href='?src=[UID()];wizard=lair'>To lair</a>, <a href='?src=[UID()];common=undress'>undress</a>, <a href='?src=[UID()];wizard=dressup'>dress up</a>, <a href='?src=[UID()];wizard=name'>let choose name</a>."
if(objectives.len==0)
. += "<br>Objectives are empty! <a href='?src=[UID()];wizard=autoobjectives'>Randomize!</a>"
else
. += "<a href='?src=[UID()];wizard=wizard'>wizard</a>|<b>NO</b>"
. += _memory_edit_role_enabled(ROLE_WIZARD)
/datum/mind/proc/memory_edit_changeling(mob/living/carbon/human/H)
. = _memory_edit_header("changeling", list("traitorchan"))
if(src in ticker.mode.changelings)
. += "<b><font color='red'>CHANGELING</font></b>|<a href='?src=[UID()];changeling=clear'>no</a>"
if(objectives.len==0)
. += "<br>Objectives are empty! <a href='?src=[UID()];changeling=autoobjectives'>Randomize!</a>"
if(changeling && changeling.absorbed_dna.len && (current.real_name != changeling.absorbed_dna[1]))
. += "<br><a href='?src=[UID()];changeling=initialdna'>Transform to initial appearance.</a>"
else
. += "<a href='?src=[UID()];changeling=changeling'>changeling</a>|<b>NO</b>"
. += _memory_edit_role_enabled(ROLE_CHANGELING)
/datum/mind/proc/memory_edit_vampire(mob/living/carbon/human/H)
. = _memory_edit_header("vampire", list("traitorvamp"))
if(src in ticker.mode.vampires)
. += "<b><font color='red'>VAMPIRE</font></b>|<a href='?src=[UID()];vampire=clear'>no</a>"
if(objectives.len==0)
. += "<br>Objectives are empty! <a href='?src=[UID()];vampire=autoobjectives'>Randomize!</a>"
else
. += "<a href='?src=[UID()];vampire=vampire'>vampire</a>|<b>NO</b>"
. += _memory_edit_role_enabled(ROLE_VAMPIRE)
/** Enthralled ***/
. += "<br><b><i>enthralled</i></b>: "
if(src in ticker.mode.vampire_enthralled)
. += "<b><font color='red'>THRALL</font></b>|<a href='?src=[UID()];vampthrall=clear'>no</a>"
else
. += "thrall|<b>NO</b>"
/datum/mind/proc/memory_edit_nuclear(mob/living/carbon/human/H)
. = _memory_edit_header("nuclear")
if(src in ticker.mode.syndicates)
. += "<b><font color='red'>OPERATIVE</b></font>|<a href='?src=[UID()];nuclear=clear'>no</a>"
. += "<br><a href='?src=[UID()];nuclear=lair'>To shuttle</a>, <a href='?src=[UID()];common=undress'>undress</a>, <a href='?src=[UID()];nuclear=dressup'>dress up</a>."
var/code
for(var/obj/machinery/nuclearbomb/bombue in machines)
if(length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN")
code = bombue.r_code
break
if(code)
. += " Code is [code]. <a href='?src=[UID()];nuclear=tellcode'>tell the code.</a>"
else
. += "<a href='?src=[UID()];nuclear=nuclear'>operative</a>|<b>NO</b>"
. += _memory_edit_role_enabled(ROLE_OPERATIVE)
/datum/mind/proc/memory_edit_shadowling(mob/living/carbon/human/H)
. = _memory_edit_header("shadowling")
if(src in ticker.mode.shadows)
. += "<b><font color='red'>SHADOWLING</font></b>|thrall|<a href='?src=[UID()];shadowling=clear'>no</a>"
else if(src in ticker.mode.shadowling_thralls)
. += "Shadowling|<b><font color='red'>THRALL</font></b>|<a href='?src=[UID()];shadowling=clear'>no</a>"
else
. += "<a href='?src=[UID()];shadowling=shadowling'>shadowling</a>|<a href='?src=[UID()];shadowling=thrall'>thrall</a>|<b>NO</b>"
. += _memory_edit_role_enabled(ROLE_SHADOWLING)
/datum/mind/proc/memory_edit_abductor(mob/living/carbon/human/H)
. = _memory_edit_header("abductor")
if(src in ticker.mode.abductors)
. += "<b><font color='red'>ABDUCTOR</font></b>|<a href='?src=[UID()];abductor=clear'>no</a>"
. += "|<a href='?src=[UID()];common=undress'>undress</a>|<a href='?src=[UID()];abductor=equip'>equip</a>"
else
. += "<a href='?src=[UID()];abductor=abductor'>abductor</a>|<b>NO</b>"
. += _memory_edit_role_enabled(ROLE_ABDUCTOR)
/datum/mind/proc/memory_edit_traitor()
. = _memory_edit_header("traitor", list("traitorchan", "traitorvamp"))
if(src in ticker.mode.traitors)
. += "<b><font color='red'>TRAITOR</font></b>|<a href='?src=[UID()];traitor=clear'>no</a>"
if(objectives.len==0)
. += "<br>Objectives are empty! <a href='?src=[UID()];traitor=autoobjectives'>Randomize</a>!"
else
. += "<a href='?src=[UID()];traitor=traitor'>traitor</a>|<b>NO</b>"
. += _memory_edit_role_enabled(ROLE_TRAITOR)
/datum/mind/proc/memory_edit_silicon()
. = "<i><b>Silicon</b></i>: "
var/mob/living/silicon/robot/robot = current
if(istype(robot) && robot.emagged)
. += "<br>Cyborg: <b><font color='red'>Is emagged!</font></b> <a href='?src=[UID()];silicon=unemag'>Unemag!</a><br>0th law: [robot.laws.zeroth_law]"
var/mob/living/silicon/ai/ai = current
if(istype(ai) && ai.connected_robots.len)
var/n_e_robots = 0
for(var/mob/living/silicon/robot/R in ai.connected_robots)
if(R.emagged)
n_e_robots++
. += "<br>[n_e_robots] of [ai.connected_robots.len] slaved cyborgs are emagged. <a href='?src=[UID()];silicon=unemagcyborgs'>Unemag</a>"
/datum/mind/proc/memory_edit_uplink()
. = ""
if(ishuman(current) && ((src in ticker.mode.head_revolutionaries) || \
(src in ticker.mode.traitors) || \
(src in ticker.mode.syndicates)))
. = "Uplink: <a href='?src=[UID()];common=uplink'>give</a>"
var/obj/item/uplink/hidden/suplink = find_syndicate_uplink()
var/crystals
if(suplink)
crystals = suplink.uses
if(suplink)
. += "|<a href='?src=[UID()];common=takeuplink'>take</a>"
if(usr.client.holder.rights & (R_SERVER|R_EVENT))
. += ", <a href='?src=[UID()];common=crystals'>[crystals]</a> crystals"
else
. += ", [crystals] crystals"
. += "." //hiel grammar
// ^ whoever left this comment is literally a grammar nazi. stalin better. in russia grammar correct you.
/datum/mind/proc/edit_memory()
if(!ticker || !ticker.mode)
alert("Not before round-start!", "Alert")
return
var/out = "<B>[name]</B>[(current&&(current.real_name!=name))?" (as [current.real_name])":""]<br>"
out += "Mind currently owned by key: [key] [active?"(synced)":"(not synced)"]<br>"
var/out = "<B>[name]</B>[(current && (current.real_name != name))?" (as [current.real_name])" : ""]<br>"
out += "Mind currently owned by key: [key] [active ? "(synced)" : "(not synced)"]<br>"
out += "Assigned role: [assigned_role]. <a href='?src=[UID()];role_edit=1'>Edit</a><br>"
out += "Factions and special roles:<br>"
@@ -169,284 +360,60 @@
"nuclear",
"traitor", // "traitorchan",
)
var/text = ""
var/mob/living/carbon/human/H = current
if(ishuman(current))
/** Impanted**/
if(ismindshielded(H))
text = "Mindshield Implant:<a href='?src=[UID()];implant=remove'>Remove</a>|<b><font color='green'>Implanted</font></b></br>"
else
text = "Mindshield Implant:<b>No Implant</b>|<a href='?src=[UID()];implant=add'>Implant [H.p_them()]!</a></br>"
sections["implant"] = text
sections["implant"] = memory_edit_implant(H)
/** REVOLUTION ***/
text = "revolution"
if(ticker.mode.config_tag=="revolution")
text += uppertext(text)
text = "<i><b>[text]</b></i>: "
if(ismindshielded(H))
text += "<b>NO</b>|headrev|rev"
else if(src in ticker.mode.head_revolutionaries)
text += "<a href='?src=[UID()];revolution=clear'>no</a>|<b><font color='red'>HEADREV</font></b>|<a href='?src=[UID()];revolution=rev'>rev</a>"
text += "<br>Flash: <a href='?src=[UID()];revolution=flash'>give</a>"
var/list/L = current.get_contents()
var/obj/item/flash/flash = locate() in L
if(flash)
if(!flash.broken)
text += "|<a href='?src=[UID()];revolution=takeflash'>take</a>."
else
text += "|<a href='?src=[UID()];revolution=takeflash'>take</a>|<a href='?src=[UID()];revolution=repairflash'>repair</a>."
else
text += "."
text += " <a href='?src=[UID()];revolution=reequip'>Reequip</a> (gives traitor uplink)."
if(objectives.len==0)
text += "<br>Objectives are empty! <a href='?src=[UID()];revolution=autoobjectives'>Set to kill all heads</a>."
else if(src in ticker.mode.revolutionaries)
text += "<a href='?src=[UID()];revolution=clear'>no</a>|<a href='?src=[UID()];revolution=headrev'>headrev</a>|<b><font color='red'>REV</font></b>"
else
text += "<b>NO</b>|<a href='?src=[UID()];revolution=headrev'>headrev</a>|<a href='?src=[UID()];revolution=rev'>rev</a>"
if(current && current.client && (ROLE_REV in current.client.prefs.be_special))
text += "|Enabled in Prefs"
else
text += "|Disabled in Prefs"
sections["revolution"] = text
sections["revolution"] = memory_edit_revolution(H)
/** CULT ***/
text = "cult"
if(ticker.mode.config_tag=="cult")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(ismindshielded(H))
text += "<B>NO</B>|cultist"
else if(src in ticker.mode.cult)
text += "<a href='?src=[UID()];cult=clear'>no</a>|<b><font color='red'>CULTIST</font></b>"
text += "<br>Give <a href='?src=[UID()];cult=tome'>tome</a>|<a href='?src=[UID()];cult=equip'>equip</a>."
/*
if(objectives.len==0)
text += "<br>Objectives are empty! Set to sacrifice and <a href='?src=[UID()];cult=escape'>escape</a> or <a href='?src=[UID()];cult=summon'>summon</a>."
*/
else
text += "<b>NO</b>|<a href='?src=[UID()];cult=cultist'>cultist</a>"
if(current && current.client && (ROLE_CULTIST in current.client.prefs.be_special))
text += "|Enabled in Prefs"
else
text += "|Disabled in Prefs"
sections["cult"] = text
sections["cult"] = memory_edit_cult(H)
/** WIZARD ***/
text = "wizard"
if(ticker.mode.config_tag=="wizard")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(src in ticker.mode.wizards)
text += "<b><font color='red'>WIZARD</font></b>|<a href='?src=[UID()];wizard=clear'>no</a>"
text += "<br><a href='?src=[UID()];wizard=lair'>To lair</a>, <a href='?src=[UID()];common=undress'>undress</a>, <a href='?src=[UID()];wizard=dressup'>dress up</a>, <a href='?src=[UID()];wizard=name'>let choose name</a>."
if(objectives.len==0)
text += "<br>Objectives are empty! <a href='?src=[UID()];wizard=autoobjectives'>Randomize!</a>"
else
text += "<a href='?src=[UID()];wizard=wizard'>wizard</a>|<b>NO</b>"
if(current && current.client && (ROLE_WIZARD in current.client.prefs.be_special))
text += "|Enabled in Prefs"
else
text += "|Disabled in Prefs"
sections["wizard"] = text
sections["wizard"] = memory_edit_wizard(H)
/** CHANGELING ***/
text = "changeling"
if(ticker.mode.config_tag=="changeling" || ticker.mode.config_tag=="traitorchan")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(src in ticker.mode.changelings)
text += "<b><font color='red'>CHANGELING</font></b>|<a href='?src=[UID()];changeling=clear'>no</a>"
if(objectives.len==0)
text += "<br>Objectives are empty! <a href='?src=[UID()];changeling=autoobjectives'>Randomize!</a>"
if( changeling && changeling.absorbed_dna.len && (current.real_name != changeling.absorbed_dna[1]) )
text += "<br><a href='?src=[UID()];changeling=initialdna'>Transform to initial appearance.</a>"
else
text += "<a href='?src=[UID()];changeling=changeling'>changeling</a>|<b>NO</b>"
if(current && current.client && (ROLE_CHANGELING in current.client.prefs.be_special))
text += "|Enabled in Prefs"
else
text += "|Disabled in Prefs"
sections["changeling"] = text
sections["changeling"] = memory_edit_changeling(H)
/** VAMPIRE ***/
text = "vampire"
if(ticker.mode.config_tag=="vampire" || ticker.mode.config_tag=="traitorvamp")
text = uppertext(text)
text = "<b><i>[text]</i></b>: "
if(src in ticker.mode.vampires)
text += "<b><font color='red'>VAMPIRE</font></b>|<a href='?src=[UID()];vampire=clear'>no</a>"
if(objectives.len==0)
text += "<br>Objectives are empty! <a href='?src=[UID()];vampire=autoobjectives'>Randomize!</a>"
else
text += "<a href='?src=[UID()];vampire=vampire'>vampire</a>|<b>NO</b>"
if(current && current.client && (ROLE_VAMPIRE in current.client.prefs.be_special))
text += "|Enabled in Prefs"
else
text += "|Disabled in Prefs"
/** Enthralled ***/
text += "<br><b><i>enthralled</i></b>: "
if(src in ticker.mode.vampire_enthralled)
text += "<b><font color='red'>THRALL</font></b>|<a href='?src=[UID()];vampthrall=clear'>no</a>"
else
text += "thrall|<b>NO</b>"
sections["vampire"] = text
sections["vampire"] = memory_edit_vampire(H)
/** NUCLEAR ***/
text = "nuclear"
if(ticker.mode.config_tag=="nuclear")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(src in ticker.mode.syndicates)
text += "<b><font color='red'>OPERATIVE</b></font>|<a href='?src=[UID()];nuclear=clear'>no</a>"
text += "<br><a href='?src=[UID()];nuclear=lair'>To shuttle</a>, <a href='?src=[UID()];common=undress'>undress</a>, <a href='?src=[UID()];nuclear=dressup'>dress up</a>."
var/code
for(var/obj/machinery/nuclearbomb/bombue in machines)
if(length(bombue.r_code) <= 5 && bombue.r_code != "LOLNO" && bombue.r_code != "ADMIN")
code = bombue.r_code
break
if(code)
text += " Code is [code]. <a href='?src=[UID()];nuclear=tellcode'>tell the code.</a>"
else
text += "<a href='?src=[UID()];nuclear=nuclear'>operative</a>|<b>NO</b>"
if(current && current.client && (ROLE_OPERATIVE in current.client.prefs.be_special))
text += "|Enabled in Prefs"
else
text += "|Disabled in Prefs"
sections["nuclear"] = text
sections["nuclear"] = memory_edit_nuclear(H)
/** SHADOWLING **/
text = "shadowling"
if(ticker.mode.config_tag == "shadowling")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(src in ticker.mode.shadows)
text += "<b><font color='red'>SHADOWLING</font></b>|thrall|<a href='?src=[UID()];shadowling=clear'>no</a>"
else if(src in ticker.mode.shadowling_thralls)
text += "Shadowling|<b><font color='red'>THRALL</font></b>|<a href='?src=[UID()];shadowling=clear'>no</a>"
else
text += "<a href='?src=[UID()];shadowling=shadowling'>shadowling</a>|<a href='?src=[UID()];shadowling=thrall'>thrall</a>|<b>NO</b>"
if(current && current.client && (ROLE_SHADOWLING in current.client.prefs.be_special))
text += "|Enabled in Prefs"
else
text += "|Disabled in Prefs"
sections["shadowling"] = text
sections["shadowling"] = memory_edit_shadowling(H)
/** Abductors **/
text = "abductor"
if(ticker.mode.config_tag == "abductor")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(src in ticker.mode.abductors)
text += "<b><font color='red'>ABDUCTOR</font></b>|<a href='?src=[UID()];abductor=clear'>no</a>"
text += "|<a href='?src=[UID()];common=undress'>undress</a>|<a href='?src=[UID()];abductor=equip'>equip</a>"
else
text += "<a href='?src=[UID()];abductor=abductor'>abductor</a>|<b>NO</b>"
if(current && current.client && (ROLE_ABDUCTOR in current.client.prefs.be_special))
text += "|Enabled in Prefs"
else
text += "|Disabled in Prefs"
sections["Abductor"] = text
sections["abductor"] = memory_edit_abductor(H)
/** TRAITOR ***/
text = "traitor"
if(ticker.mode.config_tag=="traitor" || ticker.mode.config_tag=="traitorchan" || ticker.mode.config_tag=="traitorvamp")
text = uppertext(text)
text = "<i><b>[text]</b></i>: "
if(src in ticker.mode.traitors)
text += "<b><font color='red'>TRAITOR</font></b>|<a href='?src=[UID()];traitor=clear'>no</a>"
if(objectives.len==0)
text += "<br>Objectives are empty! <a href='?src=[UID()];traitor=autoobjectives'>Randomize</a>!"
else
text += "<a href='?src=[UID()];traitor=traitor'>traitor</a>|<b>NO</b>"
if(current && current.client && (ROLE_TRAITOR in current.client.prefs.be_special))
text += "|Enabled in Prefs"
else
text += "|Disabled in Prefs"
sections["traitor"] = text
sections["traitor"] = memory_edit_traitor()
/** SILICON ***/
if(issilicon(current))
text = "silicon"
var/mob/living/silicon/robot/robot = current
if(istype(robot) && robot.emagged)
text += "<br>Cyborg: <b><font color='red'>Is emagged!</font></b> <a href='?src=[UID()];silicon=unemag'>Unemag!</a><br>0th law: [robot.laws.zeroth_law]"
var/mob/living/silicon/ai/ai = current
if(istype(ai) && ai.connected_robots.len)
var/n_e_robots = 0
for(var/mob/living/silicon/robot/R in ai.connected_robots)
if(R.emagged)
n_e_robots++
text += "<br>[n_e_robots] of [ai.connected_robots.len] slaved cyborgs are emagged. <a href='?src=[UID()];silicon=unemagcyborgs'>Unemag</a>"
sections["silicon"] = memory_edit_silicon()
/*
This prioritizes antags relevant to the current round to make them appear at the top of the panel.
Traitorchan and traitorvamp are snowflaked in because they have multiple sections.
*/
if(ticker.mode.config_tag == "traitorchan")
if(sections["traitor"])
out += sections["traitor"]+"<br>"
out += sections["traitor"] + "<br>"
if(sections["changeling"])
out += sections["changeling"]+"<br>"
out += sections["changeling"] + "<br>"
sections -= "traitor"
sections -= "changeling"
if(ticker.mode.config_tag == "traitorvamp")
// Elif technically unnecessary but it makes the following else look better
else if(ticker.mode.config_tag == "traitorvamp")
if(sections["traitor"])
out += sections["traitor"]+"<br>"
out += sections["traitor"] + "<br>"
if(sections["vampire"])
out += sections["vampire"]+"<br>"
out += sections["vampire"] + "<br>"
sections -= "traitor"
sections -= "vampire"
else
if(sections[ticker.mode.config_tag])
out += sections[ticker.mode.config_tag]+"<br>"
out += sections[ticker.mode.config_tag] + "<br>"
sections -= ticker.mode.config_tag
for(var/i in sections)
if(sections[i])
out += sections[i]+"<br>"
if(((src in ticker.mode.head_revolutionaries) || \
(src in ticker.mode.traitors) || \
(src in ticker.mode.syndicates)) && \
ishuman(current) )
text = "Uplink: <a href='?src=[UID()];common=uplink'>give</a>"
var/obj/item/uplink/hidden/suplink = find_syndicate_uplink()
var/crystals
if(suplink)
crystals = suplink.uses
if(suplink)
text += "|<a href='?src=[UID()];common=takeuplink'>take</a>"
if(usr.client.holder.rights & (R_SERVER|R_EVENT))
text += ", <a href='?src=[UID()];common=crystals'>[crystals]</a> crystals"
else
text += ", [crystals] crystals"
text += "." //hiel grammar
out += text
out += sections[i] + "<br>"
out += memory_edit_uplink()
out += "<br>"
out += "<b>Memory:</b><br>"
@@ -456,14 +423,9 @@
if(objectives.len == 0)
out += "EMPTY<br>"
else
var/obj_count = 1
for(var/datum/objective/objective in objectives)
out += "<B>[obj_count]</B>: [objective.explanation_text] <a href='?src=[UID()];obj_edit=\ref[objective]'>Edit</a> <a href='?src=[UID()];obj_delete=\ref[objective]'>Delete</a> <a href='?src=[UID()];obj_completed=\ref[objective]'><font color=[objective.completed ? "green" : "red"]>Toggle Completion</font></a><br>"
obj_count++
out += gen_objective_text(admin = TRUE)
out += "<a href='?src=[UID()];obj_add=1'>Add objective</a><br><br>"
out += "<a href='?src=[UID()];obj_announce=1'>Announce objectives</a><br><br>"
usr << browse(out, "window=edit_memory[src];size=400x500")
/datum/mind/Topic(href, href_list)
@@ -1284,12 +1246,9 @@
return A
/datum/mind/proc/announce_objectives()
var/obj_count = 1
to_chat(current, "<span class='notice'>Your current objectives:</span>")
for(var/objective in objectives)
var/datum/objective/O = objective
to_chat(current, "<B>Objective #[obj_count]</B>: [O.explanation_text]")
obj_count++
for(var/line in splittext(gen_objective_text(), "<br>"))
to_chat(current, line)
/datum/mind/proc/find_syndicate_uplink()
var/list/L = current.get_contents()
+1 -1
View File
@@ -90,7 +90,7 @@
for(var/path in backpack_contents)
var/number = backpack_contents[path]
for(var/i in 1 to number)
H.equip_to_slot_or_del(new path(H), slot_in_backpack)
H.equip_or_collect(new path(H), slot_in_backpack)
for(var/path in cybernetic_implants)
var/obj/item/organ/internal/O = new path(H)
+3 -3
View File
@@ -65,12 +65,12 @@
lakey = sanitizeSQL(H.lastattacker:key)
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
var/coord = "[H.x], [H.y], [H.z]"
// to_chat(world, "INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()])")
// to_chat(world, "INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.getBrainLoss()], [H.getOxyLoss()])")
establish_db_connection()
if(!dbcon.IsConnected())
log_game("SQL ERROR during death reporting. Failed to connect.")
else
var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')")
var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.getBrainLoss()], [H.getOxyLoss()], '[coord]')")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during death reporting. Error : \[[err]\]\n")
@@ -105,7 +105,7 @@
if(!dbcon.IsConnected())
log_game("SQL ERROR during death reporting. Failed to connect.")
else
var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')")
var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("death")] (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.getBrainLoss()], [H.getOxyLoss()], '[coord]')")
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during death reporting. Error : \[[err]\]\n")
+1 -1
View File
@@ -27,7 +27,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
icon_state = "unknown"
layer = AREA_LAYER
luminosity = 0
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
invisibility = INVISIBILITY_LIGHTING
var/valid_territory = TRUE //used for cult summoning areas on station zlevel
var/map_name // Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
+5 -5
View File
@@ -132,14 +132,14 @@
if(!fire)
fire = 1 //used for firedoor checks
updateicon()
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
air_doors_close()
/area/proc/fire_reset()
if(fire)
fire = 0 //used for firedoor checks
updateicon()
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
air_doors_open()
return
@@ -165,7 +165,7 @@
/area/proc/set_fire_alarm_effect()
fire = 1
updateicon()
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/area/proc/readyalert()
if(!eject)
@@ -181,12 +181,12 @@
if(!party)
party = 1
updateicon()
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/area/proc/partyreset()
if(party)
party = 0
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
updateicon()
/area/proc/updateicon()
+11
View File
@@ -44,6 +44,10 @@
var/initialized = FALSE
var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4.
var/list/remove_overlays // a very temporary list of overlays to remove
var/list/add_overlays // a very temporary list of overlays to add
/atom/New(loc, ...)
if(use_preloader && (src.type == _preloader.target_path))//in case the instanciated atom is creating other atoms in New()
_preloader.load(src)
@@ -83,6 +87,9 @@
if(opacity && isturf(loc))
var/turf/T = loc
T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guranteed to be on afterwards anyways.
if(loc)
loc.InitializedOn(src) // Used for poolcontroller / pool to improve performance greatly. However it also open up path to other usage of observer pattern on turfs.
ComponentInitialize()
@@ -97,6 +104,8 @@
/atom/proc/ComponentInitialize()
return
/atom/proc/InitializedOn(atom/A) // Proc for when something is initialized on a atom - Optional to call. Useful for observer pattern etc.
return
/atom/proc/onCentcom()
var/turf/T = get_turf(src)
@@ -137,6 +146,8 @@
QDEL_NULL(reagents)
invisibility = 101
LAZYCLEARLIST(overlays)
LAZYCLEARLIST(priority_overlays)
return ..()
//Hook for running code when a dir change occurs
+8
View File
@@ -159,6 +159,14 @@
/datum/dna/gene/disability/nearsighted/New()
block=GLASSESBLOCK
/datum/dna/gene/disability/nearsighted/activate(mob/living/M, connected, flags)
. = ..()
M.update_nearsighted_effects()
/datum/dna/gene/disability/nearsighted/deactivate(mob/living/M, connected, flags)
. = ..()
M.update_nearsighted_effects()
/datum/dna/gene/disability/lisp
name = "Lisp"
desc = "I wonder wath thith doeth."
+1 -1
View File
@@ -265,7 +265,7 @@
affecting = H.bodyparts_by_name[name]
if(!istype(affecting, /obj/item/organ/external))
continue
affecting.heal_damage(4, 0)
affecting.heal_damage(4, 0, updating_health = FALSE)
H.UpdateDamageIcon()
H.updatehealth()
+8 -2
View File
@@ -97,7 +97,10 @@
loc.visible_message("<span class='warning'>The corpse of [H.name] suddenly rises!</span>")
/mob/living/simple_animal/hostile/blob/blobspore/death(gibbed)
..()
// Only execute the below if we successfuly died
. = ..()
if(!.)
return FALSE
// On death, create a small smoke of harmful gas (s-Acid)
var/datum/effect_system/smoke_spread/chem/S = new
var/turf/location = get_turf(src)
@@ -178,5 +181,8 @@
return
/mob/living/simple_animal/hostile/blob/blobbernaut/death(gibbed)
..()
// Only execute the below if we successfully died
. = ..()
if(!.)
return FALSE
flick("blobbernaut_death", src)
@@ -87,7 +87,7 @@
if(!D)
return
H.set_species(D.species.type)
H.set_species(D.species.type, retain_damage = TRUE)
H.dna = D.Clone()
H.real_name = D.real_name
domutcheck(H, null, MUTCHK_FORCED) //Ensures species that get powers by the species proc handle_dna keep them
@@ -15,6 +15,7 @@
user.emote("deathgasp")
user.timeofdeath = world.time
user.status_flags |= FAKEDEATH //play dead
user.update_stat("fakedeath sting")
user.update_canmove()
addtimer(CALLBACK(src, .proc/ready_to_regenerate, user), LING_FAKEDEATH_TIME)
@@ -46,8 +46,8 @@
for(var/i in 1 to healing_ticks)
if(user)
var/healpertick = -(total_healing / healing_ticks)
user.heal_overall_damage((-healpertick/recent_uses), (-healpertick/recent_uses))
user.adjustOxyLoss(healpertick/recent_uses)
user.heal_overall_damage((-healpertick/recent_uses), (-healpertick/recent_uses), updating_health = FALSE)
user.adjustOxyLoss(healpertick/recent_uses, FALSE)
user.blood_volume = min(user.blood_volume + 30, BLOOD_VOLUME_NORMAL)
user.updatehealth()
else
+15 -13
View File
@@ -6,22 +6,22 @@
//Revive from regenerative stasis
/obj/effect/proc_holder/changeling/revive/sting_action(var/mob/living/carbon/user)
user.setToxLoss(0)
user.setOxyLoss(0)
user.setCloneLoss(0)
user.setBrainLoss(0)
user.SetParalysis(0)
user.SetStunned(0)
user.SetWeakened(0)
user.setToxLoss(0, FALSE)
user.setOxyLoss(0, FALSE)
user.setCloneLoss(0, FALSE)
user.setBrainLoss(0, FALSE)
user.SetParalysis(0, FALSE)
user.SetStunned(0, FALSE)
user.SetWeakened(0, FALSE)
user.radiation = 0
user.SetEyeBlind(0)
user.SetEyeBlurry(0)
user.SetEyeBlind(0, FALSE)
user.SetEyeBlurry(0, FALSE)
user.SetEarDamage(0)
user.SetEarDeaf(0)
user.heal_overall_damage(user.getBruteLoss(), user.getFireLoss())
user.CureBlind()
user.heal_overall_damage(user.getBruteLoss(), user.getFireLoss(), updating_health = FALSE)
user.CureBlind(FALSE)
user.CureDeaf()
user.CureNearsighted()
user.CureNearsighted(FALSE)
user.reagents.clear_reagents()
user.germ_level = 0
user.timeofdeath = 0
@@ -52,7 +52,9 @@
IO.rejuvenate()
IO.trace_chemicals.Cut()
H.remove_all_embedded_objects()
H.updatehealth()
user.updatehealth()
user.update_blind_effects()
user.update_blurry_effects()
to_chat(user, "<span class='notice'>We have regenerated.</span>")
+1 -3
View File
@@ -210,9 +210,7 @@ var/list/blacklisted_pylon_turfs = typecacheof(list(
if(L.health != L.maxHealth)
new /obj/effect/temp_visual/heal(get_turf(src), "#960000")
if(ishuman(L))
L.adjustBruteLoss(-1)
L.adjustFireLoss(-1)
L.updatehealth()
L.heal_overall_damage(1, 1)
if(istype(L, /mob/living/simple_animal/shade) || istype(L, /mob/living/simple_animal/hostile/construct))
var/mob/living/simple_animal/M = L
if(M.health < M.maxHealth)
+2 -2
View File
@@ -487,7 +487,7 @@ var/list/teleport_runes = list()
icon_state = "rune_large"
pixel_x = -32 //So the big ol' 96x96 sprite shows up right
pixel_y = -32
mouse_opacity = 1 //we're huge and easy to click
mouse_opacity = MOUSE_OPACITY_ICON //we're huge and easy to click
scribe_delay = 450 //how long the rune takes to create
scribe_damage = 40.1 //how much damage you take doing it
var/used
@@ -1031,7 +1031,7 @@ var/list/teleport_runes = list()
N.desc = "A weak shield summoned by cultists to protect them while they carry out delicate rituals"
N.color = "red"
N.health = 20
N.mouse_opacity = 0
N.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
new_human.key = ghost_to_spawn.key
ticker.mode.add_cultist(new_human.mind, 0)
summoned_guys |= new_human
+1 -1
View File
@@ -256,7 +256,7 @@ var/round_start_time = 0
cinematic.icon = 'icons/effects/station_explosion.dmi'
cinematic.icon_state = "station_intact"
cinematic.layer = 21
cinematic.mouse_opacity = 0
cinematic.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
cinematic.screen_loc = "1,0"
var/obj/structure/stool/bed/temp_buckle = new(src)
@@ -42,7 +42,7 @@
to_chat(src, "<span class='danger'>You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).</span>")
to_chat(B.host, "<span class='danger'>You feel the captive mind of [src] begin to resist your control.</span>")
var/delay = (rand(350,450) + B.host.brainloss)
var/delay = (rand(350,450) + B.host.getBrainLoss())
addtimer(CALLBACK(src, .proc/return_control, B), delay)
@@ -424,7 +424,7 @@
anchored = 1
unacidable = 1
light_range = 1
mouse_opacity = 1
mouse_opacity = MOUSE_OPACITY_ICON
var/health = 30
light_color = LIGHT_COLOR_CYAN
var/lon_range = 1
@@ -90,7 +90,10 @@
snapback()
/mob/living/simple_animal/hostile/guardian/death(gibbed)
..()
// Only execute the below if we successfully died
. = ..()
if(!.)
return FALSE
to_chat(summoner, "<span class='danger'>Your [name] died somehow!</span>")
summoner.death()
@@ -124,16 +124,19 @@
morph_time = world.time + MORPH_COOLDOWN
/mob/living/simple_animal/hostile/morph/death(gibbed)
if(morphed)
visible_message("<span class='warning'>[src] twists and dissolves into a pile of green flesh!</span>", \
"<span class='userdanger'>Your skin ruptures! Your flesh breaks apart! No disguise can ward off de--</span>")
restore()
if(gibbed)
. = ..()
if(stat == DEAD && gibbed)
for(var/atom/movable/AM in src)
AM.forceMove(loc)
if(prob(90))
step(AM, pick(alldirs))
..(gibbed)
// Only execute the below if we successfully died
if(!.)
return FALSE
if(morphed)
visible_message("<span class='warning'>[src] twists and dissolves into a pile of green flesh!</span>", \
"<span class='userdanger'>Your skin ruptures! Your flesh breaks apart! No disguise can ward off de--</span>")
restore()
/mob/living/simple_animal/hostile/morph/Aggro() // automated only
..()
@@ -161,15 +161,18 @@
/mob/living/simple_animal/revenant/dust()
death()
. = death()
/mob/living/simple_animal/revenant/gib()
death()
. = death()
/mob/living/simple_animal/revenant/death()
..()
if(!revealed)
return
return FALSE
// Only execute the below if we successfully died
. = ..()
if(!.)
return FALSE
ghost_darkness_images -= ghostimage
updateallghostimages()
@@ -190,7 +193,6 @@
R.client_to_revive = src.client //If the essence reforms, the old revenant is put back in the body
ghostize()
qdel(src)
return
/mob/living/simple_animal/revenant/attackby(obj/item/W, mob/living/user, params)
if(istype(W, /obj/item/nullrod))
@@ -96,10 +96,15 @@
desc = "A repulsive pile of guts and gore."
/mob/living/simple_animal/slaughter/death(gibbed)
// Only execute the below if we successfully died
. = ..()
if(!.)
return FALSE
for(var/mob/living/M in consumed_mobs)
M.forceMove(get_turf(src))
..()
release_consumed(M)
/mob/living/simple_animal/slaughter/proc/release_consumed(mob/living/M)
M.forceMove(get_turf(src))
/mob/living/simple_animal/slaughter/phasein()
. = ..()
@@ -297,13 +302,12 @@
deathmessage = "fades out, as all of its friends are released from its prison of hugs."
loot = list(/mob/living/simple_animal/pet/cat/kitten{name = "Laughter"})
/mob/living/simple_animal/slaughter/laughter/death(gibbed)
for(var/mob/living/M in consumed_mobs)
if(M.revive())
M.grab_ghost(force = TRUE)
playsound(get_turf(src), feast_sound, 50, 1, -1)
to_chat(M, "<span class='clown'>You leave the [src]'s warm embrace, and feel ready to take on the world.</span>")
..()
/mob/living/simple_animal/slaughter/laughter/release_consumed(mob/living/M)
if(M.revive())
M.grab_ghost(force = TRUE)
playsound(get_turf(src), feast_sound, 50, 1, -1)
to_chat(M, "<span class='clown'>You leave the [src]'s warm embrace, and feel ready to take on the world.</span>")
..(M)
//Objectives and helpers.
@@ -345,4 +349,4 @@
..()
/datum/objective/demonFluff/check_completion()
return 1
return 1
@@ -493,18 +493,19 @@
metabolization_rate = 100 //lel
/datum/reagent/shadowling_blindness_smoke/on_mob_life(mob/living/M)
var/update_flags = STATUS_UPDATE_NONE
if(!is_shadow_or_thrall(M))
to_chat(M, "<span class='warning'><b>You breathe in the black smoke, and your eyes burn horribly!</b></span>")
M.EyeBlind(5)
update_flags |= M.EyeBlind(5, FALSE)
if(prob(25))
M.visible_message("<b>[M]</b> claws at [M.p_their()] eyes!")
M.Stun(3)
else
to_chat(M, "<span class='notice'><b>You breathe in the black smoke, and you feel revitalized!</b></span>")
M.heal_organ_damage(2,2)
M.adjustOxyLoss(-2)
M.adjustToxLoss(-2)
..()
update_flags |= M.heal_organ_damage(2, 2, updating_health = FALSE)
update_flags |= M.adjustOxyLoss(-2, FALSE)
update_flags |= M.adjustToxLoss(-2, FALSE)
return ..() | update_flags
/obj/effect/proc_holder/spell/aoe_turf/unearthly_screech
name = "Sonic Screech"
+2 -4
View File
@@ -264,9 +264,6 @@
maim_clone(H)
H.Paralyse(4)
//Here let's calculate their health so the pod doesn't immediately eject them!!!
H.updatehealth()
if(grab_ghost_when == CLONER_FRESH_CLONE)
clonemind.transfer_to(H)
H.ckey = R.ckey
@@ -555,7 +552,7 @@
qdel(i)
missing_organs.Cut()
H.setCloneLoss(CLONE_INITIAL_DAMAGE)
H.setCloneLoss(CLONE_INITIAL_DAMAGE, FALSE)
H.setBrainLoss(BRAIN_INITIAL_DAMAGE)
for(var/o in H.internal_organs)
@@ -578,6 +575,7 @@
missing_organs += I
organs_number = LAZYLEN(missing_organs)
H.updatehealth()
/obj/machinery/clonepod/proc/check_brine()
// Clones are in a pickled bath of mild chemicals, keeping
+12 -14
View File
@@ -64,21 +64,19 @@
return 1
if(href_list["fix"])
src.active = 1
while(src.occupant.health < 100)
src.occupant.adjustOxyLoss(-1)
src.occupant.adjustFireLoss(-1)
src.occupant.adjustToxLoss(-1)
src.occupant.adjustBruteLoss(-1)
src.occupant.updatehealth()
if(src.occupant.health >= 0 && src.occupant.stat == 2)
src.occupant.stat = 0
src.occupant.lying = 0
dead_mob_list -= src.occupant
living_mob_list += src.occupant
active = 1
while(occupant.health < 100)
occupant.adjustOxyLoss(-1, FALSE)
occupant.adjustFireLoss(-1, FALSE)
occupant.adjustToxLoss(-1, FALSE)
occupant.adjustBruteLoss(-1, FALSE)
occupant.updatehealth()
if(occupant.health >= 0 && occupant.stat == DEAD)
occupant.update_revive()
occupant.lying = 0
sleep(10)
src.active = 0
src.add_fingerprint(usr)
active = 0
add_fingerprint(usr)
if(href_list["wireless"])
var/wireless = text2num(href_list["wireless"])
@@ -296,6 +296,15 @@
/obj/item/circuitboard/white_ship
name = "circuit Board (White Ship)"
build_path = /obj/machinery/computer/shuttle/white_ship
/obj/item/circuitboard/shuttle/syndicate
name = "circuit board (Syndicate Shuttle)"
build_path = /obj/machinery/computer/shuttle/syndicate
/obj/item/circuitboard/shuttle/syndicate/recall
name = "circuit board (Syndicate Shuttle Recall Terminal)"
build_path = /obj/machinery/computer/shuttle/syndicate/recall
/obj/item/circuitboard/shuttle/syndicate/drop_pod
name = "circuit board (Syndicate Drop Pod)"
build_path = /obj/machinery/computer/shuttle/syndicate/drop_pod
/obj/item/circuitboard/HolodeckControl
+2 -2
View File
@@ -217,7 +217,7 @@
// Check if camera is accessible when jumping
/obj/machinery/computer/security/proc/can_access_camera(var/obj/machinery/camera/C, var/mob/M)
if(CanUseTopic(M, default_state) != STATUS_INTERACTIVE || M.incapacitated() || M.blinded)
if(CanUseTopic(M, default_state) != STATUS_INTERACTIVE || M.incapacitated() || !M.has_vision())
return 0
if(isrobot(M))
@@ -361,4 +361,4 @@
icon_screen = "engie_cams"
light_color = "#FAC54B"
network = list("Power Alarms","Atmosphere Alarms","Fire Alarms")
circuit = /obj/item/circuitboard/camera/engineering
circuit = /obj/item/circuitboard/camera/engineering
+1 -1
View File
@@ -385,7 +385,7 @@
occupant.adjustToxLoss(max(-efficiency, (-20*(efficiency ** 2)) / occupant.getToxLoss()))
var/heal_brute = occupant.getBruteLoss() ? min(efficiency, 20*(efficiency**2) / occupant.getBruteLoss()) : 0
var/heal_fire = occupant.getFireLoss() ? min(efficiency, 20*(efficiency**2) / occupant.getFireLoss()) : 0
occupant.heal_organ_damage(heal_brute,heal_fire)
occupant.heal_organ_damage(heal_brute, heal_fire)
if(beaker && next_trans == 0)
var/proportion = 10 * min(1/beaker.volume, 1)
// Yes, this means you can get more bang for your buck with a beaker of SF vs a patch
+4 -5
View File
@@ -313,15 +313,14 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/update_icon(state=0, override=0)
if(operating && !override)
return
icon_state = density ? "closed" : "open"
switch(state)
if(0)
if(density)
state = AIRLOCK_CLOSED
else
state = AIRLOCK_OPEN
icon_state = ""
if(AIRLOCK_OPEN, AIRLOCK_CLOSED)
icon_state = ""
if(AIRLOCK_DENY, AIRLOCK_OPENING, AIRLOCK_CLOSING, AIRLOCK_EMAG)
icon_state = "nonexistenticonstate" //MADNESS
set_airlock_overlays(state)
@@ -670,12 +669,12 @@ About the new airlock wires panel:
return FALSE
//For the tools being used on the door. Since you don't want to call the attack_hand method if you're using hands. That would be silly
//Also it's a bit inconsistent that when you access the panel you headbutt it. But not while crowbarring
//Also it's a bit inconsistent that when you access the panel you headbutt it. But not while crowbarring
//Try to interact with the panel. If the user can't it'll try activating the door
/obj/machinery/door/airlock/proc/interact_with_panel(mob/user)
if(shock_user(user, 100))
return
if(panel_open)
if(security_level)
to_chat(user, "<span class='warning'>Wires are protected!</span>")
@@ -1325,7 +1324,7 @@ About the new airlock wires panel:
user.visible_message("<span class='notice'>[user] removes [note] from [src].</span>", "<span class='notice'>You remove [note] from [src].</span>")
playsound(src, 'sound/items/poster_ripped.ogg', 50, 1)
else return FALSE
else
else
user.visible_message("<span class='notice'>[user] cuts down [note] from [src].</span>", "<span class='notice'>You remove [note] from [src].</span>")
playsound(src, 'sound/items/Wirecutter.ogg', 50, 1)
note.forceMove(get_turf(user))
+11 -6
View File
@@ -55,6 +55,7 @@ var/list/holopads = list()
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
var/obj/effect/overlay/holoray/ray
var/ringing = FALSE
var/dialling_input = FALSE //The user is currently selecting where to send their call
/obj/machinery/hologram/holopad/New()
..()
@@ -133,6 +134,8 @@ var/list/holopads = list()
/obj/machinery/hologram/holopad/interact(mob/living/carbon/human/user) //Carn: hologram requests.
if(!istype(user))
return
if(!anchored)
return
var/dat
if(temp)
@@ -191,7 +194,9 @@ var/list/holopads = list()
else if(href_list["Holocall"])
if(outgoing_call)
return
if(dialling_input)
to_chat(usr, "<span class='notice'>Finish dialling first!</span>")
return
temp = "You must stand on the holopad to make a call!<br>"
temp += "<a href='?src=[UID()];mainmenu=1'>Main Menu</a>"
if(usr.loc == loc)
@@ -201,9 +206,9 @@ var/list/holopads = list()
if(A)
LAZYADD(callnames[A], I)
callnames -= get_area(src)
dialling_input = TRUE
var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames
dialling_input = FALSE
if(QDELETED(usr) || !result || outgoing_call)
return
@@ -250,7 +255,7 @@ var/list/holopads = list()
/obj/machinery/hologram/holopad/process()
for(var/I in masters)
var/mob/living/master = I
if((stat & NOPOWER) || !validate_user(master))
if((stat & NOPOWER) || !validate_user(master) || !anchored)
clear_holo(master)
if(outgoing_call)
@@ -348,7 +353,7 @@ var/list/holopads = list()
hologram.alpha = 100
hologram.Impersonation = user
hologram.mouse_opacity = 0//So you can't click on it.
hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it.
hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
hologram.anchored = 1//So space wind cannot drag it.
hologram.name = "[user.name] (hologram)"//If someone decides to right click.
@@ -481,7 +486,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
layer = FLY_LAYER
density = FALSE
anchored = TRUE
mouse_opacity = 1
mouse_opacity = MOUSE_OPACITY_ICON
pixel_x = -32
pixel_y = -32
alpha = 100
+24 -30
View File
@@ -11,18 +11,21 @@
icon_state = "airlock_control_standby"
anchored = 1 //this is what I get for assuming /obj/machinery has anchored set to 1 by default
var/list/linkedturfs = list() //List contains all of the linked pool turfs to this controller, assignment happens on New()
var/mobinpool = list() //List contains all of the mob in the pool, to prevent looping through the entire area to find mobs inside..
var/decalinpool = list() // List containing all of the cleanable decals in pool
var/linked_area = null
var/temperature = NORMAL //The temperature of the pool, starts off on normal, which has no effects.
var/temperaturecolor = "" //used for nanoUI fancyness
var/srange = 5 //The range of the search for pool turfs, change this for bigger or smaller pools.
var/list/linkedmist = list() //Used to keep track of created mist
var/deep_water = 0 //set to 1 to drown even standing people
var/deep_water = FALSE //set to 1 to drown even standing people
/obj/machinery/poolcontroller/New() //This proc automatically happens on world start
if(!linked_area)
for(var/turf/simulated/floor/beach/water/W in range(srange,src)) //Search for /turf/simulated/floor/beach/water in the range of var/srange
linkedturfs += W //Add found pool turfs to the central list.
W.linkedcontroller = src // And add the linked controller to itself.
..() //Changed to call parent as per MarkvA's recommendation
/obj/machinery/poolcontroller/emag_act(user as mob) //Emag_act, this is called when it is hit with a cryptographic sequencer.
@@ -48,21 +51,24 @@
ui_interact(user)
/obj/machinery/poolcontroller/process()
updatePool() //Call the mob affecting/decal cleaning proc
processMob() //Call the mob affecting proc
cleanPool() //Call the decal cleaning proc
/obj/machinery/poolcontroller/proc/updatePool()
for(var/turf/T in linkedturfs) //Check for pool-turfs linked to the controller.
for(var/mob/M in T) //Check for mobs in the linked pool-turfs.
handleTemp(M) //handles pool temp effects on the swimmers
/obj/machinery/poolcontroller/proc/processMob()
for(var/M in mobinpool) //They're already typecasted when entering the turf
// Following two are sanity check. If the mob is no longer in the pool for whatever reason (Looking at you teleport), remove them
if(!istype(get_turf(M), /turf/simulated/floor/beach/water) && !istype(get_turf(M), /turf/unsimulated/beach/water)) // Water component when?
mobinpool -= M
continue
handleTemp(M) //handles pool temp effects on the swimmers
if(ishuman(M)) //Only human types will drown, to keep things simple for non-human mobs that live in the water
handleDrowning(M)
if(ishuman(M)) //Make sure they are human before typecasting.
var/mob/living/carbon/human/drownee = M //Typecast them as human.
handleDrowning(drownee) //Only human types will drown, to keep things simple for non-human mobs that live in the water
for(var/obj/effect/decal/cleanable/decal in T) //Cleans up cleanable decals like blood and such
/obj/machinery/poolcontroller/proc/cleanPool()
for(var/obj/effect/decal/cleanable/decal in decalinpool) //Cleans up cleanable decals like blood and such
if(!QDELETED(decal))
animate(decal, alpha = 10, time = 20)
spawn(25)
qdel(decal)
QDEL_IN(decal, 25)
/obj/machinery/poolcontroller/proc/handleTemp(var/mob/M)
if(!M || isAIEye(M) || issilicon(M) || isobserver(M) || M.stat == DEAD)
@@ -187,29 +193,17 @@
/obj/machinery/poolcontroller/seacontroller
invisibility = 101
unacidable = 1
name = "Sea Controller"
desc = "A controller for the underwater portion of the sea. Players shouldn't see this."
deep_water = 1 //deep sea is deep water
deep_water = TRUE //deep sea is deep water
/obj/machinery/poolcontroller/seacontroller/New()
/obj/machinery/poolcontroller/seacontroller/Initialize()
linked_area = get_area(src)
for(var/turf/unsimulated/beach/water/W in linked_area)
linkedturfs += W //Add found pool turfs to the central list.
W.linkedcontroller = src // And add the linked controller to itself.
..()
/obj/machinery/poolcontroller/seacontroller/updatePool()
for(var/turf/T in linked_area)
for(var/mob/M in T)
handleTemp(M) //handles pool temp effects on the swimmers
if(ishuman(M)) //Make sure they are human before typecasting.
var/mob/living/carbon/human/drownee = M //Typecast them as human.
handleDrowning(drownee) //Only human types will drown, to keep things simple for non-human mobs that live in the water
for(var/obj/effect/decal/cleanable/decal in T)
animate(decal, alpha = 10, time = 20)
spawn(25)
qdel(decal)
#undef FRIGID
#undef COOL
#undef NORMAL
+8 -1
View File
@@ -8,7 +8,7 @@
idle_power_usage = 4
active_power_usage = 250
var/obj/item/charging = null
var/list/allowed_devices = list(/obj/item/gun/energy, /obj/item/melee/baton, /obj/item/modular_computer, /obj/item/rcs)
var/list/allowed_devices = list(/obj/item/gun/energy, /obj/item/melee/baton, /obj/item/modular_computer, /obj/item/rcs, /obj/item/bodyanalyzer)
var/icon_state_off = "rechargeroff"
var/icon_state_charged = "recharger2"
var/icon_state_charging = "recharger1"
@@ -115,6 +115,13 @@
if(R.rcell.give(R.rcell.chargerate))
use_power(200)
using_power = 1
if(istype(charging, /obj/item/bodyanalyzer))
var/obj/item/bodyanalyzer/B = charging
if(B.power_supply)
if(B.power_supply.give(B.power_supply.chargerate))
use_power(200)
using_power = 1
update_icon(using_power)
+2 -5
View File
@@ -158,9 +158,7 @@
var/mob/living/silicon/robot/R = occupant
restock_modules()
if(repairs)
R.adjustBruteLoss(-(repairs))
R.adjustFireLoss(-(repairs))
R.updatehealth()
R.heal_overall_damage(repairs, repairs)
if(R.cell)
R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge)
else if(istype(occupant, /mob/living/carbon/human))
@@ -168,8 +166,7 @@
if(H.get_int_organ(/obj/item/organ/internal/cell) && H.nutrition < 450)
H.nutrition = min(H.nutrition+recharge_speed_nutrition, 450)
if(repairs)
H.heal_overall_damage(repairs, repairs, 0, 1)
H.updatehealth()
H.heal_overall_damage(repairs, repairs, TRUE, 0, 1)
/obj/machinery/recharge_station/proc/go_out()
if(!occupant)
-1
View File
@@ -62,7 +62,6 @@
playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
H.emote("scream") // It is painful
H.adjustBruteLoss(max(0, 80 - H.getBruteLoss())) // Hurt the human, don't try to kill them though.
H.handle_regular_hud_updates() // Make sure they see the pain.
// Sleep for a couple of ticks to allow the human to see the pain
sleep(5)
@@ -228,7 +228,6 @@
return
if(M.health > 0)
M.adjustOxyLoss(-1)
M.updatehealth()
M.AdjustStunned(-4)
M.AdjustWeakened(-4)
M.AdjustStunned(-4)
@@ -520,4 +519,3 @@
for(var/reagent in processed_reagents)
reagents.add_reagent(reagent,amount)
chassis.use_power(energy_drain)
@@ -94,7 +94,6 @@
if(target)
target.Paralyse(10)
target.updatehealth()
/obj/item/mecha_parts/mecha_equipment/drill/diamonddrill
@@ -56,7 +56,6 @@
if(!M)
return
M.adjustOxyLoss(round(dam_force/2))
M.updatehealth()
target.visible_message("<span class='danger'>[chassis] squeezes [target].</span>", \
"<span class='userdanger'>[chassis] squeezes [target].</span>",\
"<span class='italics'>You hear something crack.</span>")
@@ -451,4 +450,3 @@
//NC.mergeConnectedNetworksOnTurf()
last_piece = NC
return 1
@@ -62,8 +62,8 @@
color = "#EBEBEB"
/obj/effect/decal/cleanable/flour/foam/Initialize()
. = ..()
QDEL_IN(src, 15 SECONDS)
. = ..()
QDEL_IN(src, 15 SECONDS)
/obj/effect/decal/cleanable/greenglow
name = "glowing goo"
@@ -77,8 +77,8 @@
icon_state = "greenglow"
/obj/effect/decal/cleanable/greenglow/Initialize(mapload)
. = ..()
QDEL_IN(src, 2 MINUTES)
. = ..()
QDEL_IN(src, 2 MINUTES)
/obj/effect/decal/cleanable/cobweb
name = "cobweb"
@@ -201,4 +201,3 @@
icon_state = "confetti1"
random_icon_states = list("confetti1", "confetti2", "confetti3")
anchored = TRUE
@@ -7,7 +7,7 @@ would spawn and follow the beaker, even if it is carried or thrown.
/obj/effect/particle_effect
name = "particle effect"
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
unacidable = 1//So effects are not targeted by alien acid.
pass_flags = PASSTABLE | PASSGRILLE
@@ -27,7 +27,7 @@
icon_state = "explosion"
opacity = 1
anchored = 1
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
pixel_x = -32
pixel_y = -32
+1 -1
View File
@@ -32,7 +32,7 @@
anchored = 1
layer = 99
plane = HUD_PLANE
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
unacidable = 1//Just to be sure.
/obj/effect/beam
+1 -1
View File
@@ -58,7 +58,7 @@
anchored = 1
density = 1
layer = 5
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/obj/effect/overlay/wall_rot/New()
..()
@@ -42,3 +42,8 @@
name = "reinforced window spawner"
icon_state = "rwindow_spawner"
windowtospawn = /obj/structure/window/reinforced
/obj/effect/spawner/window/reinforced/plasma
name = "reinforced plasma window spawner"
icon_state = "pwindow_spawner"
windowtospawn = /obj/structure/window/plasmareinforced
@@ -134,7 +134,7 @@
name = mimiced_atom.name
appearance = mimiced_atom.appearance
setDir(mimiced_atom.dir)
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/obj/effect/temp_visual/decoy/fading/New(loc, atom/mimiced_atom)
..()
@@ -2,7 +2,7 @@
/obj/effect/temp_visual
anchored = 1
layer = ABOVE_MOB_LAYER
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/duration = 10
var/randomdir = TRUE
+3 -3
View File
@@ -1,12 +1,12 @@
/proc/empulse(turf/epicenter, heavy_range, light_range, log=0)
/proc/empulse(turf/epicenter, heavy_range, light_range, log=0, cause = null)
if(!epicenter) return
if(!istype(epicenter, /turf))
epicenter = get_turf(epicenter.loc)
if(log)
message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] [ADMIN_COORDJMP(epicenter)]</a>")
log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] [COORD(epicenter)]")
message_admins("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])": ] [ADMIN_COORDJMP(epicenter)]</a>")
log_game("EMP with size ([heavy_range], [light_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])" : ] [COORD(epicenter)]")
if(heavy_range > 1)
new/obj/effect/temp_visual/emp/pulse(epicenter)
+3 -3
View File
@@ -1,6 +1,6 @@
//TODO: Flash range does nothing currently
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range = 0 ,silent = 0, smoke = 1)
/proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1, ignorecap = 0, flame_range = 0 ,silent = 0, smoke = 1, cause = null)
src = null //so we don't abort once src is deleted
epicenter = get_turf(epicenter)
@@ -25,8 +25,8 @@
var/list/cached_exp_block = list()
if(adminlog)
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[epicenter.x];Y=[epicenter.y];Z=[epicenter.z]'>JMP</a>)")
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] ([epicenter.x],[epicenter.y],[epicenter.z])")
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])" : ] [ADMIN_COORDJMP(epicenter)] ")
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in area [epicenter.loc.name] [cause ? "(Cause: [cause])" : ] [COORD(epicenter)] ")
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
// Stereo users will also hear the direction of the explosion!
+1 -2
View File
@@ -232,7 +232,6 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_arm")
if(affecting && affecting.receive_damage(0, 5)) // 5 burn damage
H.UpdateDamageIcon()
H.updatehealth()
return
else
extinguish()
@@ -554,4 +553,4 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
return TRUE
/obj/item/attack_hulk(mob/living/carbon/human/user)
return FALSE
return FALSE
@@ -90,7 +90,6 @@
to_chat(AI, "Your core files are being wiped!")
while(AI && AI.stat != DEAD)
AI.adjustOxyLoss(2)
AI.updatehealth()
sleep(10)
flush = 0
+250
View File
@@ -632,3 +632,253 @@ REAGENT SCANNER
if(T.cores > 1)
user.show_message("Anomalous slime core amount detected", 1)
user.show_message("Growth progress: [T.amount_grown]/10", 1)
/obj/item/bodyanalyzer
name = "handheld body analyzer"
icon = 'icons/obj/device.dmi'
icon_state = "bodyanalyzer_0"
item_state = "healthanalyser"
desc = "A handheld scanner capable of deep-scanning an entire body."
slot_flags = SLOT_BELT
throwforce = 3
w_class = WEIGHT_CLASS_TINY
throw_speed = 5
throw_range = 10
origin_tech = "magnets=6;biotech=6"
var/obj/item/stock_parts/cell/power_supply
var/cell_type = /obj/item/stock_parts/cell/upgraded
var/ready = TRUE // Ready to scan
var/time_to_use = 0 // How much time remaining before next scan is available.
var/usecharge = 750
/obj/item/bodyanalyzer/advanced
cell_type = /obj/item/stock_parts/cell/upgraded/plus
/obj/item/bodyanalyzer/New()
..()
power_supply = new cell_type(src)
power_supply.give(power_supply.maxcharge)
update_icon()
/obj/item/bodyanalyzer/proc/setReady()
ready = TRUE
playsound(src, 'sound/machines/defib_saftyOn.ogg', 50, 0)
update_icon()
/obj/item/bodyanalyzer/update_icon(printing = FALSE)
overlays.Cut()
var/percent = power_supply.percent()
if(ready)
icon_state = "bodyanalyzer_1"
else
icon_state = "bodyanalyzer_2"
var/overlayid = round(percent / 10)
overlayid = "bodyanalyzer_charge[overlayid]"
overlays += icon(icon, overlayid)
if(printing)
overlays += icon(icon, "bodyanalyzer_printing")
/obj/item/bodyanalyzer/attack(mob/living/M, mob/living/carbon/human/user)
if(user.incapacitated() || !user.Adjacent(M))
return
if(!ready)
to_chat(user, "<span class='notice'>The scanner beeps angrily at you! It's currently recharging - [round((time_to_use - world.time) * 0.1)] seconds remaining.</span>")
playsound(user.loc, 'sound/machines/buzz-sigh.ogg', 50, 1)
return
if(power_supply.charge >= usecharge)
mobScan(M, user)
else
to_chat(user, "<span class='notice'>The scanner beeps angrily at you! It's out of charge!</span>")
playsound(user.loc, 'sound/machines/buzz-sigh.ogg', 50, 1)
/obj/item/bodyanalyzer/proc/mobScan(mob/living/M, mob/user)
if(ishuman(M))
var/report = generate_printing_text(M, user)
user.visible_message("[user] begins scanning [M] with [src].", "You begin scanning [M].")
if(do_after(user, 100, target = M))
var/obj/item/paper/printout = new
printout.info = report
printout.name = "Scan report - [M.name]"
playsound(user.loc, 'sound/goonstation/machines/printer_dotmatrix.ogg', 50, 1)
user.put_in_hands(printout)
time_to_use = world.time + 600
power_supply.use(usecharge)
ready = FALSE
update_icon(TRUE)
addtimer(CALLBACK(src, /obj/item/bodyanalyzer/.proc/setReady), 600)
addtimer(CALLBACK(src, /obj/item/bodyanalyzer/.proc/update_icon), 20)
else if(iscorgi(M) && M.stat == DEAD)
to_chat(user, "<span class='notice'>You wonder if [M.p_they()] was a good dog. <b>[src] tells you they were the best...</b></span>") // :'(
playsound(loc, 'sound/machines/ping.ogg', 50, 0)
ready = FALSE
addtimer(CALLBACK(src, /obj/item/bodyanalyzer/.proc/setReady), 600)
time_to_use = world.time + 600
else
to_chat(user, "<span class='notice'>Scanning error detected. Invalid specimen.</span>")
//Unashamedly ripped from adv_med.dm
/obj/item/bodyanalyzer/proc/generate_printing_text(mob/living/M, mob/user)
var/dat = ""
var/mob/living/carbon/human/target = M
dat = "<font color='blue'><b>Target Statistics:</b></font><br>"
var/t1
switch(target.stat) // obvious, see what their status is
if(CONSCIOUS)
t1 = "Conscious"
if(UNCONSCIOUS)
t1 = "Unconscious"
else
t1 = "*dead*"
dat += "[target.health > 50 ? "<font color='blue'>" : "<font color='red'>"]\tHealth %: [target.health], ([t1])</font><br>"
var/found_disease = FALSE
for(var/thing in target.viruses)
var/datum/disease/D = thing
if(D.visibility_flags) //If any visibility flags are on.
continue
found_disease = TRUE
break
if(found_disease)
dat += "<font color='red'>Disease detected in target.</font><BR>"
var/extra_font = null
extra_font = (target.getBruteLoss() < 60 ? "<font color='blue'>" : "<font color='red'>")
dat += "[extra_font]\t-Brute Damage %: [target.getBruteLoss()]</font><br>"
extra_font = (target.getOxyLoss() < 60 ? "<font color='blue'>" : "<font color='red'>")
dat += "[extra_font]\t-Respiratory Damage %: [target.getOxyLoss()]</font><br>"
extra_font = (target.getToxLoss() < 60 ? "<font color='blue'>" : "<font color='red'>")
dat += "[extra_font]\t-Toxin Content %: [target.getToxLoss()]</font><br>"
extra_font = (target.getFireLoss() < 60 ? "<font color='blue'>" : "<font color='red'>")
dat += "[extra_font]\t-Burn Severity %: [target.getFireLoss()]</font><br>"
extra_font = (target.radiation < 10 ?"<font color='blue'>" : "<font color='red'>")
dat += "[extra_font]\tRadiation Level %: [target.radiation]</font><br>"
extra_font = (target.getCloneLoss() < 1 ?"<font color='blue'>" : "<font color='red'>")
dat += "[extra_font]\tGenetic Tissue Damage %: [target.getCloneLoss()]<br>"
extra_font = (target.getBrainLoss() < 1 ?"<font color='blue'>" : "<font color='red'>")
dat += "[extra_font]\tApprox. Brain Damage %: [target.getBrainLoss()]<br>"
dat += "Paralysis Summary %: [target.paralysis] ([round(target.paralysis / 4)] seconds left!)<br>"
dat += "Body Temperature: [target.bodytemperature-T0C]&deg;C ([target.bodytemperature*1.8-459.67]&deg;F)<br>"
dat += "<hr>"
if(target.has_brain_worms())
dat += "Large growth detected in frontal lobe, possibly cancerous. Surgical removal is recommended.<br>"
var/blood_percent = round((target.blood_volume / BLOOD_VOLUME_NORMAL))
blood_percent *= 100
extra_font = (target.blood_volume > 448 ? "<font color='blue'>" : "<font color='red'>")
dat += "[extra_font]\tBlood Level %: [blood_percent] ([target.blood_volume] units)</font><br>"
if(target.reagents)
dat += "Epinephrine units: [target.reagents.get_reagent_amount("Epinephrine")] units<BR>"
dat += "Ether: [target.reagents.get_reagent_amount("ether")] units<BR>"
extra_font = (target.reagents.get_reagent_amount("silver_sulfadiazine") < 30 ? "<font color='black'>" : "<font color='red'>")
dat += "[extra_font]\tSilver Sulfadiazine: [target.reagents.get_reagent_amount("silver_sulfadiazine")]</font><br>"
extra_font = (target.reagents.get_reagent_amount("styptic_powder") < 30 ? "<font color='black'>" : "<font color='red'>")
dat += "[extra_font]\tStyptic Powder: [target.reagents.get_reagent_amount("styptic_powder")] units<BR>"
extra_font = (target.reagents.get_reagent_amount("salbutamol") < 30 ? "<font color='black'>" : "<font color='red'>")
dat += "[extra_font]\tSalbutamol: [target.reagents.get_reagent_amount("salbutamol")] units<BR>"
dat += "<hr><table border='1'>"
dat += "<tr>"
dat += "<th>Organ</th>"
dat += "<th>Burn Damage</th>"
dat += "<th>Brute Damage</th>"
dat += "<th>Other Wounds</th>"
dat += "</tr>"
for(var/obj/item/organ/external/e in target.bodyparts)
dat += "<tr>"
var/AN = ""
var/open = ""
var/infected = ""
var/robot = ""
var/imp = ""
var/bled = ""
var/splint = ""
var/internal_bleeding = ""
var/lung_ruptured = ""
if(e.internal_bleeding)
internal_bleeding = "<br>Internal bleeding"
if(istype(e, /obj/item/organ/external/chest) && target.is_lung_ruptured())
lung_ruptured = "Lung ruptured:"
if(e.status & ORGAN_SPLINTED)
splint = "Splinted:"
if(e.status & ORGAN_BROKEN)
AN = "[e.broken_description]:"
if(e.is_robotic())
robot = "Robotic:"
if(e.open)
open = "Open:"
switch(e.germ_level)
if(INFECTION_LEVEL_ONE to INFECTION_LEVEL_ONE + 200)
infected = "Mild Infection:"
if(INFECTION_LEVEL_ONE + 200 to INFECTION_LEVEL_ONE + 300)
infected = "Mild Infection+:"
if(INFECTION_LEVEL_ONE + 300 to INFECTION_LEVEL_ONE + 400)
infected = "Mild Infection++:"
if(INFECTION_LEVEL_TWO to INFECTION_LEVEL_TWO + 200)
infected = "Acute Infection:"
if(INFECTION_LEVEL_TWO + 200 to INFECTION_LEVEL_TWO + 300)
infected = "Acute Infection+:"
if(INFECTION_LEVEL_TWO + 300 to INFECTION_LEVEL_TWO + 400)
infected = "Acute Infection++:"
if(INFECTION_LEVEL_THREE to INFINITY)
infected = "Septic:"
var/unknown_body = 0
for(var/I in e.embedded_objects)
unknown_body++
if(unknown_body || e.hidden)
imp += "Unknown body present:"
if(!AN && !open && !infected & !imp)
AN = "None:"
dat += "<td>[e.name]</td><td>[e.burn_dam]</td><td>[e.brute_dam]</td><td>[robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured]</td>"
dat += "</tr>"
for(var/obj/item/organ/internal/i in target.internal_organs)
var/mech = i.desc
var/infection = "None"
switch(i.germ_level)
if(1 to INFECTION_LEVEL_ONE + 200)
infection = "Mild Infection:"
if(INFECTION_LEVEL_ONE + 200 to INFECTION_LEVEL_ONE + 300)
infection = "Mild Infection+:"
if(INFECTION_LEVEL_ONE + 300 to INFECTION_LEVEL_ONE + 400)
infection = "Mild Infection++:"
if(INFECTION_LEVEL_TWO to INFECTION_LEVEL_TWO + 200)
infection = "Acute Infection:"
if(INFECTION_LEVEL_TWO + 200 to INFECTION_LEVEL_TWO + 300)
infection = "Acute Infection+:"
if(INFECTION_LEVEL_TWO + 300 to INFINITY)
infection = "Acute Infection++:"
dat += "<tr>"
dat += "<td>[i.name]</td><td>N/A</td><td>[i.damage]</td><td>[infection]:[mech]</td><td></td>"
dat += "</tr>"
dat += "</table>"
if(target.disabilities & BLIND)
dat += "<font color='red'>Cataracts detected.</font><BR>"
if(target.disabilities & COLOURBLIND)
dat += "<font color='red'>Photoreceptor abnormalities detected.</font><BR>"
if(target.disabilities & NEARSIGHTED)
dat += "<font color='red'>Retinal misalignment detected.</font><BR>"
return dat
@@ -302,14 +302,12 @@
if(cyborg.health < cyborg.maxHealth)
if(cyborg.health < 0)
repair_amount = -2.5
repair_amount = 2.5
powercost = 30
else
repair_amount = -1
repair_amount = 1
powercost = 10
cyborg.adjustBruteLoss(repair_amount)
cyborg.adjustFireLoss(repair_amount)
cyborg.updatehealth()
cyborg.heal_overall_damage(repair_amount, repair_amount)
cyborg.cell.use(powercost)
else
cyborg.cell.use(5)
+1 -3
View File
@@ -94,9 +94,7 @@
hp -= Proj.damage
if(hp <= 0)
for(var/mob/O in oviewers())
if((O.client && !( O.blinded )))
to_chat(O, "<span class='warning'>[src] breaks into tiny pieces and collapses!</span>")
visible_message("<span class='warning'>[src] breaks into tiny pieces and collapses!</span>")
qdel(src)
// Create a temporary object to represent the damage
@@ -73,7 +73,6 @@
else
M.heal_organ_damage(heal_brute, heal_burn)
M.updatehealth()
user.visible_message("<span class='green'>[user] applies [src] on [M].</span>", \
"<span class='green'>You apply [src] on [M].</span>")
use(1)
+1 -4
View File
@@ -15,9 +15,7 @@
if(istype(M,/mob/living/silicon/robot)) //Repairing cyborgs
var/mob/living/silicon/robot/R = M
if(R.getBruteLoss() || R.getFireLoss() )
R.adjustBruteLoss(-15)
R.adjustFireLoss(-15)
R.updatehealth()
R.heal_overall_damage(15, 15)
use(1)
user.visible_message("<span class='notice'>\The [user] applied some [src] at [R]'s damaged areas.</span>",\
"<span class='notice'>You apply some [src] at [R]'s damaged areas.</span>")
@@ -31,7 +29,6 @@
if(S && S.is_robotic())
if(S.get_damage())
S.heal_damage(15, 15, robo_repair = 1)
H.updatehealth()
use(1)
user.visible_message("<span class='notice'>\The [user] applies some nanite paste at[user != M ? " \the [M]'s" : " \the"][S.name] with \the [src].</span>",\
"<span class='notice'>You apply some nanite paste at [user == M ? "your" : "[M]'s"] [S.name].</span>")
-2
View File
@@ -332,7 +332,6 @@
"<span class='userdanger'>[user] has touched [H.name] with [src]!</span>")
H.adjustStaminaLoss(50)
H.Weaken(5)
H.updatehealth() //forces health update before next life tick
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
H.emote("gasp")
if(!H.undergoing_cardiac_arrest() && (prob(10) || defib.combat)) // Your heart explodes.
@@ -479,7 +478,6 @@
"<span class='userdanger'>[user] has touched [H.name] with [src]!</span>")
H.adjustStaminaLoss(50)
H.Weaken(5)
H.updatehealth() //forces health update before next life tick
if(!H.undergoing_cardiac_arrest() && prob(10)) // Your heart explodes.
H.set_heartattack(TRUE)
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, 1, -1)
+36 -1
View File
@@ -60,7 +60,7 @@
if(nadeassembly)
nadeassembly.attack_self(user)
return
var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num
var/newtime = input(usr, "Please set the timer.", "Timer", det_time) as num
if(user.is_in_active_hand(src))
newtime = Clamp(newtime, 10, 60000)
det_time = newtime
@@ -231,3 +231,38 @@
CB.prime()
..()
/obj/item/grenade/plastic/x4/thermite
name = "T4"
desc = "A wall breaching charge, containing fuel, metal oxide and metal powder mixed in just the right way. One hell of a combination. Effective against walls, ineffective against airlocks..."
det_time = 2
icon_state = "t4breach0"
item_state = "t4breach"
/obj/item/grenade/plastic/x4/thermite/prime()
var/turf/location
if(target)
if(!QDELETED(target))
location = get_turf(target)
target.overlays -= image_overlay
else
location = get_turf(src)
if(location)
var/datum/effect_system/smoke_spread/smoke = new
smoke.set_up(8,0, location, aim_dir)
if(target && target.density)
var/turf/T = get_step(location, aim_dir)
for(var/turf/simulated/wall/W in range(1, location))
W.thermitemelt(speed = 30)
addtimer(CALLBACK(null, .proc/explosion, T, 0, 0, 2), 3)
addtimer(CALLBACK(smoke, /datum/effect_system/smoke_spread/.proc/start), 3)
else
addtimer(CALLBACK(null, .proc/explosion, T, 0, 0, 2), 3)
addtimer(CALLBACK(smoke, /datum/effect_system/smoke_spread/.proc/start), 3)
if(isliving(target))
var/mob/living/M = target
M.adjust_fire_stacks(2)
M.IgniteMob()
qdel(src)
+2 -1
View File
@@ -56,7 +56,6 @@
var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand")
if(affecting.receive_damage( 0, 5 )) //INFERNO
H.UpdateDamageIcon()
H.updatehealth()
user.visible_message("<span class='notice'>After a few attempts, [user] manages to light the [src], [user.p_they()] however burn[user.p_s()] [user.p_their()] finger in the process.</span>")
set_light(2)
@@ -184,6 +183,7 @@
attack_verb = list("burnt","singed")
processing_objects.Add(src)
update_icon()
return TRUE
/obj/item/match/proc/matchburnout()
if(lit)
@@ -197,6 +197,7 @@
desc = "A match. This one has seen better days."
attack_verb = list("flicked")
processing_objects.Remove(src)
return TRUE
/obj/item/match/dropped(mob/user)
matchburnout()
+1 -3
View File
@@ -50,7 +50,6 @@
to_chat(H, "<span class='warning'>[src] cuts into your hand!</span>")
if(affecting.receive_damage(force*0.5))
H.UpdateDamageIcon()
H.updatehealth()
/obj/item/shard/attackby(obj/item/I, mob/user, params)
if(iswelder(I))
@@ -87,7 +86,6 @@
H.Weaken(3)
if(affecting.receive_damage(5, 0))
H.UpdateDamageIcon()
H.updatehealth()
..()
/obj/item/shard/plasma
@@ -126,4 +124,4 @@
to_chat(usr, "You add the newly-formed plasma glass to the stack. It now contains [NG.amount] sheets.")
qdel(src)
else
return ..()
return ..()
@@ -246,6 +246,15 @@
new /obj/item/grenade/flashbang(src)
update_icon()
/obj/item/storage/belt/security/response_team_gamma/New()
..()
new /obj/item/melee/baton/loaded(src)
new /obj/item/reagent_containers/spray/pepper(src)
new /obj/item/flash(src)
new /obj/item/grenade/flashbang(src)
new /obj/item/grenade/flashbang(src)
update_icon()
/obj/item/storage/belt/soulstone
name = "soul stone belt"
desc = "Designed for ease of access to the shards during a fight, as to not let a single enemy spirit slip away"
@@ -123,3 +123,13 @@
new /obj/item/clothing/accessory/medal/conduct(src)
new /obj/item/clothing/accessory/medal/conduct(src)
new /obj/item/clothing/accessory/medal/gold/captain(src)
/obj/item/storage/lockbox/t4
name = "lockbox (T4)"
desc = "Contains three T4 breaching charges."
req_access = list(access_cent_specops)
/obj/item/storage/lockbox/t4/New()
..()
for(var/i = 0, i < 3, i++)
new /obj/item/grenade/plastic/x4/thermite(src)
@@ -166,7 +166,7 @@
if(display_contents_with_number)
for(var/datum/numbered_display/ND in display_contents)
ND.sample_object.mouse_opacity = 2
ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE
ND.sample_object.screen_loc = "[cx]:16,[cy]:16"
ND.sample_object.maptext = "<font color='white'>[(ND.number > 1)? "[ND.number]" : ""]</font>"
ND.sample_object.layer = 20
@@ -177,7 +177,7 @@
cy--
else
for(var/obj/O in contents)
O.mouse_opacity = 2 //This is here so storage items that spawn with contents correctly have the "click around item to equip"
O.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip"
O.screen_loc = "[cx]:16,[cy]:16"
O.maptext = ""
O.layer = 20
@@ -309,7 +309,7 @@
src.orient2hud(usr)
if(usr.s_active)
usr.s_active.show_to(usr)
W.mouse_opacity = 2 //So you can click on the area around the item to equip it, instead of having to pixel hunt
W.mouse_opacity = MOUSE_OPACITY_OPAQUE //So you can click on the area around the item to equip it, instead of having to pixel hunt
update_icon()
return 1
+13 -6
View File
@@ -14,6 +14,7 @@
var/status = 0
var/obj/item/stock_parts/cell/high/bcell = null
var/hitcost = 1000
var/throw_hit_chance = 35
/obj/item/melee/baton/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is putting the live [name] in [user.p_their()] mouth! It looks like [user.p_theyre()] trying to commit suicide.</span>")
@@ -28,6 +29,11 @@
QDEL_NULL(bcell)
return ..()
/obj/item/melee/baton/throw_impact(atom/hit_atom)
..()
if(status && prob(throw_hit_chance))
baton_stun(hit_atom)
/obj/item/melee/baton/loaded/New() //this one starts with a cell pre-installed.
..()
bcell = new(src)
@@ -138,15 +144,17 @@
if(H.check_shields(0, "[user]'s [name]", src, MELEE_ATTACK)) //No message; check_shields() handles that
playsound(L, 'sound/weapons/Genhit.ogg', 50, 1)
return
user.lastattacked = L
L.lastattacker = user
L.Stun(stunforce)
L.Weaken(stunforce)
L.apply_effect(STUTTER, stunforce)
L.visible_message("<span class='danger'>[user] has stunned [L] with [src]!</span>", \
"<span class='userdanger'>[user] has stunned you with [src]!</span>")
if(user)
user.lastattacked = L
L.lastattacker = user
L.visible_message("<span class='danger'>[user] has stunned [L] with [src]!</span>", \
"<span class='userdanger'>[user] has stunned you with [src]!</span>")
add_attack_logs(user, L, "stunned")
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
if(isrobot(loc))
@@ -160,8 +168,6 @@
var/mob/living/carbon/human/H = L
H.forcesay(hit_appends)
add_attack_logs(user, L, "Stunned with [src]")
/obj/item/melee/baton/emp_act(severity)
if(bcell)
deductcharge(1000 / severity)
@@ -193,6 +199,7 @@
throwforce = 5
stunforce = 5
hitcost = 2000
throw_hit_chance = 10
slot_flags = SLOT_BACK
var/obj/item/assembly/igniter/sparkler = null
@@ -315,7 +315,7 @@
desc = "A frozen shell of ice containing nanofrost that freezes the surrounding area after activation."
icon = 'icons/effects/effects.dmi'
icon_state = "frozen_smoke_capsule"
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
pass_flags = PASSTABLE
/obj/effect/nanofrost_container/proc/Smoke()

Some files were not shown because too many files have changed in this diff Show More