mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-25 21:19:44 +01:00
Merge remote-tracking branch 'polaris/master' into pl-chemistry
This commit is contained in:
@@ -234,6 +234,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
|
||||
|
||||
/datum/controller/air_system/proc/remove_zone(zone/z)
|
||||
zones.Remove(z)
|
||||
zones_to_update.Remove(z)
|
||||
|
||||
/datum/controller/air_system/proc/air_blocked(turf/A, turf/B)
|
||||
#ifdef ZASDBG
|
||||
|
||||
+3
-2
@@ -108,11 +108,12 @@ Class Procs:
|
||||
c_invalidate()
|
||||
for(var/turf/simulated/T in contents)
|
||||
into.add(T)
|
||||
T.update_graphic(graphic_remove = air.graphic)
|
||||
#ifdef ZASDBG
|
||||
T.dbg(merged)
|
||||
#endif
|
||||
|
||||
//rebuild the old zone's edges so that the will be possesed by the new zone
|
||||
|
||||
//rebuild the old zone's edges so that they will be possessed by the new zone
|
||||
for(var/connection_edge/E in edges)
|
||||
if(E.contains_zone(into))
|
||||
continue //don't need to rebuild this edge
|
||||
|
||||
@@ -91,7 +91,7 @@ var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret
|
||||
|
||||
// Will not bother pumping or filtering if the gas source as fewer than this amount of moles, to help with performance.
|
||||
#define MINIMUM_MOLES_TO_PUMP 0.01
|
||||
#define MINIMUM_MOLES_TO_FILTER 0.1
|
||||
#define MINIMUM_MOLES_TO_FILTER 0.04
|
||||
|
||||
// The flow rate/effectiveness of various atmos devices is limited by their internal volume,
|
||||
// so for many atmos devices these will control maximum flow rates in L/s.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#define TARGET_CAN_MOVE 1
|
||||
#define TARGET_CAN_RUN 2
|
||||
#define TARGET_CAN_CLICK 4
|
||||
#define TARGET_CAN_RADIO 8
|
||||
+12
-14
@@ -38,8 +38,10 @@
|
||||
* mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed
|
||||
*/
|
||||
/mob/proc/ClickOn(var/atom/A, var/params)
|
||||
|
||||
if(world.time <= next_click) // Hard check, before anything else, to avoid crashing
|
||||
return
|
||||
|
||||
next_click = world.time + 1
|
||||
|
||||
if(client.buildmode)
|
||||
@@ -49,19 +51,19 @@
|
||||
var/list/modifiers = params2list(params)
|
||||
if(modifiers["shift"] && modifiers["ctrl"])
|
||||
CtrlShiftClickOn(A)
|
||||
return
|
||||
return 1
|
||||
if(modifiers["middle"])
|
||||
MiddleClickOn(A)
|
||||
return
|
||||
return 1
|
||||
if(modifiers["shift"])
|
||||
ShiftClickOn(A)
|
||||
return
|
||||
return 0
|
||||
if(modifiers["alt"]) // alt and alt-gr (rightalt)
|
||||
AltClickOn(A)
|
||||
return
|
||||
return 1
|
||||
if(modifiers["ctrl"])
|
||||
CtrlClickOn(A)
|
||||
return
|
||||
return 1
|
||||
|
||||
if(stat || paralysis || stunned || weakened)
|
||||
return
|
||||
@@ -80,17 +82,14 @@
|
||||
if(restrained())
|
||||
setClickCooldown(10)
|
||||
RestrainedClickOn(A)
|
||||
return
|
||||
return 1
|
||||
|
||||
if(in_throw_mode)
|
||||
if(isturf(A) || isturf(A.loc))
|
||||
throw_item(A)
|
||||
return
|
||||
return 1
|
||||
throw_mode_off()
|
||||
|
||||
if(!istype(A, /obj/item/weapon/gun) && !isturf(A) && !istype(A, /obj/screen))
|
||||
last_target_click = world.time
|
||||
|
||||
var/obj/item/W = get_active_hand()
|
||||
|
||||
if(W == A) // Handle attack_self
|
||||
@@ -99,7 +98,7 @@
|
||||
update_inv_l_hand(0)
|
||||
else
|
||||
update_inv_r_hand(0)
|
||||
return
|
||||
return 1
|
||||
|
||||
//Atoms on your person
|
||||
// A is your location but is not a turf; or is on you (backpack); or is on something on you (box in backpack); sdepth is needed here because contents depth does not equate inventory storage depth.
|
||||
@@ -117,7 +116,7 @@
|
||||
if(ismob(A)) // No instant mob attacking
|
||||
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
UnarmedAttack(A, 1)
|
||||
return
|
||||
return 1
|
||||
|
||||
if(!isturf(loc)) // This is going to stop you from telekinesing from inside a closet, but I don't shed many tears for that
|
||||
return
|
||||
@@ -144,8 +143,7 @@
|
||||
W.afterattack(A, src, 0, params) // 0: not Adjacent
|
||||
else
|
||||
RangedAttack(A, params)
|
||||
|
||||
return
|
||||
return 1
|
||||
|
||||
/mob/proc/setClickCooldown(var/timeout)
|
||||
next_move = max(world.time + timeout, next_move)
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/obj/screen/gun
|
||||
name = "gun"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
master = null
|
||||
dir = 2
|
||||
|
||||
/obj/screen/gun/Click(location, control, params)
|
||||
if(!usr)
|
||||
return
|
||||
return 1
|
||||
|
||||
/obj/screen/gun/move
|
||||
name = "Allow Movement"
|
||||
icon_state = "no_walk0"
|
||||
screen_loc = ui_gun2
|
||||
|
||||
/obj/screen/gun/move/Click(location, control, params)
|
||||
if(..())
|
||||
var/mob/living/user = usr
|
||||
if(istype(user))
|
||||
if(!user.aiming) user.aiming = new(user)
|
||||
user.aiming.toggle_permission(TARGET_CAN_MOVE)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/screen/gun/item
|
||||
name = "Allow Item Use"
|
||||
icon_state = "no_item0"
|
||||
screen_loc = ui_gun1
|
||||
|
||||
/obj/screen/gun/item/Click(location, control, params)
|
||||
if(..())
|
||||
var/mob/living/user = usr
|
||||
if(istype(user))
|
||||
if(!user.aiming) user.aiming = new(user)
|
||||
user.aiming.toggle_permission(TARGET_CAN_CLICK)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/screen/gun/mode
|
||||
name = "Toggle Gun Mode"
|
||||
icon_state = "gun0"
|
||||
screen_loc = ui_gun_select
|
||||
|
||||
/obj/screen/gun/mode/Click(location, control, params)
|
||||
if(..())
|
||||
var/mob/living/user = usr
|
||||
if(istype(user))
|
||||
if(!user.aiming) user.aiming = new(user)
|
||||
user.aiming.toggle_active()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/screen/gun/radio
|
||||
name = "Allow Radio Use"
|
||||
icon_state = "no_radio0"
|
||||
screen_loc = ui_gun4
|
||||
|
||||
/obj/screen/gun/radio/Click(location, control, params)
|
||||
if(..())
|
||||
var/mob/living/user = usr
|
||||
if(istype(user))
|
||||
if(!user.aiming) user.aiming = new(user)
|
||||
user.aiming.toggle_permission(TARGET_CAN_RADIO)
|
||||
return 1
|
||||
return 0
|
||||
@@ -257,8 +257,6 @@ datum/hud/New(mob/owner)
|
||||
human_hud(ui_style, ui_color, ui_alpha, mymob) // Pass the player the UI style chosen in preferences
|
||||
else if(isrobot(mymob))
|
||||
robot_hud()
|
||||
else if(issmall(mymob))
|
||||
monkey_hud(ui_style, ui_color, ui_alpha)
|
||||
else if(isbrain(mymob))
|
||||
brain_hud(ui_style)
|
||||
else if(isalien(mymob))
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255, var/mob/living/carbon/human/target)
|
||||
/mob/living/carbon/human/instantiate_hud(var/datum/hud/HUD, var/ui_style, var/ui_color, var/ui_alpha)
|
||||
HUD.human_hud(ui_style, ui_color, ui_alpha, src)
|
||||
|
||||
/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255, var/mob/living/carbon/human/target)
|
||||
var/datum/hud_data/hud_data
|
||||
if(!istype(target))
|
||||
hud_data = new()
|
||||
@@ -354,17 +356,11 @@
|
||||
mymob.gun_move_icon.color = ui_color
|
||||
mymob.gun_move_icon.alpha = ui_alpha
|
||||
|
||||
mymob.gun_run_icon = new /obj/screen/gun/run(null)
|
||||
mymob.gun_run_icon.icon = ui_style
|
||||
mymob.gun_run_icon.color = ui_color
|
||||
mymob.gun_run_icon.alpha = ui_alpha
|
||||
|
||||
mymob.radio_use_icon = new /obj/screen/gun/radio(null)
|
||||
mymob.radio_use_icon.icon = ui_style
|
||||
mymob.radio_use_icon.color = ui_color
|
||||
mymob.radio_use_icon.alpha = ui_alpha
|
||||
|
||||
|
||||
mymob.client.screen = null
|
||||
|
||||
mymob.client.screen += hud_elements
|
||||
|
||||
@@ -1,282 +0,0 @@
|
||||
/datum/hud/proc/monkey_hud(var/ui_style='icons/mob/screen1_old.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255)
|
||||
|
||||
src.adding = list()
|
||||
src.other = list()
|
||||
|
||||
var/obj/screen/using
|
||||
var/obj/screen/inventory/inv_box
|
||||
|
||||
using = new /obj/screen()
|
||||
using.name = "act_intent"
|
||||
using.icon = ui_style
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
using.icon_state = mymob.a_intent
|
||||
using.screen_loc = ui_acti
|
||||
using.layer = 20
|
||||
src.adding += using
|
||||
action_intent = using
|
||||
|
||||
//intent small hud objects
|
||||
var/icon/ico
|
||||
|
||||
ico = new(ui_style, "black")
|
||||
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
|
||||
ico.DrawBox(rgb(255,255,255,1),1,ico.Height()/2,ico.Width()/2,ico.Height())
|
||||
using = new /obj/screen( src )
|
||||
using.name = I_HELP
|
||||
using.icon = ico
|
||||
using.screen_loc = ui_acti
|
||||
using.layer = 21
|
||||
src.adding += using
|
||||
help_intent = using
|
||||
|
||||
ico = new(ui_style, "black")
|
||||
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
|
||||
ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,ico.Height()/2,ico.Width(),ico.Height())
|
||||
using = new /obj/screen( src )
|
||||
using.name = I_DISARM
|
||||
using.icon = ico
|
||||
using.screen_loc = ui_acti
|
||||
using.layer = 21
|
||||
src.adding += using
|
||||
disarm_intent = using
|
||||
|
||||
ico = new(ui_style, "black")
|
||||
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
|
||||
ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,1,ico.Width(),ico.Height()/2)
|
||||
using = new /obj/screen( src )
|
||||
using.name = I_GRAB
|
||||
using.icon = ico
|
||||
using.screen_loc = ui_acti
|
||||
using.layer = 21
|
||||
src.adding += using
|
||||
grab_intent = using
|
||||
|
||||
ico = new(ui_style, "black")
|
||||
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
|
||||
ico.DrawBox(rgb(255,255,255,1),1,1,ico.Width()/2,ico.Height()/2)
|
||||
using = new /obj/screen( src )
|
||||
using.name = I_HURT
|
||||
using.icon = ico
|
||||
using.screen_loc = ui_acti
|
||||
using.layer = 21
|
||||
src.adding += using
|
||||
hurt_intent = using
|
||||
|
||||
//end intent small hud objects
|
||||
|
||||
using = new /obj/screen()
|
||||
using.name = "mov_intent"
|
||||
using.icon = ui_style
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
using.icon_state = (mymob.m_intent == "run" ? "running" : "walking")
|
||||
using.screen_loc = ui_movi
|
||||
using.layer = 20
|
||||
src.adding += using
|
||||
move_intent = using
|
||||
|
||||
using = new /obj/screen()
|
||||
using.name = "drop"
|
||||
using.icon = ui_style
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
using.icon_state = "act_drop"
|
||||
using.screen_loc = ui_drop_throw
|
||||
using.layer = 19
|
||||
src.adding += using
|
||||
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.name = "r_hand"
|
||||
inv_box.icon = ui_style
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
inv_box.icon_state = "r_hand_inactive"
|
||||
if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use
|
||||
inv_box.icon_state = "hand_active"
|
||||
inv_box.screen_loc = ui_rhand
|
||||
inv_box.slot_id = slot_r_hand
|
||||
inv_box.layer = 19
|
||||
src.r_hand_hud_object = inv_box
|
||||
src.adding += inv_box
|
||||
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.name = "l_hand"
|
||||
inv_box.icon = ui_style
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
inv_box.icon_state = "l_hand_inactive"
|
||||
if(mymob && mymob.hand) //This being 1 means the left hand is in use
|
||||
inv_box.icon_state = "hand_active"
|
||||
inv_box.screen_loc = ui_lhand
|
||||
inv_box.slot_id = slot_l_hand
|
||||
inv_box.layer = 19
|
||||
src.l_hand_hud_object = inv_box
|
||||
src.adding += inv_box
|
||||
|
||||
using = new /obj/screen/inventory()
|
||||
using.name = "hand"
|
||||
using.icon = ui_style
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
using.icon_state = "hand1"
|
||||
using.screen_loc = ui_swaphand1
|
||||
using.layer = 19
|
||||
src.adding += using
|
||||
|
||||
using = new /obj/screen/inventory()
|
||||
using.name = "hand"
|
||||
using.icon = ui_style
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
using.icon_state = "hand2"
|
||||
using.screen_loc = ui_swaphand2
|
||||
using.layer = 19
|
||||
src.adding += using
|
||||
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.name = "mask"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.color = ui_color
|
||||
inv_box.alpha = ui_alpha
|
||||
inv_box.icon_state = "equip"
|
||||
inv_box.screen_loc = ui_monkey_mask
|
||||
inv_box.slot_id = slot_wear_mask
|
||||
inv_box.layer = 19
|
||||
src.adding += inv_box
|
||||
|
||||
inv_box = new /obj/screen/inventory()
|
||||
inv_box.name = "back"
|
||||
inv_box.icon = ui_style
|
||||
inv_box.color = ui_color
|
||||
inv_box.alpha = ui_alpha
|
||||
inv_box.icon_state = "equip"
|
||||
inv_box.screen_loc = ui_back
|
||||
inv_box.slot_id = slot_back
|
||||
inv_box.layer = 19
|
||||
src.adding += inv_box
|
||||
|
||||
mymob.throw_icon = new /obj/screen()
|
||||
mymob.throw_icon.icon = ui_style
|
||||
mymob.throw_icon.color = ui_color
|
||||
mymob.throw_icon.alpha = ui_alpha
|
||||
mymob.throw_icon.icon_state = "act_throw_off"
|
||||
mymob.throw_icon.name = "throw"
|
||||
mymob.throw_icon.screen_loc = ui_drop_throw
|
||||
|
||||
mymob.oxygen = new /obj/screen()
|
||||
mymob.oxygen.icon = ui_style
|
||||
mymob.oxygen.color = ui_color
|
||||
mymob.oxygen.alpha = ui_alpha
|
||||
mymob.oxygen.icon_state = "oxy0"
|
||||
mymob.oxygen.name = "oxygen"
|
||||
mymob.oxygen.screen_loc = ui_oxygen
|
||||
|
||||
mymob.pressure = new /obj/screen()
|
||||
mymob.pressure.icon = ui_style
|
||||
mymob.pressure.color = ui_color
|
||||
mymob.pressure.alpha = ui_alpha
|
||||
mymob.pressure.icon_state = "pressure0"
|
||||
mymob.pressure.name = "pressure"
|
||||
mymob.pressure.screen_loc = ui_pressure
|
||||
|
||||
mymob.toxin = new /obj/screen()
|
||||
mymob.toxin.icon = ui_style
|
||||
mymob.toxin.color = ui_color
|
||||
mymob.toxin.alpha = ui_alpha
|
||||
mymob.toxin.icon_state = "tox0"
|
||||
mymob.toxin.name = "toxin"
|
||||
mymob.toxin.screen_loc = ui_toxin
|
||||
|
||||
mymob.internals = new /obj/screen()
|
||||
mymob.internals.icon = ui_style
|
||||
mymob.internals.color = ui_color
|
||||
mymob.internals.alpha = ui_alpha
|
||||
mymob.internals.icon_state = "internal0"
|
||||
mymob.internals.name = "internal"
|
||||
mymob.internals.screen_loc = ui_internal
|
||||
|
||||
mymob.fire = new /obj/screen()
|
||||
mymob.fire.icon = ui_style
|
||||
mymob.fire.color = ui_color
|
||||
mymob.fire.alpha = ui_alpha
|
||||
mymob.fire.icon_state = "fire0"
|
||||
mymob.fire.name = "fire"
|
||||
mymob.fire.screen_loc = ui_fire
|
||||
|
||||
mymob.bodytemp = new /obj/screen()
|
||||
mymob.bodytemp.icon = ui_style
|
||||
mymob.bodytemp.color = ui_color
|
||||
mymob.bodytemp.alpha = ui_alpha
|
||||
mymob.bodytemp.icon_state = "temp1"
|
||||
mymob.bodytemp.name = "body temperature"
|
||||
mymob.bodytemp.screen_loc = ui_temp
|
||||
|
||||
mymob.healths = new /obj/screen()
|
||||
mymob.healths.icon = ui_style
|
||||
mymob.healths.color = ui_color
|
||||
mymob.healths.alpha = ui_alpha
|
||||
mymob.healths.icon_state = "health0"
|
||||
mymob.healths.name = "health"
|
||||
mymob.healths.screen_loc = ui_health
|
||||
|
||||
mymob.pullin = new /obj/screen()
|
||||
mymob.pullin.icon = ui_style
|
||||
mymob.pullin.color = ui_color
|
||||
mymob.pullin.alpha = ui_alpha
|
||||
mymob.pullin.icon_state = "pull0"
|
||||
mymob.pullin.name = "pull"
|
||||
mymob.pullin.screen_loc = ui_pull_resist
|
||||
|
||||
mymob.blind = new /obj/screen()
|
||||
mymob.blind.icon = 'icons/mob/screen1_full.dmi'
|
||||
mymob.blind.icon_state = "blackimageoverlay"
|
||||
mymob.blind.name = " "
|
||||
mymob.blind.screen_loc = "1,1"
|
||||
mymob.blind.layer = 0
|
||||
|
||||
mymob.flash = new /obj/screen()
|
||||
mymob.flash.icon = ui_style
|
||||
mymob.flash.icon_state = "blank"
|
||||
mymob.flash.name = "flash"
|
||||
mymob.flash.screen_loc = ui_entire_screen
|
||||
mymob.flash.layer = 17
|
||||
|
||||
mymob.zone_sel = new /obj/screen/zone_sel()
|
||||
mymob.zone_sel.icon = ui_style
|
||||
mymob.zone_sel.color = ui_color
|
||||
mymob.zone_sel.alpha = ui_alpha
|
||||
mymob.zone_sel.overlays.Cut()
|
||||
mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]")
|
||||
|
||||
//Handle the gun settings buttons
|
||||
mymob.gun_setting_icon = new /obj/screen/gun/mode(null)
|
||||
if (mymob.client)
|
||||
if (mymob.client.gun_mode) // If in aim mode, correct the sprite
|
||||
mymob.gun_setting_icon.set_dir(2)
|
||||
for(var/obj/item/weapon/gun/G in mymob) // If targeting someone, display other buttons
|
||||
if (G.aim_targets)
|
||||
mymob.item_use_icon = new /obj/screen/gun/item(null)
|
||||
if (mymob.client.target_can_click)
|
||||
mymob.item_use_icon.set_dir(1)
|
||||
src.adding += mymob.item_use_icon
|
||||
mymob.radio_use_icon = new /obj/screen/gun/radio(null)
|
||||
if (mymob.client.target_can_radio)
|
||||
mymob.radio_use_icon.set_dir(1)
|
||||
src.adding += mymob.radio_use_icon
|
||||
mymob.gun_move_icon = new /obj/screen/gun/move(null)
|
||||
if (mymob.client.target_can_move)
|
||||
mymob.gun_move_icon.set_dir(1)
|
||||
mymob.gun_run_icon = new /obj/screen/gun/run(null)
|
||||
if (mymob.client.target_can_run)
|
||||
mymob.gun_run_icon.set_dir(1)
|
||||
src.adding += mymob.gun_run_icon
|
||||
src.adding += mymob.gun_move_icon
|
||||
|
||||
mymob.client.screen = null
|
||||
|
||||
mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.pullin, mymob.blind, mymob.flash, mymob.gun_setting_icon) //, mymob.hands, mymob.rest, mymob.sleep, mymob.mach )
|
||||
mymob.client.screen += src.adding + src.other
|
||||
|
||||
return
|
||||
@@ -153,31 +153,13 @@ var/obj/screen/robot_inventory
|
||||
|
||||
//Handle the gun settings buttons
|
||||
mymob.gun_setting_icon = new /obj/screen/gun/mode(null)
|
||||
if (mymob.client)
|
||||
if (mymob.client.gun_mode) // If in aim mode, correct the sprite
|
||||
mymob.gun_setting_icon.set_dir(2)
|
||||
for(var/obj/item/weapon/gun/G in mymob) // If targeting someone, display other buttons
|
||||
if (G.aim_targets)
|
||||
mymob.item_use_icon = new /obj/screen/gun/item(null)
|
||||
if (mymob.client.target_can_click)
|
||||
mymob.item_use_icon.set_dir(1)
|
||||
src.adding += mymob.item_use_icon
|
||||
mymob.radio_use_icon = new /obj/screen/gun/radio(null)
|
||||
if (mymob.client.target_can_radio)
|
||||
mymob.radio_use_icon.set_dir(1)
|
||||
src.adding += mymob.radio_use_icon
|
||||
mymob.gun_move_icon = new /obj/screen/gun/move(null)
|
||||
if (mymob.client.target_can_move)
|
||||
mymob.gun_move_icon.set_dir(1)
|
||||
mymob.gun_run_icon = new /obj/screen/gun/run(null)
|
||||
if (mymob.client.target_can_run)
|
||||
mymob.gun_run_icon.set_dir(1)
|
||||
src.adding += mymob.gun_run_icon
|
||||
src.adding += mymob.gun_move_icon
|
||||
mymob.item_use_icon = new /obj/screen/gun/item(null)
|
||||
mymob.gun_move_icon = new /obj/screen/gun/move(null)
|
||||
mymob.radio_use_icon = new /obj/screen/gun/radio(null)
|
||||
|
||||
mymob.client.screen = null
|
||||
|
||||
mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.blind, mymob.flash, mymob.gun_setting_icon, robot_inventory) //, mymob.rest, mymob.sleep, mymob.mach )
|
||||
mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.blind, mymob.flash, robot_inventory, mymob.gun_setting_icon)
|
||||
mymob.client.screen += src.adding + src.other
|
||||
|
||||
return
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
layer = 20.0
|
||||
unacidable = 1
|
||||
var/obj/master = null //A reference to the object in the slot. Grabs or items, generally.
|
||||
var/gun_click_time = -100 //I'm lazy.
|
||||
|
||||
/obj/screen/Destroy()
|
||||
master = null
|
||||
@@ -95,38 +94,6 @@
|
||||
usr.ClickOn(master)
|
||||
return 1
|
||||
|
||||
/obj/screen/gun
|
||||
name = "gun"
|
||||
icon = 'icons/mob/screen1.dmi'
|
||||
master = null
|
||||
dir = 2
|
||||
|
||||
move
|
||||
name = "Allow Walking"
|
||||
icon_state = "no_walk0"
|
||||
screen_loc = ui_gun2
|
||||
|
||||
run
|
||||
name = "Allow Running"
|
||||
icon_state = "no_run0"
|
||||
screen_loc = ui_gun3
|
||||
|
||||
item
|
||||
name = "Allow Item Use"
|
||||
icon_state = "no_item0"
|
||||
screen_loc = ui_gun1
|
||||
|
||||
mode
|
||||
name = "Toggle Gun Mode"
|
||||
icon_state = "gun0"
|
||||
screen_loc = ui_gun_select
|
||||
//dir = 1
|
||||
|
||||
radio
|
||||
name = "Allow Radio Use"
|
||||
icon_state = "no_radio0"
|
||||
screen_loc = ui_gun4
|
||||
|
||||
/obj/screen/zone_sel
|
||||
name = "damage zone"
|
||||
icon_state = "zone_sel"
|
||||
@@ -201,7 +168,6 @@
|
||||
|
||||
/obj/screen/Click(location, control, params)
|
||||
if(!usr) return 1
|
||||
|
||||
switch(name)
|
||||
if("toggle")
|
||||
if(usr.hud_used.inventory_shown)
|
||||
@@ -431,46 +397,6 @@
|
||||
if("module3")
|
||||
if(istype(usr, /mob/living/silicon/robot))
|
||||
usr:toggle_module(3)
|
||||
|
||||
if("Allow Walking", "Disallow Walking")
|
||||
if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
|
||||
return
|
||||
if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
|
||||
usr << "You need your gun in your active hand to do that!"
|
||||
return
|
||||
usr.client.AllowTargetMove()
|
||||
gun_click_time = world.time
|
||||
|
||||
if("Allow Running", "Disallow Running")
|
||||
if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
|
||||
return
|
||||
if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
|
||||
usr << "You need your gun in your active hand to do that!"
|
||||
return
|
||||
usr.client.AllowTargetRun()
|
||||
gun_click_time = world.time
|
||||
|
||||
if("Allow Item Use", "Disallow Item Use")
|
||||
if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
|
||||
return
|
||||
if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
|
||||
usr << "You need your gun in your active hand to do that!"
|
||||
return
|
||||
usr.client.AllowTargetClick()
|
||||
gun_click_time = world.time
|
||||
|
||||
if("Toggle Gun Mode")
|
||||
usr.client.ToggleGunMode()
|
||||
|
||||
if("Allow Radio Use", "Disallow Radio Use")
|
||||
if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
|
||||
return
|
||||
if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
|
||||
usr << "You need your gun in your active hand to do that!"
|
||||
return
|
||||
usr.client.AllowTargetRadio()
|
||||
gun_click_time = world.time
|
||||
|
||||
else
|
||||
return 0
|
||||
return 1
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
Exonet Protocol Version 2
|
||||
|
||||
This is designed to be a fairly simple fake-networking system, allowing you to send and receive messages
|
||||
between the exonet_protocol datums, and for atoms to react to those messages, based on the contents of the message.
|
||||
Hopefully, this can evolve to be a more robust fake-networking system and allow for some devious network hacking in the future.
|
||||
|
||||
Version 1 never existed.
|
||||
|
||||
*Setting up*
|
||||
|
||||
To set up the exonet link, define a variable on your desired atom it is like this;
|
||||
var/datum/exonet_protocol/exonet = null
|
||||
Afterwards, before you want to do networking, call exonet = New(src), then exonet.make_address(string), and give it a string to hash into the new IP.
|
||||
The reason it needs a string is so you can have the addresses be persistant, assuming no-one already took it first.
|
||||
|
||||
When you're no longer wanting to use the address and want to free it up, like when you want to Destroy() it, you need to call remove_address()
|
||||
|
||||
*Sending messages*
|
||||
|
||||
To send a message to another datum, you need to know it's EPv2 (fake IP) address. Once you know that, call send_message(), place your
|
||||
intended address in the first argument, then the message in the second. For example, send_message(exonet.address, "ping") will make you
|
||||
ping yourself.
|
||||
|
||||
*Receiving messages*
|
||||
You don't need to do anything special to receive the messages, other than give your target exonet datum an address as well. Once something hits
|
||||
your datum with send_message(), receive_message() is called, and the default action is to call receive_exonet_message() on the datum's holder.
|
||||
You'll want to override receive_exonet_message() on your atom, and define what will occur when the message is received.
|
||||
The receiving atom will receive the origin atom (the atom that sent the message), the origin address, and finally the message itself.
|
||||
It's suggested to start with an if or switch statement for the message, to determine what to do.
|
||||
*/
|
||||
|
||||
var/global/list/all_exonet_connections = list()
|
||||
|
||||
/datum/exonet_protocol
|
||||
var/address = "" //Resembles IPv6, but with only five 'groups', e.g. XXXX:XXXX:XXXX:XXXX:XXXX
|
||||
var/atom/movable/holder = null
|
||||
|
||||
/datum/exonet_protocol/New(var/atom/holder)
|
||||
src.holder = holder
|
||||
..()
|
||||
|
||||
|
||||
// Proc: make_address()
|
||||
// Parameters: 1 (string - used to make into a hash that will be part of the new address)
|
||||
// Description: Allocates a new address based on the string supplied. It results in consistant addresses for each round assuming it is not already taken..
|
||||
/datum/exonet_protocol/proc/make_address(var/string)
|
||||
if(string)
|
||||
var/new_address = null
|
||||
while(new_address == find_address(new_address)) //Collision test.
|
||||
var/hash = md5(string)
|
||||
var/raw_address = copytext(hash,1,25)
|
||||
var/addr_0 = "fc00" //Used for unique local address in real-life IPv6.
|
||||
var/addr_1 = hexadecimal_to_EPv2(raw_address)
|
||||
|
||||
new_address = "[addr_0]:[addr_1]"
|
||||
string = "[string]0" //If we did get a collision, this should make the next attempt not have one.
|
||||
sleep(1)
|
||||
address = new_address
|
||||
all_exonet_connections |= src
|
||||
|
||||
|
||||
// Proc: make_arbitrary_address()
|
||||
// Parameters: 1 (new_address - the desired address)
|
||||
// Description: Allocates that specific address, if it is available.
|
||||
/datum/exonet_protocol/proc/make_arbitrary_address(var/new_address)
|
||||
if(new_address)
|
||||
if(new_address == find_address(new_address) ) //Collision test.
|
||||
return 0
|
||||
address = new_address
|
||||
all_exonet_connections |= src
|
||||
return 1
|
||||
|
||||
// Proc: hexadecimal_to_EPv2()
|
||||
// Parameters: 1 (hex - a string of hexadecimals to convert)
|
||||
// Description: Helper proc to add colons to a string in the right places.
|
||||
/proc/hexadecimal_to_EPv2(var/hex)
|
||||
if(!hex)
|
||||
return null
|
||||
var/addr_1 = copytext(hex,1,5)
|
||||
var/addr_2 = copytext(hex,5,9)
|
||||
var/addr_3 = copytext(hex,9,13)
|
||||
var/addr_4 = copytext(hex,13,17)
|
||||
var/new_address = "[addr_1]:[addr_2]:[addr_3]:[addr_4]"
|
||||
return new_address
|
||||
|
||||
|
||||
// Proc: remove_address()
|
||||
// Parameters: None
|
||||
// Description: Deallocates the address, freeing it for use.
|
||||
/datum/exonet_protocol/proc/remove_address()
|
||||
address = ""
|
||||
all_exonet_connections.Remove(src)
|
||||
|
||||
|
||||
// Proc: find_address()
|
||||
// Parameters: 1 (target_address - the desired address to find)
|
||||
// Description: Searches the global list all_exonet_connections for a specific address, and returns it if found, otherwise returns null.
|
||||
/datum/exonet_protocol/proc/find_address(var/target_address)
|
||||
for(var/datum/exonet_protocol/exonet in all_exonet_connections)
|
||||
if(exonet.address == target_address)
|
||||
return exonet.address
|
||||
return null
|
||||
|
||||
// Proc: send_message()
|
||||
// Parameters: 2 (target_address - the desired address to send the message to, message - the message to send)
|
||||
// Description: Sends the message to target_address, by calling receive_message() on the desired datum.
|
||||
/datum/exonet_protocol/proc/send_message(var/target_address, var/message)
|
||||
if(!address)
|
||||
return 0
|
||||
for(var/datum/exonet_protocol/exonet in all_exonet_connections)
|
||||
if(exonet.address == target_address)
|
||||
exonet.receive_message(holder, address, message)
|
||||
break
|
||||
|
||||
// Proc: receive_message()
|
||||
// Parameters: 3 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent)
|
||||
// Description: Called when send_message() successfully reaches the intended datum. By default, calls receive_exonet_message() on the holder atom.
|
||||
/datum/exonet_protocol/proc/receive_message(var/atom/origin_atom, var/origin_address, var/message)
|
||||
holder.receive_exonet_message(origin_atom, origin_address, message)
|
||||
return
|
||||
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 3 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent)
|
||||
// Description: Override this to make your atom do something when a message is received.
|
||||
/atom/proc/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message)
|
||||
return
|
||||
@@ -8,7 +8,7 @@
|
||||
if(creator)
|
||||
parent = creator
|
||||
|
||||
var/global/datum/locations/milky_way/locations = new()
|
||||
var/global/datum/locations/milky_way/all_locations = new()
|
||||
|
||||
//Galaxy
|
||||
|
||||
@@ -26,6 +26,24 @@ var/global/datum/locations/milky_way/locations = new()
|
||||
new /datum/locations/uueoa_esa(src),
|
||||
new /datum/locations/vir(src)
|
||||
)
|
||||
|
||||
/proc/choose_location_datum(client/user)
|
||||
var/datum/locations/choice = all_locations
|
||||
while(length(choice.contents) > 0) //For some reason it wouldn't let me do contents.len even when I defined it as a list.
|
||||
var/specific = alert(user, "The location currently selected is [choice.name]. More specific options exist, would you like to pick a more specific location?",
|
||||
"Choose location", "Yes", "No")
|
||||
if(specific == "Yes" && length(choice.contents) > 0)
|
||||
choice = input(user, "Please choose a location.","Locations") as null|anything in choice.contents
|
||||
else
|
||||
break
|
||||
user << choice.name
|
||||
user << choice.desc
|
||||
return choice
|
||||
|
||||
// var/datum/locations/choice = input(user, "Please choose a location.","Locations") as null|anything in all_locations
|
||||
// if(choice && choice.contents.len > 0)
|
||||
|
||||
|
||||
/*
|
||||
/datum/locations/proc/show_contents()
|
||||
// world << "[src]\n[desc]"
|
||||
|
||||
@@ -52,6 +52,17 @@
|
||||
desc = "The Northern Star is an asteroid colony owned and operated by Nanotrasen, among many other asteroid installations. \
|
||||
Originally conceived as 'just another pitstop' for weary asteroid miners, it has grown to become a significant installation in the Kara subsystem."
|
||||
|
||||
/datum/locations/northern_star/New(var/creator)
|
||||
contents.Add(
|
||||
new /datum/locations/northern_star_interior(src)
|
||||
)
|
||||
..(creator)
|
||||
|
||||
/datum/locations/northern_star_interior
|
||||
name = "Northern Star Inner Level"
|
||||
desc = "The Northern Star contains multiple layers, this one being the inner level, also known as the residentual area. It contains most of the \
|
||||
homes for the Northern Star, as well as acting as the heart of commerece, with many shops and markets near the center."
|
||||
|
||||
/datum/locations/rota
|
||||
name = "Rota"
|
||||
desc = "A Neptune-like ice giant, with a beautiful ring system circling it. It is 165 kelvin (-157°C)."
|
||||
@@ -715,8 +715,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
/obj/item/weapon/gun/energy/gun,
|
||||
/obj/item/weapon/gun/energy/taser,
|
||||
/obj/item/weapon/gun/energy/taser,
|
||||
/obj/item/weapon/gun/projectile/sec,
|
||||
/obj/item/weapon/gun/projectile/sec,
|
||||
/obj/item/weapon/gun/projectile/colt/detective,
|
||||
/obj/item/weapon/gun/projectile/colt/detective,
|
||||
/obj/item/weapon/storage/box/flashbangs,
|
||||
/obj/item/weapon/storage/box/flashbangs)
|
||||
cost = 40
|
||||
|
||||
@@ -174,7 +174,6 @@
|
||||
w_class = 3.0
|
||||
origin_tech = list(TECH_MATERIAL = 1)
|
||||
var/breakouttime = 300 //Deciseconds = 30s = 0.5 minute
|
||||
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/handcuffs.dmi')
|
||||
|
||||
/obj/item/weapon/caution
|
||||
desc = "Caution! Wet Floor!"
|
||||
|
||||
@@ -86,8 +86,7 @@ var/datum/antagonist/raider/raiders
|
||||
/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
|
||||
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet,
|
||||
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn,
|
||||
/obj/item/weapon/gun/projectile/colt,
|
||||
/obj/item/weapon/gun/projectile/sec,
|
||||
/obj/item/weapon/gun/projectile/colt/detective,
|
||||
/obj/item/weapon/gun/projectile/pistol,
|
||||
/obj/item/weapon/gun/projectile/revolver,
|
||||
/obj/item/weapon/gun/projectile/pirate
|
||||
|
||||
@@ -561,6 +561,7 @@ area/space/atmosalert()
|
||||
icon_state = "yellow"
|
||||
requires_power = 0
|
||||
flags = RAD_SHIELDED
|
||||
base_turf = /turf/space
|
||||
|
||||
/area/syndicate_station/start
|
||||
name = "\improper Mercenary Forward Operating Base"
|
||||
@@ -620,6 +621,7 @@ area/space/atmosalert()
|
||||
name = "\improper Skipjack"
|
||||
icon_state = "yellow"
|
||||
requires_power = 0
|
||||
base_turf = /turf/space
|
||||
|
||||
/area/skipjack_station/start
|
||||
name = "\improper Skipjack"
|
||||
@@ -2760,7 +2762,7 @@ var/list/the_station_areas = list (
|
||||
lighting_use_dynamic = 0
|
||||
requires_power = 0
|
||||
var/sound/mysound = null
|
||||
|
||||
/*
|
||||
New()
|
||||
..()
|
||||
var/sound/S = new/sound()
|
||||
@@ -2808,4 +2810,4 @@ var/list/the_station_areas = list (
|
||||
H << S
|
||||
|
||||
spawn(60) .()
|
||||
|
||||
*/
|
||||
@@ -1,8 +1,8 @@
|
||||
// Returns the lowest turf available on a given Z-level, defaults to asteroid for Polaris.
|
||||
var/global/list/base_turf_by_z = list(
|
||||
"1" = /turf/simulated/floor/asteroid,
|
||||
"4" = /turf/simulated/floor/asteroid,
|
||||
"5" = /turf/simulated/floor/asteroid
|
||||
"1" = /turf/simulated/mineral/floor,
|
||||
"4" = /turf/simulated/mineral/floor,
|
||||
"5" = /turf/simulated/mineral/floor
|
||||
)
|
||||
|
||||
proc/get_base_turf(var/z)
|
||||
|
||||
@@ -72,8 +72,8 @@
|
||||
icon_state = "lingarmor"
|
||||
// item_state = "lingarmor"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
armor = list(melee = 85, bullet = 70, laser = 70, energy = 70, bomb = 70, bio = 0, rad = 0) //It costs 3 points, so it should be very protective.
|
||||
siemens_coefficient = 0.1
|
||||
armor = list(melee = 75, bullet = 60, laser = 60, energy = 60, bomb = 60, bio = 0, rad = 0) //It costs 3 points, so it should be very protective.
|
||||
siemens_coefficient = 0.3
|
||||
max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE
|
||||
slowdown = 3
|
||||
|
||||
@@ -92,8 +92,8 @@
|
||||
desc = "A tough, hard covering of black chitin with transparent chitin in front."
|
||||
icon_state = "lingarmorhelmet"
|
||||
// item_state = "lingarmorhelmet"
|
||||
armor = list(melee = 85, bullet = 70, laser = 70,energy = 70, bomb = 70, bio = 0, rad = 0)
|
||||
siemens_coefficient = 0.1
|
||||
armor = list(melee = 75, bullet = 60, laser = 60,energy = 60, bomb = 60, bio = 0, rad = 0)
|
||||
siemens_coefficient = 0.3
|
||||
max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE
|
||||
|
||||
/obj/item/clothing/head/helmet/space/changeling/armored/dropped()
|
||||
@@ -103,7 +103,7 @@
|
||||
name = "chitinous gauntlets"
|
||||
desc = "Very resilient gauntlets made out of black chitin. It looks very durable, and can probably resist electrical shock in addition to the elements."
|
||||
icon_state = "lingarmorgloves"
|
||||
armor = list(melee = 85, bullet = 70, laser = 70,energy = 70, bomb = 70, bio = 0, rad = 0) //No idea if glove armor gets checked
|
||||
armor = list(melee = 75, bullet = 60, laser = 60,energy = 60, bomb = 60, bio = 0, rad = 0) //No idea if glove armor gets checked
|
||||
siemens_coefficient = 0
|
||||
|
||||
/obj/item/clothing/shoes/combat/changeling //Noslips
|
||||
@@ -111,8 +111,8 @@
|
||||
name = "Footwear made out of a hard, black chitinous material. The bottoms of these appear to have spikes that can protrude or extract itself into and out \
|
||||
of the floor at will, granting the wearer stability."
|
||||
icon_state = "lingboots"
|
||||
armor = list(melee = 85, bullet = 70, laser = 70,energy = 70, bomb = 70, bio = 0, rad = 0)
|
||||
siemens_coefficient = 0.1
|
||||
armor = list(melee = 75, bullet = 60, laser = 70,energy = 60, bomb = 60, bio = 0, rad = 0)
|
||||
siemens_coefficient = 0.3
|
||||
cold_protection = FEET
|
||||
min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE
|
||||
heat_protection = FEET
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
if(T.reagents)
|
||||
T.reagents.add_reagent("cryotoxin", inject_amount)
|
||||
feedback_add_details("changeling_powers","CS")
|
||||
src.verbs -= /mob/proc/changeling_cryo_sting
|
||||
spawn(3 MINUTES)
|
||||
src << "<span class='notice'>Our cryogenic string is ready to be used once more.</span>"
|
||||
src.verbs |= /mob/proc/changeling_cryo_sting
|
||||
return 1
|
||||
|
||||
/datum/reagent/cryotoxin //A much more potent version of frost oil.
|
||||
@@ -34,7 +38,7 @@
|
||||
/datum/reagent/cryotoxin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
|
||||
if(alien == IS_DIONA)
|
||||
return
|
||||
M.bodytemperature = max(M.bodytemperature - 40 * TEMPERATURE_DAMAGE_COEFFICIENT, 0)
|
||||
M.bodytemperature = max(M.bodytemperature - 30 * TEMPERATURE_DAMAGE_COEFFICIENT, 0)
|
||||
if(prob(3))
|
||||
M.emote("shiver")
|
||||
..()
|
||||
|
||||
@@ -19,13 +19,18 @@
|
||||
i = i * 2
|
||||
src << "<span class='notice'>Our toxin will be extra potent, when it strikes.</span>"
|
||||
src.mind.changeling.recursive_enhancement = 0
|
||||
spawn(120) //Two minutes
|
||||
spawn(2 MINUTES)
|
||||
if(T) //We might not exist in two minutes, for whatever reason.
|
||||
T << "<span class='danger'>You feel a burning sensation flowing through your veins!</span>"
|
||||
while(i)
|
||||
T.adjustToxLoss(1)
|
||||
i--
|
||||
sleep(20)
|
||||
src.verbs -= /mob/proc/changeling_delayed_toxic_sting
|
||||
spawn(3 MINUTES)
|
||||
src << "<span class='notice'>We are ready to use our delayed toxic string once more.</span>"
|
||||
src.verbs |= /mob/proc/changeling_delayed_toxic_sting
|
||||
|
||||
feedback_add_details("changeling_powers","DTS")
|
||||
return 1
|
||||
|
||||
feedback_add_details("changeling_powers","DTS")
|
||||
return 1
|
||||
@@ -39,7 +39,7 @@
|
||||
if(!isbroken)
|
||||
if(prob(1+ damage * 5))
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] smashed the pylon!</span>",
|
||||
"<span class='danger'>[user] smashed the pylon!</span>",
|
||||
"<span class='warning'>You hit the pylon, and its crystal breaks apart!</span>",
|
||||
"You hear a tinkle of crystal shards"
|
||||
)
|
||||
@@ -137,39 +137,4 @@
|
||||
|
||||
var/mob/living/M = A
|
||||
|
||||
if(M.stat != DEAD)
|
||||
if(M.transforming)
|
||||
return
|
||||
if(M.has_brain_worms())
|
||||
return //Borer stuff - RR
|
||||
|
||||
if(iscultist(M)) return
|
||||
if(!ishuman(M) && !isrobot(M)) return
|
||||
|
||||
M.transforming = 1
|
||||
M.canmove = 0
|
||||
M.icon = null
|
||||
M.overlays.len = 0
|
||||
M.invisibility = 101
|
||||
|
||||
if(istype(M, /mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/Robot = M
|
||||
if(Robot.mmi)
|
||||
qdel(Robot.mmi)
|
||||
else
|
||||
for(var/obj/item/W in M)
|
||||
if(istype(W, /obj/item/weapon/implant))
|
||||
qdel(W)
|
||||
continue
|
||||
W.layer = initial(W.layer)
|
||||
W.loc = M.loc
|
||||
W.dropped(M)
|
||||
|
||||
var/mob/living/new_mob = new /mob/living/simple_animal/corgi(A.loc)
|
||||
new_mob.a_intent = I_HURT
|
||||
if(M.mind)
|
||||
M.mind.transfer_to(new_mob)
|
||||
else
|
||||
new_mob.key = M.key
|
||||
|
||||
new_mob << "<B>Your form morphs into that of a corgi.</B>" //Because we don't have cluwnes
|
||||
M << "<span class='danger'>Walking into \the [src] is probably a bad idea, you think.</span>"
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
/*
|
||||
|
||||
In short:
|
||||
* Random area alarms
|
||||
* All areas jammed
|
||||
* Random gateways spawning hellmonsters (and turn people into cluwnes if ran into)
|
||||
* Broken APCs/Fire Alarms
|
||||
* Scary music
|
||||
* Random gateways spawning hellmonsters
|
||||
* Broken Fire Alarms
|
||||
* Random tiles changing to culty tiles.
|
||||
|
||||
*/
|
||||
@@ -42,7 +39,7 @@ In short:
|
||||
// Apply changes when entering state
|
||||
/datum/universal_state/hell/OnEnter()
|
||||
set background = 1
|
||||
garbage_collector.garbage_collect = 0
|
||||
// garbage_collector.garbage_collect = 0
|
||||
|
||||
escape_list = get_area_turfs(locate(/area/hallway/secondary/exit))
|
||||
|
||||
@@ -50,8 +47,8 @@ In short:
|
||||
AreaSet()
|
||||
MiscSet()
|
||||
APCSet()
|
||||
KillMobs()
|
||||
OverlayAndAmbientSet()
|
||||
lightsout(0,0)
|
||||
|
||||
runedec += 9000 //basically removing the rune cap
|
||||
|
||||
@@ -83,13 +80,5 @@ In short:
|
||||
/datum/universal_state/hell/proc/APCSet()
|
||||
for (var/obj/machinery/power/apc/APC in machines)
|
||||
if (!(APC.stat & BROKEN) && !APC.is_critical)
|
||||
APC.chargemode = 0
|
||||
if(APC.cell)
|
||||
APC.cell.charge = 0
|
||||
APC.emagged = 1
|
||||
APC.queue_icon_update()
|
||||
|
||||
/datum/universal_state/hell/proc/KillMobs()
|
||||
for(var/mob/living/simple_animal/M in mob_list)
|
||||
if(M && !M.client)
|
||||
M.stat = DEAD
|
||||
|
||||
@@ -196,10 +196,24 @@ var/list/sacrificed = list()
|
||||
for(var/mob/M in range(1,src))
|
||||
if(iscultist(M) && !M.stat)
|
||||
M.say("Tok-lyr rqa'nap g[pick("'","`")]lt-ulotf!")
|
||||
cultists += 1
|
||||
if(istype(M, /mob/living/carbon/human/dummy)) //No manifest cheese.
|
||||
continue
|
||||
cultists.Add(M)
|
||||
if(cultists.len >= 9)
|
||||
log_and_message_admins_many(cultists, "summoned Nar-sie.")
|
||||
new /obj/singularity/narsie/large(src.loc)
|
||||
if(!narsie_cometh)//so we don't initiate Hell more than one time.
|
||||
world << "<font size='15' color='red'><b>THE VEIL HAS BEEN SHATTERED!</b></font>"
|
||||
world << sound('sound/effects/wind/wind_5_1.ogg')
|
||||
|
||||
SetUniversalState(/datum/universal_state/hell)
|
||||
narsie_cometh = 1
|
||||
|
||||
spawn(10 SECONDS)
|
||||
if(emergency_shuttle)
|
||||
emergency_shuttle.call_evac()
|
||||
emergency_shuttle.launch_time = 0 // Cannot recall
|
||||
|
||||
log_and_message_admins_many(cultists, "summoned the end of days.")
|
||||
// new /obj/singularity/narsie/large(src.loc)
|
||||
return
|
||||
else
|
||||
return fizzle()
|
||||
|
||||
@@ -18,6 +18,10 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
|
||||
minimal_access = list() //See get_access()
|
||||
minimal_player_age = 14
|
||||
economic_modifier = 20
|
||||
|
||||
ideal_character_age = 70 // Old geezer captains ftw
|
||||
|
||||
|
||||
equip(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(H), slot_l_ear)
|
||||
@@ -63,6 +67,8 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
|
||||
req_admin_notify = 1
|
||||
minimal_player_age = 10
|
||||
economic_modifier = 10
|
||||
ideal_character_age = 50
|
||||
|
||||
access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
|
||||
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
|
||||
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
|
||||
|
||||
@@ -101,6 +101,8 @@
|
||||
access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station)
|
||||
minimal_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station)
|
||||
|
||||
ideal_character_age = 40
|
||||
|
||||
|
||||
equip(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
idtype = /obj/item/weapon/card/id/silver
|
||||
req_admin_notify = 1
|
||||
economic_modifier = 10
|
||||
|
||||
ideal_character_age = 50
|
||||
|
||||
|
||||
access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
|
||||
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
|
||||
access_heads, access_construction, access_sec_doors,
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
var/minimal_player_age = 0 // If you have use_age_restriction_for_jobs config option enabled and the database set up, this option will add a requirement for players to be at least minimal_player_age days old. (meaning they first signed in at least that many days before.)
|
||||
var/department = null // Does this position have a department tag?
|
||||
var/head_position = 0 // Is this position Command?
|
||||
var/minimum_character_age = 17
|
||||
var/ideal_character_age = 30
|
||||
|
||||
var/account_allowed = 1 // Does this job type come with a station account?
|
||||
var/economic_modifier = 2 // With how much does this job modify the initial account amount?
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
minimal_access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
|
||||
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
|
||||
access_keycard_auth, access_sec_doors, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
|
||||
|
||||
minimal_player_age = 10
|
||||
ideal_character_age = 50
|
||||
|
||||
equip(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
access_tox_storage, access_teleporter, access_sec_doors,
|
||||
access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage,
|
||||
access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch)
|
||||
|
||||
minimal_player_age = 14
|
||||
ideal_character_age = 50
|
||||
|
||||
equip(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
|
||||
@@ -49,9 +49,15 @@ var/global/datum/controller/occupations/job_master
|
||||
Debug("Running AR, Player: [player], Rank: [rank], LJ: [latejoin]")
|
||||
if(player && player.mind && rank)
|
||||
var/datum/job/job = GetJob(rank)
|
||||
if(!job) return 0
|
||||
if(jobban_isbanned(player, rank)) return 0
|
||||
if(!job.player_old_enough(player.client)) return 0
|
||||
if(!job)
|
||||
return 0
|
||||
if(job.minimum_character_age && (player.client.prefs.age < job.minimum_character_age))
|
||||
return 0
|
||||
if(jobban_isbanned(player, rank))
|
||||
return 0
|
||||
if(!job.player_old_enough(player.client))
|
||||
return 0
|
||||
|
||||
var/position_limit = job.total_positions
|
||||
if(!latejoin)
|
||||
position_limit = job.spawn_positions
|
||||
@@ -82,6 +88,9 @@ var/global/datum/controller/occupations/job_master
|
||||
if(!job.player_old_enough(player.client))
|
||||
Debug("FOC player not old enough, Player: [player]")
|
||||
continue
|
||||
if(job.minimum_character_age && (player.client.prefs.age < job.minimum_character_age))
|
||||
Debug("FOC character not old enough, Player: [player]")
|
||||
continue
|
||||
if(flag && (!player.client.prefs.be_special & flag))
|
||||
Debug("FOC flag failed, Player: [player], Flag: [flag], ")
|
||||
continue
|
||||
@@ -96,6 +105,9 @@ var/global/datum/controller/occupations/job_master
|
||||
if(!job)
|
||||
continue
|
||||
|
||||
if(job.minimum_character_age && (player.client.prefs.age < job.minimum_character_age))
|
||||
continue
|
||||
|
||||
if(istype(job, GetJob("Assistant"))) // We don't want to give him assistant, that's boring!
|
||||
continue
|
||||
|
||||
@@ -137,30 +149,24 @@ var/global/datum/controller/occupations/job_master
|
||||
|
||||
// Build a weighted list, weight by age.
|
||||
var/list/weightedCandidates = list()
|
||||
|
||||
// Different head positions have different good ages.
|
||||
var/good_age_minimal = 25
|
||||
var/good_age_maximal = 60
|
||||
if(command_position == "Captain")
|
||||
good_age_minimal = 30
|
||||
good_age_maximal = 70 // Old geezer captains ftw
|
||||
|
||||
for(var/mob/V in candidates)
|
||||
// Log-out during round-start? What a bad boy, no head position for you!
|
||||
if(!V.client) continue
|
||||
var/age = V.client.prefs.age
|
||||
|
||||
if(age < job.minimum_character_age) // Nope.
|
||||
continue
|
||||
|
||||
switch(age)
|
||||
if(good_age_minimal - 10 to good_age_minimal)
|
||||
if(job.minimum_character_age to (job.minimum_character_age+10))
|
||||
weightedCandidates[V] = 3 // Still a bit young.
|
||||
if(good_age_minimal to good_age_minimal + 10)
|
||||
if((job.minimum_character_age+10) to (job.ideal_character_age-10))
|
||||
weightedCandidates[V] = 6 // Better.
|
||||
if(good_age_minimal + 10 to good_age_maximal - 10)
|
||||
if((job.ideal_character_age-10) to (job.ideal_character_age+10))
|
||||
weightedCandidates[V] = 10 // Great.
|
||||
if(good_age_maximal - 10 to good_age_maximal)
|
||||
if((job.ideal_character_age+10) to (job.ideal_character_age+20))
|
||||
weightedCandidates[V] = 6 // Still good.
|
||||
if(good_age_maximal to good_age_maximal + 10)
|
||||
weightedCandidates[V] = 6 // Bit old, don't you think?
|
||||
if(good_age_maximal to good_age_maximal + 50)
|
||||
if((job.ideal_character_age+20) to INFINITY)
|
||||
weightedCandidates[V] = 3 // Geezer.
|
||||
else
|
||||
// If there's ABSOLUTELY NOBODY ELSE
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/obj/machinery/exonet_node
|
||||
name = "exonet node"
|
||||
desc = "This machine is one of many, many nodes inside Vir's section of the Exonet, connecting the Northern Star to the rest of the system, at least \
|
||||
electronically."
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "exonet_node"
|
||||
idle_power_usage = 2500
|
||||
density = 1
|
||||
var/on = 1
|
||||
var/toggle = 1
|
||||
|
||||
var/allow_external_PDAs = 1
|
||||
var/allow_external_communicators = 1
|
||||
var/allow_external_newscasters = 1
|
||||
|
||||
var/opened = 0
|
||||
|
||||
// Proc: New()
|
||||
// Parameters: None
|
||||
// Description: Adds components to the machine for deconstruction.
|
||||
/obj/machinery/exonet_node/New()
|
||||
..()
|
||||
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/circuitboard/telecomms/exonet_node(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/subspace/ansible(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/subspace/filter(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/subspace/crystal(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src)
|
||||
component_parts += new /obj/item/stack/cable_coil(src, 2)
|
||||
RefreshParts()
|
||||
|
||||
// Proc: update_icon()
|
||||
// Parameters: None
|
||||
// Description: Self explanatory.
|
||||
/obj/machinery/exonet_node/update_icon()
|
||||
if(on)
|
||||
if(!allow_external_PDAs && !allow_external_communicators && !allow_external_newscasters)
|
||||
icon_state = "[initial(icon_state)]_idle"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
else
|
||||
icon_state = "[initial(icon_state)]_off"
|
||||
|
||||
// Proc: update_power()
|
||||
// Parameters: None
|
||||
// Description: Sets the device on/off and adjusts power draw based on stat and toggle variables.
|
||||
/obj/machinery/exonet_node/proc/update_power()
|
||||
if(toggle)
|
||||
if(stat & (BROKEN|NOPOWER|EMPED))
|
||||
on = 0
|
||||
idle_power_usage = 0
|
||||
else
|
||||
on = 1
|
||||
idle_power_usage = 2500
|
||||
else
|
||||
on = 0
|
||||
idle_power_usage = 0
|
||||
|
||||
// Proc: emp_act()
|
||||
// Parameters: 1 (severity - how strong the EMP is, with lower numbers being stronger)
|
||||
// Description: Shuts off the machine for awhile if an EMP hits it. Ion anomalies also call this to turn it off.
|
||||
/obj/machinery/exonet_node/emp_act(severity)
|
||||
if(!(stat & EMPED))
|
||||
stat |= EMPED
|
||||
var/duration = (300 * 10)/severity
|
||||
spawn(rand(duration - 20, duration + 20))
|
||||
stat &= ~EMPED
|
||||
update_icon()
|
||||
..()
|
||||
|
||||
// Proc: process()
|
||||
// Parameters: None
|
||||
// Description: Calls the procs below every tick.
|
||||
/obj/machinery/exonet_node/process()
|
||||
update_power()
|
||||
|
||||
// Proc: attackby()
|
||||
// Parameters: 2 (I - the item being whacked against the machine, user - the person doing the whacking)
|
||||
// Description: Handles deconstruction.
|
||||
/obj/machinery/exonet_node/attackby(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/weapon/screwdriver))
|
||||
default_deconstruction_screwdriver(user, I)
|
||||
else if(istype(I, /obj/item/weapon/crowbar))
|
||||
default_deconstruction_crowbar(user, I)
|
||||
else
|
||||
..()
|
||||
|
||||
// Proc: attack_ai()
|
||||
// Parameters: 1 (user - the AI clicking on the machine)
|
||||
// Description: Redirects to attack_hand()
|
||||
/obj/machinery/exonet_node/attack_ai(mob/user)
|
||||
attack_hand(user)
|
||||
|
||||
// Proc: attack_hand()
|
||||
// Parameters: 1 (user - the person clicking on the machine)
|
||||
// Description: Opens the NanoUI interface with ui_interact()
|
||||
/obj/machinery/exonet_node/attack_hand(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
// Proc: ui_interact()
|
||||
// Parameters: 4 (standard NanoUI arguments)
|
||||
// Description: Allows the user to turn the machine on or off, or open or close certain 'ports' for things like external PDA messages, newscasters, etc.
|
||||
/obj/machinery/exonet_node/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
// this is the data which will be sent to the ui
|
||||
var/data[0]
|
||||
|
||||
|
||||
data["on"] = toggle ? 1 : 0
|
||||
data["allowPDAs"] = allow_external_PDAs
|
||||
data["allowCommunicators"] = allow_external_communicators
|
||||
data["allowNewscasters"] = allow_external_newscasters
|
||||
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "exonet_node.tmpl", "Exonet Node #157", 400, 400)
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
// Proc: Topic()
|
||||
// Parameters: 2 (standard Topic arguments)
|
||||
// Description: Responds to button presses on the NanoUI interface.
|
||||
/obj/machinery/exonet_node/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["toggle_power"])
|
||||
toggle = !toggle
|
||||
update_power()
|
||||
if(!toggle)
|
||||
var/msg = "[usr.client.key] ([usr]) has turned [src] off, at [x],[y],[z]."
|
||||
message_admins(msg)
|
||||
log_game(msg)
|
||||
|
||||
if(href_list["toggle_PDA_port"])
|
||||
allow_external_PDAs = !allow_external_PDAs
|
||||
|
||||
if(href_list["toggle_communicator_port"])
|
||||
allow_external_communicators = !allow_external_communicators
|
||||
if(!allow_external_communicators)
|
||||
var/msg = "[usr.client.key] ([usr]) has turned [src]'s communicator port off, at [x],[y],[z]."
|
||||
message_admins(msg)
|
||||
log_game(msg)
|
||||
|
||||
if(href_list["toggle_newscaster_port"])
|
||||
allow_external_newscasters = !allow_external_newscasters
|
||||
if(!allow_external_newscasters)
|
||||
var/msg = "[usr.client.key] ([usr]) has turned [src]'s newscaster port off, at [x],[y],[z]."
|
||||
message_admins(msg)
|
||||
log_game(msg)
|
||||
|
||||
update_icon()
|
||||
nanomanager.update_uis(src)
|
||||
add_fingerprint(usr)
|
||||
|
||||
// Proc: get_exonet_node()
|
||||
// Parameters: None
|
||||
// Description: Helper proc to get a reference to an Exonet node.
|
||||
/proc/get_exonet_node()
|
||||
for(var/obj/machinery/exonet_node/E in machines)
|
||||
if(E.on)
|
||||
return E
|
||||
@@ -166,6 +166,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
|
||||
var/datum/feed_channel/viewing_channel = null
|
||||
light_range = 0
|
||||
anchored = 1
|
||||
var/obj/machinery/exonet_node/node = null
|
||||
|
||||
|
||||
/obj/machinery/newscaster/security_unit //Security unit
|
||||
@@ -178,6 +179,8 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
|
||||
for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) // Let's give it an appropriate unit number
|
||||
src.unit_no++
|
||||
src.update_icon() //for any custom ones on the map...
|
||||
spawn(10) //Should be enough time for the node to spawn at tcomms.
|
||||
node = get_exonet_node()
|
||||
..() //I just realised the newscasters weren't in the global machines list. The superconstructor call will tend to that
|
||||
|
||||
/obj/machinery/newscaster/Destroy()
|
||||
@@ -247,6 +250,14 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
|
||||
if(!src.ispowered || src.isbroken)
|
||||
return
|
||||
|
||||
if(!node)
|
||||
node = get_exonet_node()
|
||||
|
||||
if(!node || !node.on || !node.allow_external_newscasters)
|
||||
user << "<span class='danger'>Error: Cannot connect to external content. Please try again in a few minutes. If this error persists, please \
|
||||
contact the system administrator.</span>"
|
||||
return 0
|
||||
|
||||
if(!user.IsAdvancedToolUser())
|
||||
return 0
|
||||
|
||||
@@ -984,12 +995,10 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
src.paper_remaining--
|
||||
return
|
||||
|
||||
//Removed for now so these aren't even checked every tick. Left this here in-case Agouri needs it later.
|
||||
///obj/machinery/newscaster/process() //Was thinking of doing the icon update through process, but multiple iterations per second does not
|
||||
// return //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list.
|
||||
|
||||
/obj/machinery/newscaster/proc/newsAlert(var/news_call) //This isn't Agouri's work, for it is ugly and vile.
|
||||
var/turf/T = get_turf(src) //Who the fuck uses spawn(600) anyway, jesus christ
|
||||
/obj/machinery/newscaster/proc/newsAlert(var/news_call)
|
||||
if(!node || !node.on || !node.allow_external_newscasters) //The messages will still be there once the connection returns.
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
if(news_call)
|
||||
for(var/mob/O in hearers(world.view-1, T))
|
||||
O.show_message("<span class='newscaster'><EM>[src.name]</EM> beeps, \"[news_call]\"</span>",2)
|
||||
|
||||
@@ -107,10 +107,6 @@
|
||||
for(var/obj/item/weapon/ore/ore in range(chassis,1))
|
||||
if(get_dir(chassis,ore)&chassis.dir)
|
||||
ore.Move(ore_box)
|
||||
else if(istype(target, /turf/simulated/floor/asteroid))
|
||||
for(var/turf/simulated/floor/asteroid/M in range(chassis,1))
|
||||
if(get_dir(chassis,M)&chassis.dir)
|
||||
M.gets_dug()
|
||||
log_message("Drilled through [target]")
|
||||
if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment)
|
||||
var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo
|
||||
@@ -160,15 +156,6 @@
|
||||
for(var/obj/item/weapon/ore/ore in range(chassis,1))
|
||||
if(get_dir(chassis,ore)&chassis.dir)
|
||||
ore.Move(ore_box)
|
||||
else if(istype(target,/turf/simulated/floor/asteroid))
|
||||
for(var/turf/simulated/floor/asteroid/M in range(target,1))
|
||||
M.gets_dug()
|
||||
log_message("Drilled through [target]")
|
||||
if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment)
|
||||
var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo
|
||||
if(ore_box)
|
||||
for(var/obj/item/weapon/ore/ore in range(target,1))
|
||||
ore.Move(ore_box)
|
||||
else if(target.loc == C)
|
||||
log_message("Drilled through [target]")
|
||||
target.ex_act(2)
|
||||
|
||||
@@ -56,7 +56,8 @@
|
||||
user << "<span class='warning'>You can't buckle anyone in before the game starts.</span>"
|
||||
if(!user.Adjacent(M) || user.restrained() || user.lying || user.stat || istype(user, /mob/living/silicon/pai))
|
||||
return
|
||||
|
||||
if(M == buckled_mob)
|
||||
return
|
||||
if(istype(M, /mob/living/carbon/slime))
|
||||
user << "<span class='warning'>The [M] is too squishy to buckle in.</span>"
|
||||
return
|
||||
|
||||
@@ -107,7 +107,7 @@ steam.start() -- spawns the effect
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
T.hotspot_expose(1000,100)
|
||||
spawn (100)
|
||||
spawn (20)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
@@ -156,8 +156,6 @@ steam.start() -- spawns the effect
|
||||
sleep(5)
|
||||
step(sparks,direction)
|
||||
spawn(20)
|
||||
if(sparks)
|
||||
qdel(sparks)
|
||||
src.total_sparks--
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
item_state = "electronic"
|
||||
w_class = 2.0
|
||||
slot_flags = SLOT_ID | SLOT_BELT
|
||||
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/id.dmi')
|
||||
|
||||
//Main variables
|
||||
var/owner = null
|
||||
@@ -949,7 +948,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
|
||||
/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P, var/tap = 1)
|
||||
if(tap)
|
||||
U.visible_message("<span class='notice'>\The [U] taps on \his PDA's screen.</span>")
|
||||
U.last_target_click = world.time
|
||||
var/t = input(U, "Please enter message", P.name, null) as text
|
||||
t = sanitize(t)
|
||||
//t = readd_quotes(t)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
// Communicators
|
||||
//
|
||||
// Allows ghosts to roleplay with crewmembers without having to commit to joining the round, and also allows communications between two communicators.
|
||||
|
||||
var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
|
||||
/obj/item/device/communicator
|
||||
@@ -12,21 +16,33 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
origin_tech = list(TECH_ENGINEERING = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2, TECH_DATA = 2)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
|
||||
|
||||
var/mob/living/voice/voice_mob = null
|
||||
var/list/voice_mobs = list()
|
||||
var/list/voice_requests = list()
|
||||
var/owner = null
|
||||
var/owner_job = null
|
||||
var/owner_rank = null //Is this different from job?
|
||||
var/list/voice_invites = list()
|
||||
var/selected_tab = 1 //1 equals dialing, 2 equals reviewing requests/invites.
|
||||
var/owner = ""
|
||||
var/alert_called = 0
|
||||
var/obj/machinery/message_server/server = null //Reference to the PDA server, to avoid having to look it up so often.
|
||||
var/obj/machinery/exonet_node/node = null //Reference to the Exonet node, to avoid having to look it up so often.
|
||||
|
||||
var/target_address = ""
|
||||
var/network_visibility = 1
|
||||
var/list/known_devices = list()
|
||||
var/datum/exonet_protocol/exonet = null
|
||||
var/list/communicating = list()
|
||||
var/update_ticks = 0
|
||||
|
||||
// Proc: New()
|
||||
// Parameters: None
|
||||
// Description: Adds the new communicator to the global list of all communicators, sorts the list, obtains a reference to the Exonet node, then tries to
|
||||
// assign the device to the holder's name automatically in a spectacularly shitty way.
|
||||
/obj/item/device/communicator/New()
|
||||
..()
|
||||
all_communicators += src
|
||||
all_communicators = sortAtom(all_communicators)
|
||||
server = get_message_server()
|
||||
node = get_exonet_node()
|
||||
processing_objects |= src
|
||||
//This is a pretty terrible way of doing this.
|
||||
spawn(20) //Wait for our mob to finish spawning.
|
||||
spawn(50) //Wait for our mob to finish spawning.
|
||||
if(ismob(loc))
|
||||
register_device(loc)
|
||||
else if(istype(loc, /obj/item/weapon/storage))
|
||||
@@ -34,201 +50,450 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
if(ismob(S.loc))
|
||||
register_device(S.loc)
|
||||
|
||||
// Proc: examine()
|
||||
// Parameters: 1 (user - the person examining the device)
|
||||
// Description: Shows all the voice mobs inside the device, and their status.
|
||||
/obj/item/device/communicator/examine(mob/user)
|
||||
if(!..(user))
|
||||
return
|
||||
|
||||
var/msg = ""
|
||||
if(voice_mob)
|
||||
msg += "<span class='notice'>On the screen, you can see a image feed of [voice_mob].</span>\n"
|
||||
msg += "<span class='warning'>"
|
||||
for(var/mob/living/voice/voice in contents)
|
||||
msg += "<span class='notice'>On the screen, you can see a image feed of [voice].</span>\n"
|
||||
msg += "<span class='warning'>"
|
||||
|
||||
if(src.voice_mob && src.voice_mob.key)
|
||||
switch(src.voice_mob.stat)
|
||||
if(CONSCIOUS)
|
||||
if(!src.voice_mob.client)
|
||||
msg += "[voice_mob] appears to be asleep.\n" //afk
|
||||
if(UNCONSCIOUS)
|
||||
msg += "[voice_mob] doesn't appear to be conscious.\n"
|
||||
if(DEAD)
|
||||
msg += "<span class='deadsay'>[voice_mob] appears to have died...</span>\n" //Hopefully this never has to be used.
|
||||
else
|
||||
msg += "<span class='notice'>The device doesn't appear to be transmitting any data.</span>\n"
|
||||
msg += "</span>"
|
||||
if(voice && voice.key)
|
||||
switch(voice.stat)
|
||||
if(CONSCIOUS)
|
||||
if(!voice.client)
|
||||
msg += "[voice] appears to be asleep.\n" //afk
|
||||
if(UNCONSCIOUS)
|
||||
msg += "[voice] doesn't appear to be conscious.\n"
|
||||
if(DEAD)
|
||||
msg += "<span class='deadsay'>[voice] appears to have died...</span>\n" //Hopefully this never has to be used.
|
||||
else
|
||||
msg += "<span class='notice'>The device doesn't appear to be transmitting any data.</span>\n"
|
||||
msg += "</span>"
|
||||
user << msg
|
||||
return
|
||||
|
||||
//This is pretty lengthy
|
||||
// Proc: emp_act()
|
||||
// Parameters: None
|
||||
// Description: Drops all calls when EMPed, so the holder can then get murdered by the antagonist.
|
||||
/obj/item/device/communicator/emp_act()
|
||||
close_connection(reason = "Hardware error de%#_^@%-BZZZZZZZT")
|
||||
|
||||
// Proc: add_to_EPv2()
|
||||
// Parameters: 1 (hex - a single hexadecimal character)
|
||||
// Description: Called when someone is manually dialing with nanoUI. Adds colons when appropiate.
|
||||
/obj/item/device/communicator/proc/add_to_EPv2(var/hex)
|
||||
var/length = length(target_address)
|
||||
if(length >= 24)
|
||||
return
|
||||
if(length == 4 || length == 9 || length == 14 || length == 19 || length == 24 || length == 29)
|
||||
target_address += ":[hex]"
|
||||
return
|
||||
target_address += hex
|
||||
|
||||
// Proc: populate_known_devices()
|
||||
// Parameters: 1 (user - the person using the device)
|
||||
// Description: Searches all communicators and ghosts in the world, and adds them to the known_devices list if they are 'visible'.
|
||||
/obj/item/device/communicator/proc/populate_known_devices(mob/user)
|
||||
if(!exonet)
|
||||
exonet = new(src)
|
||||
src.known_devices.Cut()
|
||||
if(!get_connection_to_tcomms()) //If the network's down, we can't see anything.
|
||||
return
|
||||
for(var/obj/item/device/communicator/comm in all_communicators)
|
||||
if(!comm || !comm.exonet || !comm.exonet.address || comm.exonet.address == src.exonet.address) //Don't add addressless devices, and don't add ourselves.
|
||||
continue
|
||||
src.known_devices |= comm
|
||||
for(var/mob/dead/observer/O in dead_mob_list)
|
||||
if(!O.client || O.client.prefs.communicator_visibility == 0)
|
||||
continue
|
||||
src.known_devices |= O
|
||||
|
||||
// Proc: get_connection_to_tcomms()
|
||||
// Parameters: None
|
||||
// Description: Simple check to see if the exonet node is active.
|
||||
/obj/item/device/communicator/proc/get_connection_to_tcomms()
|
||||
if(node)
|
||||
if(node.on && node.allow_external_communicators)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
// Proc: process()
|
||||
// Parameters: None
|
||||
// Description: Ticks the update_ticks variable, and checks to see if it needs to disconnect communicators every five ticks..
|
||||
/obj/item/device/communicator/process()
|
||||
update_ticks++
|
||||
if(update_ticks % 5)
|
||||
if(!node)
|
||||
node = get_exonet_node()
|
||||
if(!node || !node.on || !node.allow_external_communicators)
|
||||
close_connection(reason = "Connection timed out")
|
||||
|
||||
// Proc: attack_self()
|
||||
// Parameters: 1 (user - the mob that clicked the device in their hand)
|
||||
// Description: Makes an exonet datum if one does not exist, allocates an address for it, maintains the lists of all devies, clears the alert icon, and
|
||||
// finally makes NanoUI appear.
|
||||
/obj/item/device/communicator/attack_self(mob/user)
|
||||
if(!owner)
|
||||
var/choice = alert(user,"Would you like to register [src]?","Communicator","Yes","No")
|
||||
if(choice == "Yes")
|
||||
register_device(user)
|
||||
return
|
||||
if(!exonet)
|
||||
exonet = new(src)
|
||||
if(!exonet.address)
|
||||
exonet.make_address("communicator-[user.client]-[user.name]")
|
||||
if(!node)
|
||||
node = get_exonet_node()
|
||||
populate_known_devices()
|
||||
alert_called = 0
|
||||
update_icon()
|
||||
ui_interact(user)
|
||||
|
||||
if(voice_mob)
|
||||
var/choice = alert(user,"Would you like to hang up?","Communicator","No","Yes")
|
||||
if(choice == "Yes")
|
||||
close_connection(user, "[user] hung up")
|
||||
return
|
||||
// Proc: attack_ghost()
|
||||
// Parameters: 1 (user - the ghost clicking on the device)
|
||||
// Description: Recreates the known_devices list, so that the ghost looking at the device can see themselves, then calls ..() so that NanoUI appears.
|
||||
/obj/item/device/communicator/attack_ghost(mob/user)
|
||||
populate_known_devices() //Update the devices so ghosts can see the list on NanoUI.
|
||||
..()
|
||||
|
||||
if(!server || !server.active)
|
||||
user << "<span class='danger'>\icon[src] Error: Cannot establish connection to telecommunications.</span>"
|
||||
sleep(30)
|
||||
user << "<span class='danger'>\icon[src] Attempting to connect to telecommunications.</span>"
|
||||
sleep(30)
|
||||
if(!server)
|
||||
server = get_message_server()
|
||||
if(!server)
|
||||
user << "<span class='danger'>\icon[src] Query to telecommunications timed out.</span>"
|
||||
else if(server.active)
|
||||
user << "<span class='notice'>\icon[src] Connection re-established.</span>"
|
||||
/mob/dead/observer
|
||||
var/datum/exonet_protocol/exonet = null
|
||||
|
||||
// Proc: New()
|
||||
// Parameters: None
|
||||
// Description: Gives ghosts an exonet address based on their key and ghost name.
|
||||
/mob/dead/observer/New()
|
||||
. = ..()
|
||||
spawn(20)
|
||||
exonet = new(src)
|
||||
if(client)
|
||||
exonet.make_address("communicator-[src.client]-[src.client.prefs.real_name]")
|
||||
else
|
||||
if(server.active)
|
||||
user << "<span class='notice'>\icon[src] Connection re-established.</span>"
|
||||
else
|
||||
user << "<span class='danger'>\icon[src] Query to telecommunications timed out.</span>"
|
||||
exonet.make_address("communicator-[key]-[src.real_name]")
|
||||
|
||||
return
|
||||
// Proc: Destroy()
|
||||
// Parameters: None
|
||||
// Description: Removes the ghost's address and nulls the exonet datum, to allow qdel()ing.
|
||||
/mob/dead/observer/Destroy()
|
||||
. = ..()
|
||||
if(exonet)
|
||||
exonet.remove_address()
|
||||
exonet = null
|
||||
..()
|
||||
|
||||
var/mode = alert(user,"Would you like to check for communications requests or attempt to send a communication request to an external device?",
|
||||
"Communicator","Check Requests","Send Request", "Cancel")
|
||||
switch(mode)
|
||||
if("Check Requests")
|
||||
if(!voice_requests.len)
|
||||
user << "\icon[src] No incoming communications requests."
|
||||
return
|
||||
// Proc: ui_interact()
|
||||
// Parameters: 4 (standard NanoUI arguments)
|
||||
// Description: Uses a bunch of for loops to turn lists into lists of lists, so they can be displayed in nanoUI, then displays various buttons to the user.
|
||||
/obj/item/device/communicator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
// this is the data which will be sent to the ui
|
||||
var/data[0] //General nanoUI information
|
||||
var/communicators[0] //List of communicators
|
||||
var/invites[0] //Communicators and ghosts we've invited to our communicator.
|
||||
var/requests[0] //Communicators and ghosts wanting to go in our communicator.
|
||||
var/voices[0] //Current /mob/living/voice s inside the device.
|
||||
var/connected_communicators[0] //Current communicators connected to the device.
|
||||
|
||||
else
|
||||
alert_called = 0
|
||||
update_icon()
|
||||
var/choice = input(user,"Would would you like to talk to?","Communicator") as null|anything in voice_requests
|
||||
if(choice)
|
||||
open_connection(user, choice)
|
||||
return
|
||||
//First we add other 'local' communicators.
|
||||
for(var/obj/item/device/communicator/comm in known_devices)
|
||||
if(comm.network_visibility && comm.exonet)
|
||||
communicators[++communicators.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address)
|
||||
|
||||
if("Send Request")
|
||||
var/list/potential_candidates = list()
|
||||
for(var/mob/dead/observer/O in dead_mob_list) //To my knowledge, there isn't a list of all ghosts.
|
||||
if(O.client) //We only want logged in ghosts.
|
||||
potential_candidates.Add(O.client.prefs.real_name) //This is needed so you don't see ghosted maint drones on the list.
|
||||
//Now for ghosts who we pretend have communicators.
|
||||
for(var/mob/dead/observer/O in known_devices)
|
||||
if(O.client && O.client.prefs.communicator_visibility == 1 && O.exonet)
|
||||
communicators[++communicators.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address)
|
||||
|
||||
if(!potential_candidates.len)
|
||||
user << "\icon[src] Unfortunately, no other communicators outside your local area could be found. Please try again later."
|
||||
return
|
||||
//Lists all the other communicators that we invited.
|
||||
for(var/obj/item/device/communicator/comm in voice_invites)
|
||||
if(comm.exonet)
|
||||
invites[++invites.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address)
|
||||
|
||||
var/choice = input(src,"Please select a person to call. Due to the vast distances involved \
|
||||
as well as time-zones, please note that your request may take a long time to be noticed, and \
|
||||
that the available people to call may change as time passes.") as null|anything in potential_candidates
|
||||
if(choice)
|
||||
var/mob/dead/observer/boo = null
|
||||
for(var/mob/dead/observer/O in dead_mob_list)
|
||||
if(O.client && O.client.prefs.real_name == choice)
|
||||
boo = O
|
||||
break
|
||||
boo << "\icon[src] A communications request has been received from [src]. If you would like to answer, please use the <b>Call Communicator</b> verb."
|
||||
user << "\icon[src] A communications request has been sent to [choice]. Now you need to wait until they answer, if they do."
|
||||
//Ghosts we invited.
|
||||
for(var/mob/dead/observer/O in voice_invites)
|
||||
if(O.exonet && O.client)
|
||||
invites[++invites.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address)
|
||||
|
||||
//Communicators that want to talk to us.
|
||||
for(var/obj/item/device/communicator/comm in voice_requests)
|
||||
if(comm.exonet)
|
||||
requests[++requests.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address)
|
||||
|
||||
//Ghosts that want to talk to us.
|
||||
for(var/mob/dead/observer/O in voice_requests)
|
||||
if(O.exonet && O.client)
|
||||
requests[++requests.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address)
|
||||
|
||||
//Now for all the voice mobs inside the communicator.
|
||||
for(var/mob/living/voice/voice in contents)
|
||||
voices[++voices.len] = list("name" = sanitize("[voice.name]'s communicator"), "true_name" = sanitize(voice.name))
|
||||
|
||||
//Finally, all the communicators linked to this one.
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
connected_communicators[++connected_communicators.len] = list("name" = sanitize(comm.name), "true_name" = sanitize(comm.name))
|
||||
|
||||
|
||||
data["owner"] = owner ? owner : "Unset"
|
||||
data["connectionStatus"] = get_connection_to_tcomms()
|
||||
data["visible"] = network_visibility
|
||||
data["address"] = exonet.address ? exonet.address : "Unallocated"
|
||||
data["targetAddress"] = target_address
|
||||
data["currentTab"] = selected_tab
|
||||
data["knownDevices"] = communicators
|
||||
data["invitesSent"] = invites
|
||||
data["requestsReceived"] = requests
|
||||
data["voice_mobs"] = voices
|
||||
data["communicating"] = connected_communicators
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if(!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "communicator.tmpl", "Communicator", 450, 700)
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
ui.open()
|
||||
// auto update every five Master Controller tick
|
||||
ui.set_auto_update(5)
|
||||
|
||||
// Proc: Topic()
|
||||
// Parameters: 2 (standard Topic arguments)
|
||||
// Description: Responds to NanoUI button presses.
|
||||
/obj/item/device/communicator/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(href_list["rename"])
|
||||
var/new_name = sanitizeSafe(input(usr,"Please enter your name.","Communicator",usr.name) )
|
||||
if(new_name)
|
||||
owner = new_name
|
||||
name = "[owner]'s [initial(name)]"
|
||||
|
||||
if(href_list["toggle_visibility"])
|
||||
network_visibility = !network_visibility
|
||||
|
||||
if(href_list["add_hex"])
|
||||
var/hex = href_list["add_hex"]
|
||||
add_to_EPv2(hex)
|
||||
|
||||
if(href_list["write_target_address"])
|
||||
var/new_address = sanitizeSafe(input(usr,"Please enter the desired target EPv2 address. Note that you must write the colons \
|
||||
yourself.","Communicator",src.target_address) )
|
||||
if(new_address)
|
||||
target_address = new_address
|
||||
|
||||
if(href_list["clear_target_address"])
|
||||
target_address = ""
|
||||
|
||||
if(href_list["dial"])
|
||||
if(!get_connection_to_tcomms())
|
||||
usr << "<span class='danger'>Error: Cannot connect to Exonet node.</span>"
|
||||
return
|
||||
var/their_address = href_list["dial"]
|
||||
exonet.send_message(their_address, "voice")
|
||||
if(href_list["disconnect"])
|
||||
var/name_to_disconnect = href_list["disconnect"]
|
||||
for(var/mob/living/voice/V in contents)
|
||||
if(name_to_disconnect == V.name)
|
||||
close_connection(usr, V, "[usr] hung up")
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
if(name_to_disconnect == comm.name)
|
||||
close_connection(usr, comm, "[usr] hung up")
|
||||
|
||||
/obj/item/device/communicator/proc/register_device(mob/user, var/job = null)
|
||||
if(href_list["copy"])
|
||||
target_address = href_list["copy"]
|
||||
|
||||
if(href_list["switch_tab"])
|
||||
selected_tab = href_list["switch_tab"]
|
||||
|
||||
nanomanager.update_uis(src)
|
||||
add_fingerprint(usr)
|
||||
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 3 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received)
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response.
|
||||
/obj/item/device/communicator/receive_exonet_message(var/atom/origin_atom, origin_address, message)
|
||||
if(message == "voice")
|
||||
if(isobserver(origin_atom) || istype(origin_atom, /obj/item/device/communicator))
|
||||
if(origin_atom in voice_invites)
|
||||
var/user = null
|
||||
if(ismob(origin_atom.loc))
|
||||
user = origin_atom.loc
|
||||
open_connection(user, origin_atom)
|
||||
return
|
||||
else if(origin_atom in voice_requests)
|
||||
return //Spam prevention
|
||||
else
|
||||
request(origin_atom)
|
||||
if(message == "ping")
|
||||
if(network_visibility)
|
||||
var/random = rand(200,350)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
|
||||
// Proc: receive_exonet_message()
|
||||
// Parameters: 3 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received)
|
||||
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response.
|
||||
/mob/dead/observer/receive_exonet_message(origin_atom, origin_address, message)
|
||||
if(message == "voice")
|
||||
if(istype(origin_atom, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = origin_atom
|
||||
if(src in comm.voice_invites)
|
||||
comm.open_connection(src)
|
||||
return
|
||||
src << "<span class='notice'>\icon[origin_atom] Receiving communicator request from [origin_atom]. To answer, use the <b>Call Communicator</b> \
|
||||
verb, and select that name to answer the call.</span>"
|
||||
comm.voice_invites |= src
|
||||
if(message == "ping")
|
||||
if(client && client.prefs.communicator_visibility)
|
||||
var/random = rand(450,700)
|
||||
random = random / 10
|
||||
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
|
||||
|
||||
// Proc: register_device()
|
||||
// Parameters: 1 (user - the person to use their name for)
|
||||
// Description: Updates the owner's name and the device's name.
|
||||
/obj/item/device/communicator/proc/register_device(mob/user)
|
||||
if(!user)
|
||||
return
|
||||
owner = user.name
|
||||
if(job)
|
||||
owner_job = job
|
||||
owner_rank = job
|
||||
|
||||
name = "[owner]'s [initial(name)]"
|
||||
|
||||
// Proc: open_connection()
|
||||
// Parameters: 2 (user - the person who initiated the connecting being opened, candidate - the communicator or observer that will connect to the device)
|
||||
// Description: Typechecks the candidate, then calls the correct proc for further connecting.
|
||||
/obj/item/device/communicator/proc/open_connection(mob/user, var/atom/candidate)
|
||||
if(isobserver(candidate))
|
||||
voice_invites.Remove(candidate)
|
||||
open_connection_to_ghost(user, candidate)
|
||||
else
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/obj/item/weapon/card/id/idcard = H.wear_id
|
||||
if(idcard)
|
||||
owner_job = idcard.assignment
|
||||
owner_rank = idcard.rank
|
||||
else
|
||||
user << "<span class='warning'>\icon[src] ID not found. Please swipe your ID on the device.</span>"
|
||||
return
|
||||
else //They're probably a synth.
|
||||
owner_job = user.job
|
||||
owner_rank = user.job
|
||||
if(istype(candidate, /obj/item/device/communicator))
|
||||
open_connection_to_communicator(user, candidate)
|
||||
|
||||
name = "\improper [initial(name)]-[owner] ([owner_job])"
|
||||
// Proc: open_connection_to_communicator()
|
||||
// Parameters: 2 (user - the person who initiated this and will be receiving feedback information, candidate - someone else's communicator)
|
||||
// Description: Adds the candidate and src to each other's communicating lists, allowing messages seen by the devices to be relayed.
|
||||
/obj/item/device/communicator/proc/open_connection_to_communicator(mob/user, var/atom/candidate)
|
||||
if(!istype(candidate, /obj/item/device/communicator))
|
||||
return
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
voice_invites.Remove(candidate)
|
||||
comm.voice_requests.Remove(src)
|
||||
|
||||
/*
|
||||
owner = idcard.registered_name
|
||||
owner_job = idcard.assignment
|
||||
owner_rank = idcard.rank
|
||||
name = "\improper communicator-[owner] ([ownjob])"
|
||||
*/
|
||||
if(user)
|
||||
comm.visible_message("<span class='notice'>\icon[src] Connecting to [src].</span>")
|
||||
user << "<span class='notice'>\icon[src] Attempting to call [comm].</span>"
|
||||
sleep(10)
|
||||
user << "<span class='notice'>\icon[src] Dialing internally from [station_name()], Kara Subsystem, [system_name()].</span>"
|
||||
sleep(20) //If they don't have an exonet something is very wrong and we want a runtime.
|
||||
user << "<span class='notice'>\icon[src] Connection re-routed to [comm] at [comm.exonet.address].</span>"
|
||||
sleep(40)
|
||||
user << "<span class='notice'>\icon[src] Connection to [comm] at [comm.exonet.address] established.</span>"
|
||||
comm.visible_message("<span class='notice'>\icon[src] Connection to [src] at [exonet.address] established.</span>")
|
||||
sleep(20)
|
||||
|
||||
/obj/item/device/communicator/proc/open_connection(mob/user, var/mob/candidate)
|
||||
communicating |= comm
|
||||
comm.communicating |= src
|
||||
|
||||
// Proc: open_connection_to_ghost()
|
||||
// Parameters: 2 (user - the person who initiated this, candidate - the ghost that will be turned into a voice mob)
|
||||
// Description: Pulls the candidate ghost from deadchat, makes a new voice mob, transfers their identity, then their client.
|
||||
/obj/item/device/communicator/proc/open_connection_to_ghost(mob/user, var/mob/candidate)
|
||||
if(!isobserver(candidate))
|
||||
return
|
||||
|
||||
//Handle moving the ghost into the new shell.
|
||||
announce_ghost_joinleave(candidate, 0, "They are occupying a personal communications device now.")
|
||||
voice_mob = new /mob/living/voice(src) //Make the voice mob the ghost is going to be.
|
||||
voice_mob.transfer_identity(candidate) //Now make the voice mob load from the ghost's active character in preferences.
|
||||
voice_requests.Remove(candidate)
|
||||
voice_invites.Remove(candidate)
|
||||
var/mob/living/voice/new_voice = new /mob/living/voice(src) //Make the voice mob the ghost is going to be.
|
||||
new_voice.transfer_identity(candidate) //Now make the voice mob load from the ghost's active character in preferences.
|
||||
//Do some simple logging since this is a tad risky as a concept.
|
||||
var/msg = "[candidate.client ? "[candidate.client.key]" : "*no key*"] ([candidate]) has entered [src], triggered by \
|
||||
[user.client ? "[user.client.key]" : "*no key*"] ([user]) at [x],[y],[z]. They have joined as [voice_mob.name]."
|
||||
var/msg = "[candidate && candidate.client ? "[candidate.client.key]" : "*no key*"] ([candidate]) has entered [src], triggered by \
|
||||
[user && user.client ? "[user.client.key]" : "*no key*"] ([user ? "[user]" : "*null*"]) at [x],[y],[z]. They have joined as [new_voice.name]."
|
||||
message_admins(msg)
|
||||
log_game(msg)
|
||||
voice_mob.mind = candidate.mind //Transfer the mind, if any.
|
||||
voice_mob.ckey = candidate.ckey //Finally, bring the client over.
|
||||
new_voice.mind = candidate.mind //Transfer the mind, if any.
|
||||
new_voice.ckey = candidate.ckey //Finally, bring the client over.
|
||||
voice_mobs.Add(new_voice)
|
||||
|
||||
var/obj/screen/blackness = new() //Makes a black screen, so the candidate can't see what's going on before actually 'connecting' to the communicator.
|
||||
blackness.screen_loc = ui_entire_screen
|
||||
blackness.icon = 'icons/effects/effects.dmi'
|
||||
blackness.icon_state = "1"
|
||||
blackness.mouse_opacity = 2 //Can't see anything!
|
||||
voice_mob.client.screen.Add(blackness)
|
||||
new_voice.client.screen.Add(blackness)
|
||||
|
||||
update_icon()
|
||||
|
||||
//Now for some connection fluff.
|
||||
user << "<span class='notice'>\icon[src] Connecting to [candidate].</span>"
|
||||
src.voice_mob << "<span class='notice'>\icon[src] Attempting to call [src].</span>"
|
||||
if(user)
|
||||
user << "<span class='notice'>\icon[src] Connecting to [candidate].</span>"
|
||||
new_voice << "<span class='notice'>\icon[src] Attempting to call [src].</span>"
|
||||
sleep(10)
|
||||
src.voice_mob << "<span class='notice'>\icon[src] Dialing to [station_name()], Kara Subsystem, [system_name()].</span>"
|
||||
new_voice << "<span class='notice'>\icon[src] Dialing to [station_name()], Kara Subsystem, [system_name()].</span>"
|
||||
sleep(20)
|
||||
src.voice_mob << "<span class='notice'>\icon[src] Connecting to [station_name()] telecommunications array.</span>"
|
||||
new_voice << "<span class='notice'>\icon[src] Connecting to [station_name()] telecommunications array.</span>"
|
||||
sleep(40)
|
||||
src.voice_mob << "<span class='notice'>\icon[src] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].</span>"
|
||||
new_voice << "<span class='notice'>\icon[src] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].</span>"
|
||||
sleep(20)
|
||||
|
||||
//We're connected, no need to hide everything.
|
||||
voice_mob.client.screen.Remove(blackness)
|
||||
new_voice.client.screen.Remove(blackness)
|
||||
qdel(blackness)
|
||||
|
||||
voice_mob.stable_connection = 1
|
||||
voice_mob << "<span class='notice'>\icon[src] Connection to [src] established.</span>"
|
||||
voice_mob << "<b>To talk to the person on the other end of the call, just talk normally.</b>"
|
||||
voice_mob << "<b>If you want to end the call, use the 'Hang Up' verb. The other person can also hang up at any time.</b>"
|
||||
voice_mob << "<b>Remember, your character does not know anything you've learned from observing!</b>"
|
||||
if(voice_mob.mind)
|
||||
voice_mob.mind.assigned_role = "Disembodied Voice"
|
||||
user << "<span class='notice'>\icon[src] Your communicator is now connected to [candidate]'s communicator.</span>"
|
||||
new_voice << "<span class='notice'>\icon[src] Connection to [src] established.</span>"
|
||||
new_voice << "<b>To talk to the person on the other end of the call, just talk normally.</b>"
|
||||
new_voice << "<b>If you want to end the call, use the 'Hang Up' verb. The other person can also hang up at any time.</b>"
|
||||
new_voice << "<b>Remember, your character does not know anything you've learned from observing!</b>"
|
||||
if(new_voice.mind)
|
||||
new_voice.mind.assigned_role = "Disembodied Voice"
|
||||
if(user)
|
||||
user << "<span class='notice'>\icon[src] Your communicator is now connected to [candidate]'s communicator.</span>"
|
||||
|
||||
/obj/item/device/communicator/proc/close_connection(mob/user, var/reason)
|
||||
if(!voice_mob)
|
||||
// Proc: close_connection()
|
||||
// Parameters: 3 (user - the user who initiated the disconnect, target - the mob or device being disconnected, reason - string shown when disconnected)
|
||||
// Description: Deletes specific voice_mobs or disconnects communicators, and shows a message to everyone when doing so. If target is null, all communicators
|
||||
// and voice mobs are removed.
|
||||
/obj/item/device/communicator/proc/close_connection(mob/user, var/atom/target, var/reason)
|
||||
if(voice_mobs.len == 0 && communicating.len == 0)
|
||||
return
|
||||
if(user != voice_mob)
|
||||
user << "<span class='notice'>\icon[src] [reason].</span>"
|
||||
voice_mob << "<span class='danger'>\icon[src] [reason].</span>"
|
||||
else
|
||||
if(ismob(loc))
|
||||
user << "<span class='notice'>\icon[src] [reason].</span>"
|
||||
loc << "<span class='danger'>\icon[src] [reason].</span>"
|
||||
qdel(voice_mob)
|
||||
|
||||
for(var/mob/living/voice/voice in voice_mobs) //Handle ghost-callers
|
||||
if(target && voice != target) //If no target is inputted, it deletes all of them.
|
||||
continue
|
||||
voice << "<span class='danger'>\icon[src] [reason].</span>"
|
||||
visible_message("<span class='danger'>\icon[src] [reason].</span>")
|
||||
voice_mobs.Remove(voice)
|
||||
qdel(voice)
|
||||
|
||||
for(var/obj/item/device/communicator/comm in communicating) //Now we handle real communicators.
|
||||
if(target && comm != target)
|
||||
continue
|
||||
comm.visible_message("<span class='danger'>\icon[src] [reason].</span>")
|
||||
visible_message("<span class='danger'>\icon[src] [reason].</span>")
|
||||
comm.communicating.Remove(src)
|
||||
communicating.Remove(comm)
|
||||
update_icon()
|
||||
|
||||
/obj/item/device/communicator/proc/request(var/mob/candidate)
|
||||
if(!isobserver(candidate))
|
||||
return
|
||||
// Proc: request()
|
||||
// Parameters: 1 (candidate - the ghost or communicator wanting to call the device)
|
||||
// Description: Response to a communicator or observer trying to call the device. Adds them to the list of requesters
|
||||
/obj/item/device/communicator/proc/request(var/atom/candidate)
|
||||
if(candidate in voice_requests)
|
||||
return
|
||||
voice_requests.Add(candidate)
|
||||
var/who = null
|
||||
if(isobserver(candidate))
|
||||
who = candidate.name
|
||||
else if(istype(candidate, /obj/item/device/communicator))
|
||||
var/obj/item/device/communicator/comm = candidate
|
||||
who = comm.owner
|
||||
comm.voice_invites |= src
|
||||
|
||||
if(!who)
|
||||
return
|
||||
|
||||
voice_requests |= candidate
|
||||
|
||||
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(2, loc))
|
||||
@@ -243,17 +508,32 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
L = loc
|
||||
|
||||
if(L)
|
||||
L << "<span class='notice'>\icon[src] Communications request from [candidate].</span>"
|
||||
L << "<span class='notice'>\icon[src] Communications request from [who].</span>"
|
||||
|
||||
// Proc: Destroy()
|
||||
// Parameters: None
|
||||
// Description: Deletes all the voice mobs, disconnects all linked communicators, and cuts lists to allow successful qdel()
|
||||
/obj/item/device/communicator/Destroy()
|
||||
if(voice_mob)
|
||||
voice_mob << "<span class='danger'>\icon[src] Connection timed out with remote host.</span>"
|
||||
qdel(voice_mob)
|
||||
for(var/mob/living/voice/voice in contents)
|
||||
voice_mobs.Remove(voice)
|
||||
voice << "<span class='danger'>\icon[src] Connection timed out with remote host.</span>"
|
||||
qdel(voice)
|
||||
close_connection(reason = "Connection timed out")
|
||||
communicating.Cut()
|
||||
voice_requests.Cut()
|
||||
voice_invites.Cut()
|
||||
all_communicators -= src
|
||||
processing_objects -= src
|
||||
if(exonet)
|
||||
exonet.remove_address()
|
||||
exonet = null
|
||||
..()
|
||||
|
||||
// Proc: update_icon()
|
||||
// Parameters: None
|
||||
// Description: Self explanatory
|
||||
/obj/item/device/communicator/update_icon()
|
||||
if(voice_mob)
|
||||
if(voice_mobs.len > 0)
|
||||
icon_state = "communicator-active"
|
||||
return
|
||||
|
||||
@@ -263,37 +543,55 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
// Proc: see_emote()
|
||||
// Parameters: 2 (M - the mob the emote originated from, text - the emote's contents)
|
||||
// Description: Relays the emote to all linked communicators.
|
||||
/obj/item/device/communicator/see_emote(mob/living/M, text)
|
||||
if(voice_mob && voice_mob.client)
|
||||
if(!voice_mob.stable_connection)
|
||||
return 0
|
||||
var/rendered = "<span class='message'>[text]</span>"
|
||||
voice_mob.show_message(rendered, 2)
|
||||
var/rendered = "\icon[src] <span class='message'>[text]</span>"
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
for(var/mob/mob in viewers(get_turf(comm))) //We can't use visible_message(), or else we will get an infinite loop if two communicators hear each other.
|
||||
mob.show_message(rendered)
|
||||
for(var/mob/living/voice/V in comm.contents)
|
||||
V.show_message(rendered)
|
||||
..()
|
||||
|
||||
// Proc: hear_talk()
|
||||
// Parameters: 4 (M - the mob the speech originated from, text - what is being said, verb - the word used to describe how text is being said, speaking - language
|
||||
// being used)
|
||||
// Description: Relays the speech to all linked communicators.
|
||||
/obj/item/device/communicator/hear_talk(mob/living/M, text, verb, datum/language/speaking)
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
var/list/mobs_to_relay = list()
|
||||
mobs_to_relay |= viewers(get_turf(comm))
|
||||
mobs_to_relay |= comm.contents //Needed so ghost-callers can see speech.
|
||||
for(var/mob/mob in mobs_to_relay)
|
||||
//Can whoever is hearing us understand?
|
||||
if(!mob.say_understands(M, speaking))
|
||||
if(speaking)
|
||||
text = speaking.scramble(text)
|
||||
else
|
||||
text = stars(text)
|
||||
var/name_used = M.GetVoice()
|
||||
var/rendered = null
|
||||
if(speaking) //Language being used
|
||||
rendered = "<span class='game say'>\icon[src] <span class='name'>[name_used]</span> [speaking.format_message(text, verb)]</span>"
|
||||
else
|
||||
rendered = "<span class='game say'>\icon[src] <span class='name'>[name_used]</span> [verb], <span class='message'>\"[text]\"</span></span>"
|
||||
mob.show_message(rendered, 2)
|
||||
|
||||
// Proc: show_message()
|
||||
// Parameters: 4 (msg - the message, type - number to determine if message is visible or audible, alt - unknown, alt_type - unknown)
|
||||
// Description: Relays the message to all linked communicators.
|
||||
/obj/item/device/communicator/show_message(msg, type, alt, alt_type)
|
||||
if(voice_mob && voice_mob.client)
|
||||
if(!voice_mob.stable_connection)
|
||||
return 0
|
||||
var/rendered = "<span class='message'>[msg]</span>"
|
||||
voice_mob.show_message(rendered, type)
|
||||
var/rendered = "\icon[src] <span class='message'>[msg]</span>"
|
||||
for(var/obj/item/device/communicator/comm in communicating)
|
||||
for(var/mob/mob in hearers(get_turf(comm))) //Ditto for audible messages.
|
||||
mob.show_message(rendered)
|
||||
..()
|
||||
|
||||
/obj/item/device/communicator/attackby(obj/item/C as obj, mob/user as mob)
|
||||
if(istype(C, /obj/item/weapon/card/id))
|
||||
var/obj/item/weapon/card/id/idcard = C
|
||||
if(!idcard.registered_name)
|
||||
user << "<span class='notice'>\icon[src] \The [src] rejects the ID.</span>"
|
||||
return
|
||||
if(!owner)
|
||||
owner = idcard.registered_name
|
||||
owner_job = idcard.assignment
|
||||
owner_rank = idcard.rank
|
||||
name = "\improper communicator-[owner] ([owner_job])"
|
||||
user << "<span class='notice'>\icon[src] Card scanned.</span>"
|
||||
else
|
||||
..()
|
||||
|
||||
// Verb: join_as_voice()
|
||||
// Parameters: None
|
||||
// Description: Allows ghosts to call communicators, if they meet all the requirements.
|
||||
/mob/dead/verb/join_as_voice()
|
||||
set category = "Ghost"
|
||||
set name = "Call Communicator"
|
||||
@@ -319,25 +617,50 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
|
||||
src << "<span class='danger'>Your identity is already present in the game world. Please load in a different character first.</span>"
|
||||
return
|
||||
|
||||
if(!all_communicators.len)
|
||||
var/obj/machinery/exonet_node/E = get_exonet_node()
|
||||
if(!E || !E.on || !E.allow_external_communicators)
|
||||
src << "<span class='danger'>The Exonet node at telecommunications is down at the moment, or is actively blocking you, so your call can't go through.</span>"
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/obj/item/device/communicator/comm in all_communicators)
|
||||
if(!comm.network_visibility || !comm.exonet || !comm.exonet.address)
|
||||
continue
|
||||
choices.Add(comm)
|
||||
|
||||
if(!choices.len)
|
||||
src << "<span class='danger'>There are no available communicators, sorry.</span>"
|
||||
return
|
||||
|
||||
if(!get_message_server())
|
||||
src << "<span class='danger'>The messaging server or telecommunications is down at the moment, so your call can't go through.</span>"
|
||||
return
|
||||
|
||||
var/choice = input(src,"Send a voice request to whom?") as null|anything in all_communicators
|
||||
var/choice = input(src,"Send a voice request to whom?") as null|anything in choices
|
||||
if(choice)
|
||||
var/obj/item/device/communicator/chosen_communicator = choice
|
||||
chosen_communicator.request(src)
|
||||
var/mob/dead/observer/O = src
|
||||
if(O.exonet)
|
||||
O.exonet.send_message(chosen_communicator.exonet.address, "voice")
|
||||
|
||||
src << "A communications request has been sent to [chosen_communicator]. Now you need to wait until someone answers."
|
||||
src << "A communications request has been sent to [chosen_communicator]. Now you need to wait until someone answers."
|
||||
|
||||
/obj/item/device/communicator/integrated //For synths who have no hands.
|
||||
name = "integrated communicator"
|
||||
desc = "A circuit used for long-range communications, able to be integrated into a system."
|
||||
|
||||
//A stupid hack because synths don't use languages properly or something.
|
||||
//I don't want to go digging in saycode for a week, so BS it as translation software or something.
|
||||
|
||||
// Proc: open_connection_to_ghost()
|
||||
// Parameters: 2 (refer to base definition for arguments)
|
||||
// Description: Synths don't use languages properly, so this is a bandaid fix until that can be resolved..
|
||||
/obj/item/device/communicator/integrated/open_connection_to_ghost(user, candidate)
|
||||
..(user, candidate)
|
||||
spawn(1)
|
||||
for(var/mob/living/voice/V in contents)
|
||||
V.universal_speak = 1
|
||||
V.universal_understand = 1
|
||||
|
||||
// Verb: activate()
|
||||
// Parameters: None
|
||||
// Description: Lets synths use their communicators without hands.
|
||||
/obj/item/device/communicator/integrated/verb/activate()
|
||||
set category = "AI IM"
|
||||
set name = "Use Communicator"
|
||||
|
||||
@@ -273,13 +273,13 @@ var/global/list/default_medbay_channels = list(
|
||||
// Fix for permacell radios, but kinda eh about actually fixing them.
|
||||
if(!M || !message) return 0
|
||||
|
||||
if(istype(M)) M.trigger_aiming(TARGET_CAN_RADIO)
|
||||
|
||||
// Uncommenting this. To the above comment:
|
||||
// The permacell radios aren't suppose to be able to transmit, this isn't a bug and this "fix" is just making radio wires useless. -Giacom
|
||||
if(wires.IsIndexCut(WIRE_TRANSMIT)) // The device has to have all its wires and shit intact
|
||||
return 0
|
||||
|
||||
M.last_target_radio = world.time // For the projectile targeting system
|
||||
|
||||
if(!radio_connection)
|
||||
set_frequency(frequency)
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ A list of items and costs is stored under the datum of every game mode, alongsid
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui) // No auto-refresh
|
||||
ui = new(user, src, ui_key, "uplink.tmpl", title, 450, 600, state = inventory_state)
|
||||
data["menu"] = 0
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
build_cost = 1
|
||||
build_type = "floor"
|
||||
build_turf = /turf/simulated/floor/airless
|
||||
else if(!deconstruct && istype(T,/turf/simulated/floor/asteroid))
|
||||
else if(!deconstruct && istype(T,/turf/simulated/mineral/floor))
|
||||
build_cost = 1
|
||||
build_type = "floor"
|
||||
build_turf = /turf/simulated/floor/plating
|
||||
@@ -114,8 +114,8 @@
|
||||
build_cost = 5
|
||||
build_type = (!canRwall && W.reinf_material) ? null : "wall"
|
||||
build_turf = /turf/simulated/floor
|
||||
else if(istype(T,/turf/simulated/floor))
|
||||
var/turf/simulated/floor/F = T
|
||||
else if(istype(T,/turf/simulated/floor) || (istype(T,/turf/simulated/mineral) && !T.density))
|
||||
var/turf/simulated/F = T
|
||||
build_delay = deconstruct ? 50 : 20
|
||||
build_cost = deconstruct ? 10 : 3
|
||||
build_type = deconstruct ? "floor" : "wall"
|
||||
|
||||
@@ -94,10 +94,6 @@
|
||||
icon_state = "id"
|
||||
item_state = "card-id"
|
||||
|
||||
sprite_sheets = list(
|
||||
"Resomi" = 'icons/mob/species/resomi/id.dmi'
|
||||
)
|
||||
|
||||
var/access = list()
|
||||
var/registered_name = "Unknown" // The name registered_name on the card
|
||||
slot_flags = SLOT_ID
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef T_BOARD
|
||||
#error T_BOARD macro is not defined but we need it!
|
||||
#error T_BOARD macro is not defined but we need it!
|
||||
#endif
|
||||
|
||||
/obj/item/weapon/circuitboard/telecomms
|
||||
@@ -73,3 +73,17 @@
|
||||
"/obj/item/weapon/stock_parts/subspace/filter" = 1,
|
||||
"/obj/item/weapon/stock_parts/subspace/crystal" = 1,
|
||||
"/obj/item/weapon/stock_parts/micro_laser/high" = 2)
|
||||
|
||||
//This isn't a real telecomms board but I don't want to make a whole file to hold only one circuitboard.
|
||||
/obj/item/weapon/circuitboard/telecomms/exonet_node
|
||||
name = T_BOARD("exonet node")
|
||||
build_path = "/obj/machinery/exonet_node"
|
||||
origin_tech = list(TECH_DATA = 5, TECH_ENGINEERING = 5, TECH_BLUESPACE = 4)
|
||||
req_components = list(
|
||||
"/obj/item/weapon/stock_parts/subspace/ansible" = 1,
|
||||
"/obj/item/weapon/stock_parts/subspace/filter" = 1,
|
||||
"/obj/item/weapon/stock_parts/manipulator" = 2,
|
||||
"/obj/item/weapon/stock_parts/micro_laser" = 1,
|
||||
"/obj/item/weapon/stock_parts/subspace/crystal" = 1,
|
||||
"/obj/item/weapon/stock_parts/subspace/treatment" = 2,
|
||||
"/obj/item/stack/cable_coil" = 2)
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
var/breakouttime = 1200 //Deciseconds = 120s = 2 minutes
|
||||
var/cuff_sound = 'sound/weapons/handcuffs.ogg'
|
||||
var/cuff_type = "handcuffs"
|
||||
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/handcuffs.dmi')
|
||||
|
||||
/obj/item/weapon/handcuffs/attack(var/mob/living/carbon/C, var/mob/living/user)
|
||||
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
slot_l_hand_str = "backpack",
|
||||
slot_r_hand_str = "backpack",
|
||||
)
|
||||
sprite_sheets = list(
|
||||
"Resomi" = 'icons/mob/species/resomi/back.dmi'
|
||||
)
|
||||
w_class = 4
|
||||
slot_flags = SLOT_BACK
|
||||
max_w_class = 3
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
item_state = "utility"
|
||||
slot_flags = SLOT_BELT
|
||||
attack_verb = list("whipped", "lashed", "disciplined")
|
||||
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/belt.dmi')
|
||||
|
||||
var/show_above_suit = 0
|
||||
|
||||
|
||||
@@ -23,10 +23,6 @@ var/list/global/tank_gauge_cache = list()
|
||||
throw_speed = 1
|
||||
throw_range = 4
|
||||
|
||||
sprite_sheets = list(
|
||||
"Resomi" = 'icons/mob/species/resomi/back.dmi'
|
||||
)
|
||||
|
||||
var/datum/gas_mixture/air_contents = null
|
||||
var/distribute_pressure = ONE_ATMOSPHERE
|
||||
var/integrity = 3
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/structure/proc/can_climb(var/mob/living/user, post_climb_check=0)
|
||||
if (!can_touch(user) || !climbable || (!post_climb_check && (user in climbers)))
|
||||
if (!climbable || !can_touch(user) || (!post_climb_check && (user in climbers)))
|
||||
return 0
|
||||
|
||||
if (!user.Adjacent(src))
|
||||
|
||||
@@ -10,10 +10,11 @@
|
||||
|
||||
/obj/structure/lattice/New() //turf/simulated/floor/asteroid
|
||||
..()
|
||||
///// Z-Level Stuff
|
||||
if(!(istype(src.loc, /turf/space) || istype(src.loc, /turf/simulated/open) || istype(src.loc, /turf/simulated/floor/asteroid)))
|
||||
///// Z-Level Stuff
|
||||
|
||||
if(!(istype(src.loc, /turf/space) || istype(src.loc, /turf/simulated/open) || istype(src.loc, /turf/simulated/mineral)))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
for(var/obj/structure/lattice/LAT in src.loc)
|
||||
if(LAT != src)
|
||||
qdel(LAT)
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ var/round_progressing = 1
|
||||
//Set to 1 to enable it.
|
||||
var/destroy_floor_override = 1
|
||||
//Below is the path of turf used in place of space tiles.
|
||||
var/destroy_floor_override_path = /turf/simulated/floor/asteroid
|
||||
var/destroy_floor_override_path = /turf/simulated/mineral/floor
|
||||
//A list of z-levels to apply the override to. This is so z-levels like tcomms work as they did before.
|
||||
var/list/destroy_floor_override_z_levels = list(1,4,5)
|
||||
//Some areas you may want to not turn into the override path you made above, like space or the solars.
|
||||
|
||||
@@ -1342,3 +1342,19 @@ proc/admin_notice(var/message, var/rights)
|
||||
message_admins(msg)
|
||||
else
|
||||
usr << "You do not have access to this command."
|
||||
|
||||
/datum/admins/proc/paralyze_mob(mob/living/H as mob)
|
||||
set category = "Admin"
|
||||
set name = "Toggle Paralyze"
|
||||
set desc = "Paralyzes a player. Or unparalyses them."
|
||||
|
||||
var/msg
|
||||
|
||||
if(check_rights(R_ADMIN|R_MOD))
|
||||
if (H.paralysis == 0)
|
||||
H.paralysis = 8000
|
||||
msg = "[key_name(usr)] has paralyzed [key_name(H)]."
|
||||
else
|
||||
H.paralysis = 0
|
||||
msg = "[key_name(usr)] has unparalyzed [key_name(H)]."
|
||||
message_admins(msg)
|
||||
|
||||
@@ -94,7 +94,8 @@ var/list/admin_verbs_admin = list(
|
||||
/client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */
|
||||
/client/proc/change_security_level,
|
||||
/client/proc/view_chemical_reaction_logs,
|
||||
/client/proc/makePAI
|
||||
/client/proc/makePAI,
|
||||
/datum/admins/proc/paralyze_mob
|
||||
)
|
||||
var/list/admin_verbs_ban = list(
|
||||
/client/proc/unban_panel,
|
||||
@@ -303,7 +304,8 @@ var/list/admin_verbs_mod = list(
|
||||
/datum/admins/proc/show_player_panel,
|
||||
/client/proc/check_antagonists,
|
||||
/client/proc/jobbans,
|
||||
/client/proc/cmd_admin_subtle_message /*send an message to somebody as a 'voice in their head'*/
|
||||
/client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/
|
||||
/datum/admins/proc/paralyze_mob
|
||||
)
|
||||
|
||||
var/list/admin_verbs_mentor = list(
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
update_icon()
|
||||
|
||||
/obj/effect/blob/proc/expand(var/turf/T)
|
||||
if(istype(T, /turf/unsimulated/) || istype(T, /turf/space))
|
||||
if(istype(T, /turf/unsimulated/) || istype(T, /turf/space) || (istype(T, /turf/simulated/mineral) && T.density))
|
||||
return
|
||||
if(istype(T, /turf/simulated/wall))
|
||||
var/turf/simulated/wall/SW = T
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
if(href_list["flavor_text"])
|
||||
switch(href_list["flavor_text"])
|
||||
if("open")
|
||||
else if("general")
|
||||
var/msg = sanitize(input(usr,"Give a general description of your character. This will be shown regardless of clothing, and may include OOC notes and preferences.","Flavor Text",html_decode(pref.flavor_texts[href_list["task"]])) as message, extra = 0)
|
||||
if("general")
|
||||
var/msg = sanitize(input(usr,"Give a general description of your character. This will be shown regardless of clothing, and may include OOC notes and preferences.","Flavor Text",html_decode(pref.flavor_texts[href_list["flavor_text"]])) as message, extra = 0)
|
||||
if(CanUseTopic(user))
|
||||
pref.flavor_texts[href_list["flavor_text"]] = msg
|
||||
else
|
||||
@@ -59,7 +59,7 @@
|
||||
else if(href_list["flavour_text_robot"])
|
||||
switch(href_list["flavour_text_robot"])
|
||||
if("open")
|
||||
else if("Default")
|
||||
if("Default")
|
||||
var/msg = sanitize(input(usr,"Set the default flavour text for your robot. It will be used for any module without individual setting.","Flavour Text",html_decode(pref.flavour_texts_robot["Default"])) as message, extra = 0)
|
||||
if(CanUseTopic(user))
|
||||
pref.flavour_texts_robot[href_list["flavour_text_robot"]] = msg
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/datum/category_item/player_setup_item/player_global/communicators
|
||||
name = "Communicators"
|
||||
sort_order = 4
|
||||
|
||||
/datum/category_item/player_setup_item/player_global/communicators/load_preferences(var/savefile/S)
|
||||
S["communicator_visibility"] >> pref.communicator_visibility
|
||||
|
||||
|
||||
/datum/category_item/player_setup_item/player_global/communicators/save_preferences(var/savefile/S)
|
||||
S["communicator_visibility"] << pref.communicator_visibility
|
||||
|
||||
|
||||
/datum/category_item/player_setup_item/player_global/communicators/sanitize_preferences()
|
||||
pref.communicator_visibility = sanitize_integer(pref.communicator_visibility, 0, 1, initial(pref.communicator_visibility))
|
||||
|
||||
/datum/category_item/player_setup_item/player_global/communicators/content(var/mob/user)
|
||||
. += "<b>Communicator Identity:</b><br>"
|
||||
. += "Visibility: <a href='?src=\ref[src];toggle_comm_visibility=1'><b>[(pref.communicator_visibility) ? "Yes" : "No"]</b></a><br>"
|
||||
|
||||
/datum/category_item/player_setup_item/player_global/communicators/OnTopic(var/href,var/list/href_list, var/mob/user)
|
||||
if(href_list["toggle_comm_visibility"])
|
||||
if(CanUseTopic(user))
|
||||
pref.communicator_visibility = !pref.communicator_visibility
|
||||
return TOPIC_REFRESH
|
||||
|
||||
return ..()
|
||||
@@ -89,6 +89,9 @@
|
||||
var/available_in_days = job.available_in_days(user.client)
|
||||
. += "<del>[rank]</del></td><td> \[IN [(available_in_days)] DAYS]</td></tr>"
|
||||
continue
|
||||
if(job.minimum_character_age && user.client && (user.client.prefs.age < job.minimum_character_age))
|
||||
. += "<del>[rank]</del></td><td> \[MINIMUM CHARACTER AGE: [job.minimum_character_age]]</td></tr>"
|
||||
continue
|
||||
if((pref.job_civilian_low & ASSISTANT) && (rank != "Assistant"))
|
||||
. += "<font color=orange>[rank]</font></td><td></td></tr>"
|
||||
continue
|
||||
|
||||
@@ -108,6 +108,9 @@ datum/preferences
|
||||
// OOC Metadata:
|
||||
var/metadata = ""
|
||||
|
||||
// Communicator identity data
|
||||
var/communicator_visibility = 0
|
||||
|
||||
var/client/client = null
|
||||
|
||||
var/datum/category_collection/player_setup_collection/player_setup
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -38,7 +38,6 @@
|
||||
icons.Add(usr.gun_setting_icon)
|
||||
icons.Add(usr.item_use_icon)
|
||||
icons.Add(usr.gun_move_icon)
|
||||
icons.Add(usr.gun_run_icon)
|
||||
icons.Add(usr.radio_use_icon)
|
||||
|
||||
var/icon/ic = all_ui_styles[UI_style_new]
|
||||
|
||||
@@ -101,7 +101,6 @@
|
||||
w_class = 1.0
|
||||
throwforce = 2
|
||||
slot_flags = SLOT_EARS
|
||||
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/ears.dmi')
|
||||
|
||||
/obj/item/clothing/ears/attack_hand(mob/user as mob)
|
||||
if (!user) return
|
||||
@@ -209,10 +208,6 @@ BLIND // can't see anything
|
||||
var/vision_flags = 0
|
||||
var/darkness_view = 0//Base human is 2
|
||||
var/see_invisible = -1
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/eyes.dmi',
|
||||
"Resomi" = 'icons/mob/species/resomi/eyes.dmi',
|
||||
)
|
||||
|
||||
/obj/item/clothing/glasses/update_clothing_icon()
|
||||
if (ismob(src.loc))
|
||||
@@ -235,8 +230,7 @@ BLIND // can't see anything
|
||||
attack_verb = list("challenged")
|
||||
species_restricted = list("exclude","Unathi","Tajara", "Vox")
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/gloves.dmi',
|
||||
"Resomi" = 'icons/mob/species/resomi/gloves.dmi',
|
||||
"Vox" = 'icons/mob/species/vox/gloves.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/gloves/update_clothing_icon()
|
||||
@@ -293,8 +287,7 @@ BLIND // can't see anything
|
||||
var/on = 0
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/head.dmi',
|
||||
"Resomi" = 'icons/mob/species/resomi/head.dmi'
|
||||
"Vox" = 'icons/mob/species/vox/head.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/head/attack_self(mob/user)
|
||||
@@ -392,8 +385,7 @@ BLIND // can't see anything
|
||||
slot_flags = SLOT_MASK
|
||||
body_parts_covered = FACE|EYES
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/masks.dmi',
|
||||
"Resomi" = 'icons/mob/species/resomi/masks.dmi',
|
||||
"Vox" = 'icons/mob/species/vox/masks.dmi'
|
||||
)
|
||||
|
||||
var/voicechange = 0
|
||||
@@ -428,8 +420,7 @@ BLIND // can't see anything
|
||||
var/overshoes = 0
|
||||
species_restricted = list("exclude","Unathi","Tajara","Vox")
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/shoes.dmi',
|
||||
"Resomi" = 'icons/mob/species/resomi/shoes.dmi',
|
||||
"Vox" = 'icons/mob/species/vox/shoes.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/shoes/proc/draw_knife()
|
||||
@@ -503,8 +494,7 @@ BLIND // can't see anything
|
||||
w_class = 3
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi',
|
||||
"Resomi" = 'icons/mob/species/resomi/suit.dmi'
|
||||
"Vox" = 'icons/mob/species/vox/suit.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/suit/update_clothing_icon()
|
||||
@@ -537,8 +527,7 @@ BLIND // can't see anything
|
||||
var/displays_id = 1
|
||||
var/rolled_down = -1 //0 = unrolled, 1 = rolled, -1 = cannot be toggled
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/uniform.dmi',
|
||||
"Resomi" = 'icons/mob/species/resomi/uniform.dmi'
|
||||
"Vox" = 'icons/mob/species/vox/uniform.dmi'
|
||||
)
|
||||
|
||||
//convenience var for defining the icon state for the overlay used when the clothing is worn.
|
||||
|
||||
@@ -28,8 +28,56 @@
|
||||
icon_state = "skrell_cloth_female"
|
||||
item_state = "skrell_cloth_female"
|
||||
|
||||
/obj/item/clothing/ears/skrell/cloth_female/black
|
||||
name = "skrell headtail cloth"
|
||||
desc = "A cloth shawl worn by female skrell draped around their head tails."
|
||||
icon_state = "skrell_cloth_black_female"
|
||||
item_state = "skrell_cloth_black_female"
|
||||
|
||||
/obj/item/clothing/ears/skrell/cloth_female/blue
|
||||
name = "skrell headtail cloth"
|
||||
desc = "A cloth shawl worn by female skrell draped around their head tails."
|
||||
icon_state = "skrell_cloth_blue_female"
|
||||
item_state = "skrell_cloth_blue_female"
|
||||
|
||||
/obj/item/clothing/ears/skrell/cloth_female/green
|
||||
name = "skrell headtail cloth"
|
||||
desc = "A cloth shawl worn by female skrell draped around their head tails."
|
||||
icon_state = "skrell_cloth_green_female"
|
||||
item_state = "skrell_cloth_green_female"
|
||||
|
||||
/obj/item/clothing/ears/skrell/cloth_female/pink
|
||||
name = "skrell headtail cloth"
|
||||
desc = "A cloth shawl worn by female skrell draped around their head tails."
|
||||
icon_state = "skrell_cloth_pink_female"
|
||||
item_state = "skrell_cloth_pink_female"
|
||||
|
||||
/obj/item/clothing/ears/skrell/cloth_male
|
||||
name = "skrell headtail cloth"
|
||||
desc = "A cloth band worn by male skrell around their head tails."
|
||||
icon_state = "skrell_cloth_male"
|
||||
item_state = "skrell_cloth_male"
|
||||
item_state = "skrell_cloth_male"
|
||||
|
||||
/obj/item/clothing/ears/skrell/cloth_male/black
|
||||
name = "skrell headtail cloth"
|
||||
desc = "A cloth band worn by male skrell around their head tails."
|
||||
icon_state = "skrell_cloth_black_male"
|
||||
item_state = "skrell_cloth_black_male"
|
||||
|
||||
/obj/item/clothing/ears/skrell/cloth_male/blue
|
||||
name = "skrell headtail cloth"
|
||||
desc = "A cloth band worn by male skrell around their head tails."
|
||||
icon_state = "skrell_cloth_blue_male"
|
||||
item_state = "skrell_cloth_blue_male"
|
||||
|
||||
/obj/item/clothing/ears/skrell/cloth_male/green
|
||||
name = "skrell headtail cloth"
|
||||
desc = "A cloth band worn by male skrell around their head tails."
|
||||
icon_state = "skrell_cloth_green_male"
|
||||
item_state = "skrell_cloth_green_male"
|
||||
|
||||
/obj/item/clothing/ears/skrell/cloth_male/pink
|
||||
name = "skrell headtail cloth"
|
||||
desc = "A cloth band worn by male skrell around their head tails."
|
||||
icon_state = "skrell_cloth_pink_male"
|
||||
item_state = "skrell_cloth_pink_male"
|
||||
@@ -19,7 +19,6 @@
|
||||
/obj/item/clothing/glasses/hud/health/prescription
|
||||
name = "Prescription Health Scanner HUD"
|
||||
desc = "A medical HUD integrated with a set of prescription glasses"
|
||||
icon_state = "healthhud"
|
||||
prescription = 1
|
||||
icon_state = "healthhudpresc"
|
||||
item_state = "healthhudpresc"
|
||||
@@ -37,7 +36,6 @@
|
||||
/obj/item/clothing/glasses/hud/security/prescription
|
||||
name = "Prescription Security HUD"
|
||||
desc = "A security HUD integrated with a set of prescription glasses"
|
||||
icon_state = "securityhud"
|
||||
prescription = 1
|
||||
icon_state = "sechudpresc"
|
||||
item_state = "sechudpresc"
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
desc = "an ultra rare hat. It commands a certain respect."
|
||||
icon_state = "petehat"
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/head.dmi',
|
||||
"Resomi" = 'icons/mob/species/resomi/head.dmi'
|
||||
"Vox" = 'icons/mob/species/vox/head.dmi'
|
||||
)
|
||||
|
||||
/obj/item/clothing/head/collectable/slime
|
||||
|
||||
@@ -204,6 +204,13 @@
|
||||
|
||||
//end bs12 hats
|
||||
|
||||
/obj/item/clothing/head/cowboy_hat
|
||||
name = "cowboy hat"
|
||||
desc = "For those that have spurs that go jingle jangle jingle."
|
||||
icon_state = "cowboyhat"
|
||||
item_state = "cowboy_hat"
|
||||
body_parts_covered = 0
|
||||
|
||||
/obj/item/clothing/head/witchwig
|
||||
name = "witch costume wig"
|
||||
desc = "Eeeee~heheheheheheh!"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Ushanka
|
||||
* Pumpkin head
|
||||
* Kitty ears
|
||||
*
|
||||
* Holiday hats
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -153,3 +153,15 @@
|
||||
icon_state = "richard"
|
||||
body_parts_covered = HEAD|FACE
|
||||
flags_inv = BLOCKHAIR
|
||||
|
||||
/obj/item/clothing/head/santa
|
||||
name = "santa hat"
|
||||
desc = "It's a festive christmas hat, in red!"
|
||||
icon_state = "santahatnorm"
|
||||
body_parts_covered = 0
|
||||
|
||||
/obj/item/clothing/head/santa/green
|
||||
name = "green santa hat"
|
||||
desc = "It's a festive christmas hat, in green!"
|
||||
icon_state = "santahatgreen"
|
||||
body_parts_covered = 0
|
||||
@@ -851,7 +851,6 @@
|
||||
return 0
|
||||
|
||||
// AIs are a bit slower than regular and ignore move intent.
|
||||
wearer.last_move_intent = world.time + ai_controlled_move_delay
|
||||
wearer_move_delay = world.time + ai_controlled_move_delay
|
||||
|
||||
var/tickcomp = 0
|
||||
|
||||
@@ -355,17 +355,17 @@
|
||||
icon_state = "puffervest"
|
||||
item_state = "puffervest"
|
||||
|
||||
/obj/item/clothing/suit/jacket/miljacket
|
||||
/obj/item/clothing/suit/storage/miljacket
|
||||
name = "military jacket"
|
||||
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable."
|
||||
icon_state = "militaryjacket"
|
||||
item_state = "militaryjacket"
|
||||
icon_state = "militaryjacket_nobadge"
|
||||
item_state = "militaryjacket_nobadge"
|
||||
|
||||
/obj/item/clothing/suit/jacket/miljacket2
|
||||
/obj/item/clothing/suit/storage/miljacket/alt
|
||||
name = "military jacket"
|
||||
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable."
|
||||
icon_state = "militaryjacket2"
|
||||
item_state = "militaryjacket2"
|
||||
icon_state = "militaryjacket_badge"
|
||||
item_state = "militaryjacket_badge"
|
||||
|
||||
/obj/item/clothing/suit/storage/toggle/bomber
|
||||
name = "bomber jacket"
|
||||
@@ -478,6 +478,29 @@
|
||||
icon_open = "yellow_hoodie_open"
|
||||
icon_closed = "yellow_hoodie"
|
||||
|
||||
/obj/item/clothing/suit/storage/toggle/hoodie/cti
|
||||
name = "CTI hoodie"
|
||||
desc = "A warm, black sweatshirt. It bears the letters ‘CTI’ on the back, a lettering to the prestigious university in Tau Ceti, Ceti Technical Institute. There is a blue supernova embroidered on the front, the emblem of CTI."
|
||||
icon_state = "cti_hoodie"
|
||||
item_state = "cti_hoodie"
|
||||
icon_open = "cti_hoodie_open"
|
||||
icon_closed = "cti_hoodie"
|
||||
|
||||
/obj/item/clothing/suit/storage/toggle/hoodie/mu
|
||||
name = "mars university hoodie"
|
||||
desc = "A warm, gray sweatshirt. It bears the letters ‘MU’ on the front, a lettering to the well-known public college, Mars University."
|
||||
icon_state = "mu_hoodie"
|
||||
item_state = "mu_hoodie"
|
||||
icon_open = "mu_hoodie_open"
|
||||
icon_closed = "mu_hoodie"
|
||||
|
||||
/obj/item/clothing/suit/storage/toggle/hoodie/nt
|
||||
name = "NT hoodie"
|
||||
desc = "A warm, blue sweatshirt. It proudly bears the silver NanoTrasen insignia lettering on the back. The edges are trimmed with silver."
|
||||
icon_state = "nt_hoodie"
|
||||
item_state = "nt_hoodie"
|
||||
icon_open = "nt_hoodie_open"
|
||||
icon_closed = "nt_hoodie"
|
||||
|
||||
// FUN!
|
||||
|
||||
@@ -557,12 +580,12 @@
|
||||
/obj/item/clothing/suit/storage/hooded/wintercoat/captain
|
||||
name = "captain's winter coat"
|
||||
icon_state = "coatcaptain"
|
||||
armor = list(melee = 25, bullet = 30, laser = 30, energy = 10, bomb = 25, bio = 0, rad = 0)
|
||||
armor = list(melee = 20, bullet = 15, laser = 20, energy = 10, bomb = 15, bio = 0, rad = 0)
|
||||
|
||||
/obj/item/clothing/suit/storage/hooded/wintercoat/security
|
||||
name = "security winter coat"
|
||||
icon_state = "coatsecurity"
|
||||
armor = list(melee = 25, bullet = 15, laser = 30, energy = 10, bomb = 25, bio = 0, rad = 0)
|
||||
armor = list(melee = 25, bullet = 20, laser = 20, energy = 15, bomb = 20, bio = 0, rad = 0)
|
||||
|
||||
/obj/item/clothing/suit/storage/hooded/wintercoat/medical
|
||||
name = "medical winter coat"
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
icon_state = icon_badge
|
||||
usr << "You reveal \the [src]'s badge."
|
||||
else
|
||||
usr << "\The [src] does not have a vest badge."
|
||||
usr << "\The [src] does not have a badge."
|
||||
return
|
||||
update_clothing_icon()
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
slot = "utility"
|
||||
var/obj/item/holstered = null
|
||||
|
||||
/obj/item/clothing/accessory/holster/proc/holster(obj/item/I, mob/user as mob)
|
||||
if(holstered)
|
||||
/obj/item/clothing/accessory/holster/proc/holster(var/obj/item/I, var/mob/living/user)
|
||||
if(holstered && istype(user))
|
||||
user << "<span class='warning'>There is already \a [holstered] holstered here!</span>"
|
||||
return
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
user << "<span class='warning'>[I] won't fit in [src]!</span>"
|
||||
return
|
||||
|
||||
if(istype(user))
|
||||
user.stop_aiming(no_message=1)
|
||||
holstered = I
|
||||
user.drop_from_inventory(holstered)
|
||||
holstered.loc = src
|
||||
|
||||
@@ -566,3 +566,38 @@
|
||||
icon_state = "blue_blazer"
|
||||
item_state = "blue_blazer"
|
||||
worn_state = "blue_blazer"
|
||||
|
||||
/obj/item/clothing/under/croptop
|
||||
name = "crop top"
|
||||
desc = "A shirt that has had the top cropped. This one is NT sponsored."
|
||||
icon_state = "croptop"
|
||||
item_state = "gy_suit"
|
||||
worn_state = "croptop"
|
||||
|
||||
/obj/item/clothing/under/croptop/red
|
||||
name = "red crop top"
|
||||
desc = "A red shirt that has had the top cropped."
|
||||
icon_state = "croptop_red"
|
||||
item_state = "r_suit"
|
||||
worn_state = "croptop_red"
|
||||
|
||||
/obj/item/clothing/under/croptop/grey
|
||||
name = "grey crop top"
|
||||
desc = "A grey shirt that has had the top cropped."
|
||||
icon_state = "croptop_grey"
|
||||
item_state = "gy_suit"
|
||||
worn_state = "croptop_grey"
|
||||
|
||||
/obj/item/clothing/under/cuttop
|
||||
name = "grey cut top"
|
||||
desc = "A grey shirt that has had the top cut low."
|
||||
icon_state = "cuttop"
|
||||
item_state = "gy_suit"
|
||||
worn_state = "cuttop"
|
||||
|
||||
/obj/item/clothing/under/cuttop/red
|
||||
name = "red cut top"
|
||||
desc = "A red shirt that has had the top cut low."
|
||||
icon_state = "cuttop_red"
|
||||
item_state = "r_suit"
|
||||
worn_state = "cuttop_red"
|
||||
@@ -28,3 +28,59 @@
|
||||
name = "grey athletic shorts"
|
||||
icon_state = "greyshorts"
|
||||
worn_state = "greyshorts"
|
||||
|
||||
/obj/item/clothing/under/shorts/jeans
|
||||
name = "jeans shorts"
|
||||
desc = "Some jeans! Just in short form!"
|
||||
icon_state = "jeans_shorts"
|
||||
worn_state = "jeans_shorts"
|
||||
|
||||
/obj/item/clothing/under/shorts/jeans/female
|
||||
icon_state = "jeans_shorts_f"
|
||||
worn_state = "jeans_shorts_f"
|
||||
|
||||
/obj/item/clothing/under/shorts/jeans/classic
|
||||
name = "classic jeans shorts"
|
||||
icon_state = "jeansclassic_shorts"
|
||||
worn_state = "jeansclassic_shorts"
|
||||
|
||||
/obj/item/clothing/under/shorts/jeans/classic/female
|
||||
icon_state = "jeansclassic_shorts_f"
|
||||
worn_state = "jeansclassic_shorts_f"
|
||||
|
||||
/obj/item/clothing/under/shorts/jeans/mustang
|
||||
name = "mustang jeans shorts"
|
||||
icon_state = "jeansmustang_shorts"
|
||||
worn_state = "jeansmustang_shorts"
|
||||
|
||||
/obj/item/clothing/under/shorts/jeans/mustang/female
|
||||
icon_state = "jeansmustang_shorts_f"
|
||||
worn_state = "jeansmustang_shorts_f"
|
||||
|
||||
/obj/item/clothing/under/shorts/jeans/youngfolks
|
||||
name = "young folks jeans shorts"
|
||||
icon_state = "jeansyoungfolks_shorts"
|
||||
worn_state = "jeansyoungfolks_shorts"
|
||||
|
||||
/obj/item/clothing/under/shorts/jeans/youngfolks/female
|
||||
icon_state = "jeansyoungfolks_shorts_f"
|
||||
worn_state = "jeansyoungfolks_shorts_f"
|
||||
|
||||
/obj/item/clothing/under/shorts/jeans/black
|
||||
name = "black jeans shorts"
|
||||
icon_state = "black_shorts"
|
||||
worn_state = "black_shorts"
|
||||
|
||||
/obj/item/clothing/under/shorts/jeans/black/female
|
||||
icon_state = "black_shorts_f"
|
||||
worn_state = "black_shorts_f"
|
||||
|
||||
/obj/item/clothing/under/shorts/khaki
|
||||
name = "khaki shorts"
|
||||
desc = "For that island getaway. It's five o'clock somewhere, right?"
|
||||
icon_state = "khaki_shorts"
|
||||
worn_state = "khaki_shorts"
|
||||
|
||||
/obj/item/clothing/under/shorts/khaki/female
|
||||
icon_state = "khaki_shorts_f"
|
||||
worn_state = "khaki_shorts_f"
|
||||
@@ -1,32 +0,0 @@
|
||||
/obj/item/clothing/under/resomi
|
||||
name = "small grey smock"
|
||||
desc = "It looks fitted to nonhuman proportions."
|
||||
icon = 'icons/obj/clothing/species/resomi/uniform.dmi'
|
||||
icon_state = "resomi_grey"
|
||||
worn_state = "resomi_grey"
|
||||
species_restricted = list("Resomi")
|
||||
|
||||
/obj/item/clothing/under/resomi/white
|
||||
name = "small white smock"
|
||||
icon_state = "resomi_white"
|
||||
worn_state = "resomi_white"
|
||||
|
||||
/obj/item/clothing/under/resomi/red
|
||||
name = "small Security smock"
|
||||
icon_state = "resomi_red"
|
||||
worn_state = "resomi_red"
|
||||
|
||||
/obj/item/clothing/under/resomi/yellow
|
||||
name = "small Engineering smock"
|
||||
icon_state = "resomi_yellow"
|
||||
worn_state = "resomi_yellow"
|
||||
|
||||
/obj/item/clothing/under/resomi/medical
|
||||
name = "small Medical uniform"
|
||||
icon_state = "resomi_medical"
|
||||
worn_state = "resomi_medical"
|
||||
|
||||
/obj/item/clothing/under/resomi/rainbow
|
||||
name = "small rainbow smock"
|
||||
icon_state = "resomi_rainbow"
|
||||
worn_state = "resomi_rainbow"
|
||||
@@ -18,3 +18,5 @@
|
||||
/datum/event/communications_blackout/start()
|
||||
for(var/obj/machinery/telecomms/T in telecomms_list)
|
||||
T.emp_act(1)
|
||||
for(var/obj/machinery/exonet_node/N in machines)
|
||||
N.emp_act(1)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
endWhen = 36000
|
||||
var/last_spam_time = 0
|
||||
var/obj/machinery/message_server/useMS
|
||||
var/obj/machinery/exonet_node/node
|
||||
|
||||
/datum/event/pda_spam/setup()
|
||||
last_spam_time = world.time
|
||||
@@ -19,6 +20,11 @@
|
||||
//if there's no spam managed to get to receiver for five minutes, give up
|
||||
kill()
|
||||
return
|
||||
if(!node)
|
||||
node = get_exonet_node()
|
||||
|
||||
if(!node || !node.on || !node.allow_external_PDAs)
|
||||
return
|
||||
|
||||
if(!useMS || !useMS.active)
|
||||
useMS = null
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/obj/item/device/communicator
|
||||
description_info = "This device allows someone to speak to another player sourced from the observer pool, as well as other communicators linked to it. \
|
||||
To use the device, use it in your hand, and it will open an interface with various buttons. Near the bottom will be a list of devices currently available \
|
||||
for you to call, both from communications on the station, and communicators very far away (observers). To call someone, send a communications request to \
|
||||
someone and hope they respond, or receive one yourself and respond to them. Hanging up is also simple, and is handled in the 'Manage Connections' tab."
|
||||
|
||||
description_fluff = "As a concept, a device that allows long-distance communication has existed for over five hundred years. A device that can accomplish \
|
||||
that while in space, across star systems, and that the consumer can afford and use without training, is much more recent, and is thanks to the backbone \
|
||||
that is the Exonet.<br>\
|
||||
<br>\
|
||||
The Exonet is the predominant interstellar telecom system, servicing trillions of devices across a large portion of human-controlled space. \
|
||||
It is distributed by a massive network of telecommunication satellites, some privately owned and others owned by the systems’ local governments, \
|
||||
that utilize FTL technologies to bounce data between satellites at speeds that would not be possible at sub-light technology. This communicator \
|
||||
uses a protocol called Exonet Protocol Version 2, generally shortened to EPv2.<br>\
|
||||
<br>\
|
||||
EPv2 is the most common communications protocol in the Exonet, and was specifically designed for it. It was designed to facilitate communication \
|
||||
between any device in a star system, and have the ability to forward interstellar requests at the root node of that system’s Exonet. \
|
||||
It is also built to cope with the reality that the numerous nodes in a system will likely have frequent outages. The protocol allows for \
|
||||
up to 18,446,744,073,709,551,616 unique addresses, one of which is assigned to this device."
|
||||
|
||||
description_antag = "Electromagnetic pulses will cause the device to disconnect all linked communicators. Turning off the Exonet node at the Telecomms \
|
||||
satellite will also accomplish this, but for all communicators on and near the station. This may be needed to allow for a quiet kill or capture."
|
||||
@@ -0,0 +1,36 @@
|
||||
//This is not strictly a telecomms machine but conceptually it is.
|
||||
/obj/machinery/exonet_node
|
||||
description_info = "This machine is needed for several machines back at the colony to interact with systems beyond this region of space, such as \
|
||||
communicators, external PDA messages, and even newscaster units, which host their content externally. You can fiddle with the device with \
|
||||
just your hands, due to the integrated monitor and keyboard. Synthetic units can interface with it as well, just like most other machines."
|
||||
|
||||
description_fluff = "This is one of many nodes that make up the Exonet, which services trillions of devices across space. This particular node \
|
||||
is referred to as a terminal node, servicing the Northern Star.<br>\
|
||||
<br>\
|
||||
In the beginning of humanity's ascend into space, the Exonet didn't exist. Instead, the Exonet is the evolution to a network called the Interplanetary \
|
||||
Internet (sometimes referred to as the InterPlaNet), which was conceived and developed due to the limitations of the terrestrial Internet, mainly because \
|
||||
the IP protocol was unsuitable for long range communications in space, due to the massive delays associated with lightspeed being unable to overcome \
|
||||
the massive distances between planets in a timely manner. It was a store-and-forward network of smaller internets, distributed between various nodes, \
|
||||
and was designed to be error, fault, and delay tolerant. The first nodes were put into space around the time when colonization had begun, to service humanity’s \
|
||||
close holdings, such as Luna and Mars.<br>\
|
||||
<br>\
|
||||
By 2104, the Interplanetary Internet had coverage within most of Sol, but the network of networks were limited by the speed of light, and due \
|
||||
to orbital mechanics, the delay for a request to be processed could vary. As an example, a direct message from Mars to Earth could take anywhere \
|
||||
between three to twenty two minutes to get to Earth, and then the same amount of time to return to Mars. Coverage was also spotty due to the \
|
||||
nature of operating at such vast distances.<br>\
|
||||
<br>\
|
||||
Fortunately, a method for traveling faster than light was discovered, which could allow data to be transmitted beyond the speed of light, \
|
||||
and thus overcome the limitations of the Interplanetary Internet. One by one, each of the nodes were upgraded to utilize cutting edge \
|
||||
(at the time) FTL technologies to rapidly increase response time.<br>\
|
||||
<br>\
|
||||
Once humanity had send colonists out beyond Sol, to other star systems such as Sirius and Alpha Centauri, they required their own interplanetary \
|
||||
internet, so a new protocol had to be created, and another hardware upgrade for the separate interplanetary internets. The end result allowed \
|
||||
communications between Sol and the various exosolar systems, and was dubbed the Exonet. It remains the most common way for consumers to engage \
|
||||
in long range communications across planets and star systems. Generally, each system has their own Exonet, which is connected to all the other \
|
||||
Exonets at the root node(s), and is typically arranged in a tree structure. The root node(s) are generally government-owned and are very secure \
|
||||
and resilient to failure.<br>\
|
||||
<br>\
|
||||
This node is privately owned and maintained by Nanotrasen, and allows the colonists of the Northern Star to have access to the Exonet."
|
||||
|
||||
description_antag = "An EMP will disable this device for a short period of time. A longer downage can be achieved by turning it off, or rigging \
|
||||
the APC it uses to turn off remotely, such as with a signaler in the right wire."
|
||||
@@ -74,12 +74,8 @@
|
||||
return
|
||||
|
||||
//Drill through the flooring, if any.
|
||||
if(istype(get_turf(src), /turf/simulated/floor/asteroid))
|
||||
var/turf/simulated/floor/asteroid/T = get_turf(src)
|
||||
if(!T.dug)
|
||||
T.gets_dug()
|
||||
else if(istype(get_turf(src), /turf/simulated/floor))
|
||||
var/turf/simulated/floor/T = get_turf(src)
|
||||
if(istype(get_turf(src), /turf/simulated))
|
||||
var/turf/simulated/T = get_turf(src)
|
||||
T.ex_act(2.0)
|
||||
|
||||
//Dig out the tasty ores.
|
||||
|
||||
@@ -235,7 +235,7 @@
|
||||
var/obj/item/stack/flag/F = locate() in get_turf(src)
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T || !istype(T,/turf/simulated/floor/asteroid))
|
||||
if(!T || !istype(T,/turf/simulated/mineral))
|
||||
user << "The flag won't stand up in this terrain."
|
||||
return
|
||||
|
||||
|
||||
+341
-364
@@ -1,3 +1,5 @@
|
||||
var/list/mining_overlay_cache = list()
|
||||
|
||||
/**********************Mineral deposits**************************/
|
||||
/turf/unsimulated/mineral
|
||||
name = "impassable rock"
|
||||
@@ -5,7 +7,7 @@
|
||||
icon_state = "rock-dark"
|
||||
|
||||
/turf/simulated/mineral //wall piece
|
||||
name = "Rock"
|
||||
name = "rock"
|
||||
icon = 'icons/turf/walls.dmi'
|
||||
icon_state = "rock"
|
||||
oxygen = 0
|
||||
@@ -14,11 +16,13 @@
|
||||
density = 1
|
||||
blocks_air = 1
|
||||
temperature = T0C
|
||||
var/mined_turf = /turf/simulated/floor/asteroid
|
||||
|
||||
var/ore/mineral
|
||||
var/sand_dug
|
||||
var/mined_ore = 0
|
||||
var/last_act = 0
|
||||
var/emitter_blasts_taken = 0 // EMITTER MINING! Muhehe.
|
||||
var/overlay_detail
|
||||
|
||||
var/datum/geosample/geologic_data
|
||||
var/excavation_level = 0
|
||||
@@ -28,26 +32,121 @@
|
||||
var/excav_overlay = ""
|
||||
var/obj/item/weapon/last_find
|
||||
var/datum/artifact_find/artifact_find
|
||||
var/ignore_mapgen
|
||||
|
||||
has_resources = 1
|
||||
|
||||
/turf/simulated/mineral/New()
|
||||
spawn(0)
|
||||
MineralSpread()
|
||||
spawn(2)
|
||||
updateMineralOverlays(1)
|
||||
/turf/simulated/mineral/ignore_mapgen
|
||||
ignore_mapgen = 1
|
||||
|
||||
/turf/simulated/mineral/proc/updateMineralOverlays(var/update_neighbors)
|
||||
var/list/step_overlays = list("s" = NORTH, "n" = SOUTH, "w" = EAST, "e" = WEST)
|
||||
for(var/direction in step_overlays)
|
||||
var/turf/turf_to_check = get_step(src,step_overlays[direction])
|
||||
if(update_neighbors && istype(turf_to_check,/turf/simulated/floor/asteroid))
|
||||
var/turf/simulated/floor/asteroid/T = turf_to_check
|
||||
T.updateMineralOverlays()
|
||||
else if(istype(turf_to_check,/turf/space) || istype(turf_to_check,/turf/simulated/floor))
|
||||
turf_to_check.overlays += image('icons/turf/walls.dmi', "rock_side_[direction]")
|
||||
/turf/simulated/mineral/floor
|
||||
name = "sand"
|
||||
icon = 'icons/turf/flooring/asteroid.dmi'
|
||||
icon_state = "asteroid"
|
||||
density = 0
|
||||
opacity = 0
|
||||
blocks_air = 0
|
||||
|
||||
/turf/simulated/mineral/floor/ignore_mapgen
|
||||
ignore_mapgen = 1
|
||||
|
||||
/turf/simulated/mineral/proc/make_floor()
|
||||
if(!density && !opacity)
|
||||
return
|
||||
density = 0
|
||||
opacity = 0
|
||||
blocks_air = 0
|
||||
update_general()
|
||||
|
||||
/turf/simulated/mineral/proc/make_wall()
|
||||
if(density && opacity)
|
||||
return
|
||||
density = 1
|
||||
opacity = 1
|
||||
blocks_air = 1
|
||||
update_general()
|
||||
|
||||
/turf/simulated/mineral/proc/update_general()
|
||||
update_icon(1)
|
||||
if(ticker && ticker.current_state == GAME_STATE_PLAYING)
|
||||
reconsider_lights()
|
||||
if(air_master)
|
||||
air_master.mark_for_update(src)
|
||||
|
||||
/turf/simulated/mineral/Entered(atom/movable/M as mob|obj)
|
||||
. = ..()
|
||||
if(istype(M,/mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/R = M
|
||||
if(R.module)
|
||||
for(var/obj/item/weapon/storage/bag/ore/O in list(R.module_state_1, R.module_state_2, R.module_state_3))
|
||||
attackby(O, R)
|
||||
return
|
||||
|
||||
/turf/simulated/mineral/initialize()
|
||||
if(prob(20))
|
||||
overlay_detail = "asteroid[rand(0,9)]"
|
||||
if(density)
|
||||
spawn(0)
|
||||
MineralSpread()
|
||||
update_icon(1)
|
||||
|
||||
/turf/simulated/mineral/update_icon(var/update_neighbors)
|
||||
|
||||
overlays.Cut()
|
||||
|
||||
if(density)
|
||||
if(mineral)
|
||||
name = "[mineral.display_name] deposit"
|
||||
else
|
||||
name = "rock"
|
||||
|
||||
icon = 'icons/turf/walls.dmi'
|
||||
icon_state = "rock"
|
||||
|
||||
for(var/direction in cardinal)
|
||||
var/turf/T = get_step(src,direction)
|
||||
if(istype(T) && !T.density)
|
||||
var/place_dir = turn(direction, 180)
|
||||
if(!mining_overlay_cache["rock_side_[place_dir]"])
|
||||
mining_overlay_cache["rock_side_[place_dir]"] = image('icons/turf/walls.dmi', "rock_side", dir = place_dir)
|
||||
T.overlays += mining_overlay_cache["rock_side_[place_dir]"]
|
||||
else
|
||||
|
||||
name = "sand"
|
||||
icon = 'icons/turf/flooring/asteroid.dmi'
|
||||
icon_state = "asteroid"
|
||||
|
||||
if(sand_dug)
|
||||
if(!mining_overlay_cache["dug_overlay"])
|
||||
mining_overlay_cache["dug_overlay"] = image('icons/turf/flooring/asteroid.dmi', "dug_overlay")
|
||||
overlays += mining_overlay_cache["dug_overlay"]
|
||||
|
||||
for(var/direction in cardinal)
|
||||
if(istype(get_step(src, direction), /turf/space))
|
||||
if(!mining_overlay_cache["asteroid_edge_[direction]"])
|
||||
mining_overlay_cache["asteroid_edge_[direction]"] = image('icons/turf/flooring/asteroid.dmi', "asteroid_edges", dir = direction)
|
||||
overlays += mining_overlay_cache["asteroid_edge_[direction]"]
|
||||
else
|
||||
var/turf/simulated/mineral/M = get_step(src, direction)
|
||||
if(istype(M) && M.density)
|
||||
if(!mining_overlay_cache["rock_side_[direction]"])
|
||||
mining_overlay_cache["rock_side_[direction]"] = image('icons/turf/walls.dmi', "rock_side", dir = direction)
|
||||
overlays += mining_overlay_cache["rock_side_[direction]"]
|
||||
|
||||
if(overlay_detail)
|
||||
|
||||
if(!mining_overlay_cache["decal_[overlay_detail]"])
|
||||
mining_overlay_cache["decal_[overlay_detail]"] = image(icon = 'icons/turf/flooring/decals.dmi', icon_state = overlay_detail)
|
||||
overlays += mining_overlay_cache["decal_[overlay_detail]"]
|
||||
|
||||
if(update_neighbors)
|
||||
for(var/direction in alldirs)
|
||||
if(istype(get_step(src, direction), /turf/simulated/mineral))
|
||||
var/turf/simulated/mineral/M = get_step(src, direction)
|
||||
M.update_icon()
|
||||
|
||||
/turf/simulated/mineral/ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(2.0)
|
||||
if (prob(70))
|
||||
@@ -62,13 +161,17 @@
|
||||
// Emitter blasts
|
||||
if(istype(Proj, /obj/item/projectile/beam/emitter))
|
||||
emitter_blasts_taken++
|
||||
|
||||
if(emitter_blasts_taken > 2) // 3 blasts per tile
|
||||
mined_ore = 1
|
||||
GetDrilled()
|
||||
|
||||
/turf/simulated/mineral/Bumped(AM)
|
||||
|
||||
. = ..()
|
||||
|
||||
if(!density)
|
||||
return .
|
||||
|
||||
if(istype(AM,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = AM
|
||||
if((istype(H.l_hand,/obj/item/weapon/pickaxe)) && (!H.hand))
|
||||
@@ -91,7 +194,7 @@
|
||||
for(var/trydir in cardinal)
|
||||
if(prob(mineral.spread_chance))
|
||||
var/turf/simulated/mineral/target_turf = get_step(src, trydir)
|
||||
if(istype(target_turf) && !target_turf.mineral)
|
||||
if(istype(target_turf) && target_turf.density && !target_turf.mineral)
|
||||
target_turf.mineral = mineral
|
||||
target_turf.UpdateMineral()
|
||||
target_turf.MineralSpread()
|
||||
@@ -99,143 +202,213 @@
|
||||
|
||||
/turf/simulated/mineral/proc/UpdateMineral()
|
||||
clear_ore_effects()
|
||||
if(!mineral)
|
||||
name = "\improper Rock"
|
||||
icon_state = "rock"
|
||||
return
|
||||
name = "\improper [mineral.display_name] deposit"
|
||||
new /obj/effect/mineral(src, mineral)
|
||||
if(mineral)
|
||||
new /obj/effect/mineral(src, mineral)
|
||||
update_icon()
|
||||
|
||||
//Not even going to touch this pile of spaghetti
|
||||
/turf/simulated/mineral/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
|
||||
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
usr << "<span class='warning'>You don't have the dexterity to do this!</span>"
|
||||
return
|
||||
|
||||
if (istype(W, /obj/item/device/core_sampler))
|
||||
geologic_data.UpdateNearbyArtifactInfo(src)
|
||||
var/obj/item/device/core_sampler/C = W
|
||||
C.sample_item(src, user)
|
||||
return
|
||||
if(!density)
|
||||
|
||||
if (istype(W, /obj/item/device/depth_scanner))
|
||||
var/obj/item/device/depth_scanner/C = W
|
||||
C.scan_atom(user, src)
|
||||
return
|
||||
var/list/usable_tools = list(
|
||||
/obj/item/weapon/shovel,
|
||||
/obj/item/weapon/pickaxe/diamonddrill,
|
||||
/obj/item/weapon/pickaxe/drill,
|
||||
/obj/item/weapon/pickaxe/borgdrill
|
||||
)
|
||||
|
||||
if (istype(W, /obj/item/device/measuring_tape))
|
||||
var/obj/item/device/measuring_tape/P = W
|
||||
user.visible_message("\blue[user] extends [P] towards [src].","\blue You extend [P] towards [src].")
|
||||
if(do_after(user,25))
|
||||
user << "\blue \icon[P] [src] has been excavated to a depth of [2*excavation_level]cm."
|
||||
return
|
||||
var/valid_tool
|
||||
for(var/valid_type in usable_tools)
|
||||
if(istype(W,valid_type))
|
||||
valid_tool = 1
|
||||
break
|
||||
|
||||
if (istype(W, /obj/item/weapon/pickaxe))
|
||||
var/turf/T = user.loc
|
||||
if (!( istype(T, /turf) ))
|
||||
return
|
||||
|
||||
var/obj/item/weapon/pickaxe/P = W
|
||||
if(last_act + P.digspeed > world.time)//prevents message spam
|
||||
return
|
||||
last_act = world.time
|
||||
|
||||
playsound(user, P.drill_sound, 20, 1)
|
||||
|
||||
//handle any archaeological finds we might uncover
|
||||
var/fail_message
|
||||
if(finds && finds.len)
|
||||
var/datum/find/F = finds[1]
|
||||
if(excavation_level + P.excavation_amount > F.excavation_required)
|
||||
//Chance to destroy / extract any finds here
|
||||
fail_message = ". <b>[pick("There is a crunching noise","[W] collides with some different rock","Part of the rock face crumbles away","Something breaks under [W]")]</b>"
|
||||
|
||||
user << "\red You start [P.drill_verb][fail_message ? fail_message : ""]."
|
||||
|
||||
if(fail_message && prob(90))
|
||||
if(prob(25))
|
||||
excavate_find(5, finds[1])
|
||||
else if(prob(50))
|
||||
finds.Remove(finds[1])
|
||||
if(prob(50))
|
||||
artifact_debris()
|
||||
|
||||
if(do_after(user,P.digspeed))
|
||||
user << "\blue You finish [P.drill_verb] the rock."
|
||||
|
||||
if(finds && finds.len)
|
||||
var/datum/find/F = finds[1]
|
||||
if(round(excavation_level + P.excavation_amount) == F.excavation_required)
|
||||
//Chance to extract any items here perfectly, otherwise just pull them out along with the rock surrounding them
|
||||
if(excavation_level + P.excavation_amount > F.excavation_required)
|
||||
//if you can get slightly over, perfect extraction
|
||||
excavate_find(100, F)
|
||||
else
|
||||
excavate_find(80, F)
|
||||
|
||||
else if(excavation_level + P.excavation_amount > F.excavation_required - F.clearance_range)
|
||||
//just pull the surrounding rock out
|
||||
excavate_find(0, F)
|
||||
|
||||
if( excavation_level + P.excavation_amount >= 100 )
|
||||
//if players have been excavating this turf, leave some rocky debris behind
|
||||
var/obj/structure/boulder/B
|
||||
if(artifact_find)
|
||||
if( excavation_level > 0 || prob(15) )
|
||||
//boulder with an artifact inside
|
||||
B = new(src)
|
||||
if(artifact_find)
|
||||
B.artifact_find = artifact_find
|
||||
else
|
||||
artifact_debris(1)
|
||||
else if(prob(15))
|
||||
//empty boulder
|
||||
B = new(src)
|
||||
|
||||
if(B)
|
||||
GetDrilled(0)
|
||||
else
|
||||
GetDrilled(1)
|
||||
if(valid_tool)
|
||||
if (sand_dug)
|
||||
user << "<span class='warning'>This area has already been dug.</span>"
|
||||
return
|
||||
|
||||
excavation_level += P.excavation_amount
|
||||
var/turf/T = user.loc
|
||||
if (!(istype(T)))
|
||||
return
|
||||
|
||||
//archaeo overlays
|
||||
if(!archaeo_overlay && finds && finds.len)
|
||||
var/datum/find/F = finds[1]
|
||||
if(F.excavation_required <= excavation_level + F.view_range)
|
||||
archaeo_overlay = "overlay_archaeo[rand(1,3)]"
|
||||
overlays += archaeo_overlay
|
||||
user << "<span class='notice'>You start digging.</span>"
|
||||
playsound(user.loc, 'sound/effects/rustle1.ogg', 50, 1)
|
||||
|
||||
//there's got to be a better way to do this
|
||||
var/update_excav_overlay = 0
|
||||
if(excavation_level >= 75)
|
||||
if(excavation_level - P.excavation_amount < 75)
|
||||
update_excav_overlay = 1
|
||||
else if(excavation_level >= 50)
|
||||
if(excavation_level - P.excavation_amount < 50)
|
||||
update_excav_overlay = 1
|
||||
else if(excavation_level >= 25)
|
||||
if(excavation_level - P.excavation_amount < 25)
|
||||
update_excav_overlay = 1
|
||||
if(!do_after(user,40)) return
|
||||
|
||||
//update overlays displaying excavation level
|
||||
if( !(excav_overlay && excavation_level > 0) || update_excav_overlay )
|
||||
var/excav_quadrant = round(excavation_level / 25) + 1
|
||||
excav_overlay = "overlay_excv[excav_quadrant]_[rand(1,3)]"
|
||||
overlays += excav_overlay
|
||||
user << "<span class='notice'>You dug a hole.</span>"
|
||||
GetDrilled()
|
||||
|
||||
else if(istype(W,/obj/item/weapon/storage/bag/ore))
|
||||
var/obj/item/weapon/storage/bag/ore/S = W
|
||||
if(S.collection_mode)
|
||||
for(var/obj/item/weapon/ore/O in contents)
|
||||
O.attackby(W,user)
|
||||
return
|
||||
|
||||
else if(istype(W,/obj/item/weapon/storage/bag/fossils))
|
||||
var/obj/item/weapon/storage/bag/fossils/S = W
|
||||
if(S.collection_mode)
|
||||
for(var/obj/item/weapon/fossil/F in contents)
|
||||
F.attackby(W,user)
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/stack/rods))
|
||||
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
|
||||
if(L)
|
||||
return
|
||||
var/obj/item/stack/rods/R = W
|
||||
if (R.use(1))
|
||||
user << "<span class='notice'>Constructing support lattice ...</span>"
|
||||
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
|
||||
new /obj/structure/lattice(get_turf(src))
|
||||
|
||||
else if(istype(W, /obj/item/stack/tile/floor))
|
||||
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
|
||||
if(L)
|
||||
var/obj/item/stack/tile/floor/S = W
|
||||
if (S.get_amount() < 1)
|
||||
return
|
||||
qdel(L)
|
||||
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
|
||||
ChangeTurf(/turf/simulated/floor)
|
||||
S.use(1)
|
||||
return
|
||||
else
|
||||
user << "<span class='warning'>The plating is going to need some support.</span>"
|
||||
return
|
||||
|
||||
//drop some rocks
|
||||
next_rock += P.excavation_amount * 10
|
||||
while(next_rock > 100)
|
||||
next_rock -= 100
|
||||
var/obj/item/weapon/ore/O = new(src)
|
||||
geologic_data.UpdateNearbyArtifactInfo(src)
|
||||
O.geologic_data = geologic_data
|
||||
|
||||
else
|
||||
return attack_hand(user)
|
||||
if (istype(W, /obj/item/device/core_sampler))
|
||||
geologic_data.UpdateNearbyArtifactInfo(src)
|
||||
var/obj/item/device/core_sampler/C = W
|
||||
C.sample_item(src, user)
|
||||
return
|
||||
|
||||
if (istype(W, /obj/item/device/depth_scanner))
|
||||
var/obj/item/device/depth_scanner/C = W
|
||||
C.scan_atom(user, src)
|
||||
return
|
||||
|
||||
if (istype(W, /obj/item/device/measuring_tape))
|
||||
var/obj/item/device/measuring_tape/P = W
|
||||
user.visible_message("<span class='notice'>\The [user] extends \a [P] towards \the [src].</span>","<span class='notice'>You extend \the [P] towards \the [src].</span>")
|
||||
if(do_after(user,25))
|
||||
user << "<span class='notice'>\icon[P] [src] has been excavated to a depth of [2*excavation_level]cm.</span>"
|
||||
return
|
||||
|
||||
if (istype(W, /obj/item/weapon/pickaxe))
|
||||
var/turf/T = user.loc
|
||||
if (!( istype(T, /turf) ))
|
||||
return
|
||||
|
||||
var/obj/item/weapon/pickaxe/P = W
|
||||
if(last_act + P.digspeed > world.time)//prevents message spam
|
||||
return
|
||||
last_act = world.time
|
||||
|
||||
playsound(user, P.drill_sound, 20, 1)
|
||||
|
||||
//handle any archaeological finds we might uncover
|
||||
var/fail_message
|
||||
if(finds && finds.len)
|
||||
var/datum/find/F = finds[1]
|
||||
if(excavation_level + P.excavation_amount > F.excavation_required)
|
||||
//Chance to destroy / extract any finds here
|
||||
fail_message = ". <b>[pick("There is a crunching noise","[W] collides with some different rock","Part of the rock face crumbles away","Something breaks under [W]")]</b>"
|
||||
|
||||
user << "<span class='notice'>You start [P.drill_verb][fail_message ? fail_message : ""].</span>"
|
||||
|
||||
if(fail_message && prob(90))
|
||||
if(prob(25))
|
||||
excavate_find(5, finds[1])
|
||||
else if(prob(50))
|
||||
finds.Remove(finds[1])
|
||||
if(prob(50))
|
||||
artifact_debris()
|
||||
|
||||
if(do_after(user,P.digspeed))
|
||||
user << "<span class='notice'>You finish [P.drill_verb] \the [src].</span>"
|
||||
|
||||
if(finds && finds.len)
|
||||
var/datum/find/F = finds[1]
|
||||
if(round(excavation_level + P.excavation_amount) == F.excavation_required)
|
||||
//Chance to extract any items here perfectly, otherwise just pull them out along with the rock surrounding them
|
||||
if(excavation_level + P.excavation_amount > F.excavation_required)
|
||||
//if you can get slightly over, perfect extraction
|
||||
excavate_find(100, F)
|
||||
else
|
||||
excavate_find(80, F)
|
||||
|
||||
else if(excavation_level + P.excavation_amount > F.excavation_required - F.clearance_range)
|
||||
//just pull the surrounding rock out
|
||||
excavate_find(0, F)
|
||||
|
||||
if( excavation_level + P.excavation_amount >= 100 )
|
||||
//if players have been excavating this turf, leave some rocky debris behind
|
||||
var/obj/structure/boulder/B
|
||||
if(artifact_find)
|
||||
if( excavation_level > 0 || prob(15) )
|
||||
//boulder with an artifact inside
|
||||
B = new(src)
|
||||
if(artifact_find)
|
||||
B.artifact_find = artifact_find
|
||||
else
|
||||
artifact_debris(1)
|
||||
else if(prob(15))
|
||||
//empty boulder
|
||||
B = new(src)
|
||||
|
||||
if(B)
|
||||
GetDrilled(0)
|
||||
else
|
||||
GetDrilled(1)
|
||||
return
|
||||
|
||||
excavation_level += P.excavation_amount
|
||||
|
||||
//archaeo overlays
|
||||
if(!archaeo_overlay && finds && finds.len)
|
||||
var/datum/find/F = finds[1]
|
||||
if(F.excavation_required <= excavation_level + F.view_range)
|
||||
archaeo_overlay = "overlay_archaeo[rand(1,3)]"
|
||||
overlays += archaeo_overlay
|
||||
|
||||
//there's got to be a better way to do this
|
||||
var/update_excav_overlay = 0
|
||||
if(excavation_level >= 75)
|
||||
if(excavation_level - P.excavation_amount < 75)
|
||||
update_excav_overlay = 1
|
||||
else if(excavation_level >= 50)
|
||||
if(excavation_level - P.excavation_amount < 50)
|
||||
update_excav_overlay = 1
|
||||
else if(excavation_level >= 25)
|
||||
if(excavation_level - P.excavation_amount < 25)
|
||||
update_excav_overlay = 1
|
||||
|
||||
//update overlays displaying excavation level
|
||||
if( !(excav_overlay && excavation_level > 0) || update_excav_overlay )
|
||||
var/excav_quadrant = round(excavation_level / 25) + 1
|
||||
excav_overlay = "overlay_excv[excav_quadrant]_[rand(1,3)]"
|
||||
overlays += excav_overlay
|
||||
|
||||
//drop some rocks
|
||||
next_rock += P.excavation_amount * 10
|
||||
while(next_rock > 100)
|
||||
next_rock -= 100
|
||||
var/obj/item/weapon/ore/O = new(src)
|
||||
geologic_data.UpdateNearbyArtifactInfo(src)
|
||||
O.geologic_data = geologic_data
|
||||
return
|
||||
|
||||
return attack_hand(user)
|
||||
|
||||
/turf/simulated/mineral/proc/clear_ore_effects()
|
||||
for(var/obj/effect/mineral/M in contents)
|
||||
@@ -244,7 +417,6 @@
|
||||
/turf/simulated/mineral/proc/DropMineral()
|
||||
if(!mineral)
|
||||
return
|
||||
|
||||
clear_ore_effects()
|
||||
var/obj/item/weapon/ore/O = new mineral.ore (src)
|
||||
if(istype(O))
|
||||
@@ -253,7 +425,15 @@
|
||||
return O
|
||||
|
||||
/turf/simulated/mineral/proc/GetDrilled(var/artifact_fail = 0)
|
||||
//var/destroyed = 0 //used for breaking strange rocks
|
||||
|
||||
if(!density)
|
||||
if(!sand_dug)
|
||||
sand_dug = 1
|
||||
for(var/i=0;i<(rand(3)+2);i++)
|
||||
new/obj/item/weapon/ore/glass(src)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if (mineral && mineral.result_amount)
|
||||
|
||||
//if the turf has already been excavated, some of it's ore has been removed
|
||||
@@ -267,7 +447,7 @@
|
||||
if(prob(50))
|
||||
pain = 1
|
||||
for(var/mob/living/M in range(src, 200))
|
||||
M << "<font color='red'><b>[pick("A high pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fading away!</b></font>"
|
||||
M << "<span class='danger'>[pick("A high-pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fading away!</span>"
|
||||
if(pain)
|
||||
flick("pain",M.pain)
|
||||
if(prob(50))
|
||||
@@ -278,25 +458,8 @@
|
||||
M.Stun(5)
|
||||
M.apply_effect(25, IRRADIATE)
|
||||
|
||||
|
||||
var/list/step_overlays = list("n" = NORTH, "s" = SOUTH, "e" = EAST, "w" = WEST)
|
||||
|
||||
//Add some rubble, you did just clear out a big chunk of rock.
|
||||
|
||||
var/turf/simulated/floor/asteroid/N = ChangeTurf(mined_turf)
|
||||
|
||||
// Kill and update the space overlays around us.
|
||||
for(var/direction in step_overlays)
|
||||
var/turf/space/T = get_step(src, step_overlays[direction])
|
||||
if(istype(T))
|
||||
T.overlays.Cut()
|
||||
for(var/next_direction in step_overlays)
|
||||
if(istype(get_step(T, step_overlays[next_direction]),/turf/simulated/mineral))
|
||||
T.overlays += image('icons/turf/walls.dmi', "rock_side_[next_direction]")
|
||||
|
||||
if(istype(N))
|
||||
N.overlay_detail = "asteroid[rand(0,9)]"
|
||||
N.updateMineralOverlays(1)
|
||||
make_floor()
|
||||
update_icon(1)
|
||||
|
||||
/turf/simulated/mineral/proc/excavate_find(var/prob_clean = 0, var/datum/find/F)
|
||||
//with skill and luck, players can cleanly extract finds
|
||||
@@ -311,7 +474,7 @@
|
||||
|
||||
//some find types delete the /obj/item/weapon/archaeological_find and replace it with something else, this handles when that happens
|
||||
//yuck
|
||||
var/display_name = "something"
|
||||
var/display_name = "Something"
|
||||
if(!X)
|
||||
X = last_find
|
||||
if(X)
|
||||
@@ -322,12 +485,11 @@
|
||||
var/obj/effect/suspension_field/S = locate() in src
|
||||
if(!S || S.field_type != get_responsive_reagent(F.find_type))
|
||||
if(X)
|
||||
visible_message("\red<b>[pick("[display_name] crumbles away into dust","[display_name] breaks apart")].</b>")
|
||||
visible_message("<span class='danger'>\The [pick("[display_name] crumbles away into dust","[display_name] breaks apart")].</span>")
|
||||
qdel(X)
|
||||
|
||||
finds.Remove(F)
|
||||
|
||||
|
||||
/turf/simulated/mineral/proc/artifact_debris(var/severity = 0)
|
||||
//cael's patented random limited drop componentized loot system!
|
||||
//sky's patented not-fucking-retarded overhaul!
|
||||
@@ -336,219 +498,34 @@
|
||||
for(var/j in 1 to rand(1, 3 + max(min(severity, 1), 0) * 2))
|
||||
switch(rand(1,7))
|
||||
if(1)
|
||||
var/obj/item/stack/rods/R = new(src)
|
||||
R.amount = rand(5,25)
|
||||
|
||||
new /obj/item/stack/rods(src, rand(5,25))
|
||||
if(2)
|
||||
var/obj/item/stack/material/plasteel/R = new(src)
|
||||
R.amount = rand(5,25)
|
||||
|
||||
new /obj/item/stack/material/plasteel(src, rand(5,25))
|
||||
if(3)
|
||||
var/obj/item/stack/material/steel/R = new(src)
|
||||
R.amount = rand(5,25)
|
||||
|
||||
new /obj/item/stack/material/steel(src, rand(5,25))
|
||||
if(4)
|
||||
var/obj/item/stack/material/plasteel/R = new(src)
|
||||
R.amount = rand(5,25)
|
||||
|
||||
new /obj/item/stack/material/plasteel(src, rand(5,25))
|
||||
if(5)
|
||||
var/quantity = rand(1,3)
|
||||
for(var/i=0, i<quantity, i++)
|
||||
for(var/i=1 to rand(1,3))
|
||||
new /obj/item/weapon/material/shard(src)
|
||||
|
||||
if(6)
|
||||
var/quantity = rand(1,3)
|
||||
for(var/i=0, i<quantity, i++)
|
||||
for(var/i=1 to rand(1,3))
|
||||
new /obj/item/weapon/material/shard/phoron(src)
|
||||
|
||||
if(7)
|
||||
var/obj/item/stack/material/uranium/R = new(src)
|
||||
R.amount = rand(5,25)
|
||||
new /obj/item/stack/material/uranium(src, rand(5,25))
|
||||
|
||||
/turf/simulated/mineral/random
|
||||
name = "Mineral deposit"
|
||||
var/mineralSpawnChanceList = list("Uranium" = 5, "Platinum" = 5, "Iron" = 35, "Coal" = 35, "Diamond" = 1, "Gold" = 5, "Silver" = 5, "Phoron" = 10)
|
||||
var/mineralChance = 100 //10 //means 10% chance of this plot changing to a mineral deposit
|
||||
|
||||
/turf/simulated/mineral/random/New()
|
||||
if (prob(mineralChance) && !mineral)
|
||||
var/mineral_name = pickweight(mineralSpawnChanceList) //temp mineral name
|
||||
mineral_name = lowertext(mineral_name)
|
||||
if (mineral_name && (mineral_name in ore_data))
|
||||
mineral = ore_data[mineral_name]
|
||||
UpdateMineral()
|
||||
|
||||
. = ..()
|
||||
|
||||
/turf/simulated/mineral/random/high_chance
|
||||
mineralChance = 100 //25
|
||||
mineralSpawnChanceList = list("Uranium" = 10, "Platinum" = 10, "Iron" = 20, "Coal" = 20, "Diamond" = 2, "Gold" = 10, "Silver" = 10, "Phoron" = 20)
|
||||
|
||||
|
||||
/**********************Asteroid**************************/
|
||||
|
||||
// Setting icon/icon_state initially will use these values when the turf is built on/replaced.
|
||||
// This means you can put grass on the asteroid etc.
|
||||
/turf/simulated/floor/asteroid
|
||||
name = "sand"
|
||||
icon = 'icons/turf/flooring/asteroid.dmi'
|
||||
icon_state = "asteroid"
|
||||
base_name = "sand"
|
||||
base_desc = "Gritty and unpleasant."
|
||||
base_icon = 'icons/turf/flooring/asteroid.dmi'
|
||||
base_icon_state = "asteroid"
|
||||
|
||||
initial_flooring = null
|
||||
oxygen = 0
|
||||
nitrogen = 0
|
||||
temperature = TCMB
|
||||
var/dug = 0 //0 = has not yet been dug, 1 = has already been dug
|
||||
var/overlay_detail
|
||||
has_resources = 1
|
||||
|
||||
/turf/simulated/floor/asteroid/New()
|
||||
|
||||
if(prob(20))
|
||||
overlay_detail = "asteroid[rand(0,9)]"
|
||||
|
||||
/turf/simulated/floor/asteroid/ex_act(severity)
|
||||
switch(severity)
|
||||
if(3.0)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(70))
|
||||
gets_dug()
|
||||
if(1.0)
|
||||
gets_dug()
|
||||
return
|
||||
|
||||
/turf/simulated/floor/asteroid/is_plating()
|
||||
return 0
|
||||
|
||||
/turf/simulated/floor/asteroid/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
|
||||
if(!W || !user)
|
||||
return 0
|
||||
|
||||
var/list/usable_tools = list(
|
||||
/obj/item/weapon/shovel,
|
||||
/obj/item/weapon/pickaxe/diamonddrill,
|
||||
/obj/item/weapon/pickaxe/drill,
|
||||
/obj/item/weapon/pickaxe/borgdrill
|
||||
)
|
||||
|
||||
var/valid_tool
|
||||
for(var/valid_type in usable_tools)
|
||||
if(istype(W,valid_type))
|
||||
valid_tool = 1
|
||||
break
|
||||
|
||||
if(valid_tool)
|
||||
if (dug)
|
||||
user << "\red This area has already been dug"
|
||||
return
|
||||
|
||||
var/turf/T = user.loc
|
||||
if (!(istype(T)))
|
||||
return
|
||||
|
||||
user << "\red You start digging."
|
||||
playsound(user.loc, 'sound/effects/rustle1.ogg', 50, 1)
|
||||
|
||||
if(!do_after(user,40)) return
|
||||
|
||||
user << "\blue You dug a hole."
|
||||
gets_dug()
|
||||
|
||||
else if(istype(W,/obj/item/weapon/storage/bag/ore))
|
||||
var/obj/item/weapon/storage/bag/ore/S = W
|
||||
if(S.collection_mode)
|
||||
for(var/obj/item/weapon/ore/O in contents)
|
||||
O.attackby(W,user)
|
||||
return
|
||||
else if(istype(W,/obj/item/weapon/storage/bag/fossils))
|
||||
var/obj/item/weapon/storage/bag/fossils/S = W
|
||||
if(S.collection_mode)
|
||||
for(var/obj/item/weapon/fossil/F in contents)
|
||||
F.attackby(W,user)
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/stack/rods))
|
||||
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
|
||||
if(L)
|
||||
return
|
||||
var/obj/item/stack/rods/R = W
|
||||
if (R.use(1))
|
||||
user << "<span class='notice'>Constructing support lattice ...</span>"
|
||||
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
|
||||
new /obj/structure/lattice(get_turf(src))
|
||||
/turf/simulated/mineral/proc/make_ore(var/rare_ore)
|
||||
if(mineral)
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/stack/tile/floor))
|
||||
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
|
||||
if(L)
|
||||
var/obj/item/stack/tile/floor/S = W
|
||||
if (S.get_amount() < 1)
|
||||
return
|
||||
qdel(L)
|
||||
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
|
||||
ChangeTurf(/turf/simulated/floor/airless)
|
||||
S.use(1)
|
||||
return
|
||||
else
|
||||
user << "<span class='warning'>The plating is going to need some support.</span>"
|
||||
return
|
||||
var/mineral_name
|
||||
if(rare_ore)
|
||||
mineral_name = pickweight(list("uranium" = 10, "platinum" = 10, "iron" = 20, "coal" = 20, "diamond" = 2, "gold" = 10, "silver" = 10, "phoron" = 20))
|
||||
|
||||
else
|
||||
..(W,user)
|
||||
return
|
||||
mineral_name = pickweight(list("uranium" = 5, "platinum" = 5, "iron" = 35, "coal" = 35, "diamond" = 1, "gold" = 5, "silver" = 5, "phoron" = 10))
|
||||
|
||||
/turf/simulated/floor/asteroid/proc/gets_dug()
|
||||
|
||||
if(dug)
|
||||
return
|
||||
|
||||
for(var/i=0;i<(rand(3)+2);i++)
|
||||
new/obj/item/weapon/ore/glass(src)
|
||||
|
||||
dug = 1
|
||||
icon_state = "asteroid_dug"
|
||||
return
|
||||
|
||||
/turf/simulated/floor/asteroid/proc/updateMineralOverlays(var/update_neighbors)
|
||||
|
||||
overlays.Cut()
|
||||
|
||||
var/list/step_overlays = list("n" = NORTH, "s" = SOUTH, "e" = EAST, "w" = WEST)
|
||||
for(var/direction in step_overlays)
|
||||
|
||||
if(istype(get_step(src, step_overlays[direction]), /turf/space))
|
||||
overlays += image('icons/turf/floors.dmi', "asteroid_edge_[direction]")
|
||||
|
||||
if(istype(get_step(src, step_overlays[direction]), /turf/simulated/mineral))
|
||||
overlays += image('icons/turf/walls.dmi', "rock_side_[direction]")
|
||||
|
||||
//todo cache
|
||||
if(overlay_detail) overlays |= image(icon = 'icons/turf/flooring/decals.dmi', icon_state = overlay_detail)
|
||||
|
||||
if(update_neighbors)
|
||||
var/list/all_step_directions = list(NORTH,NORTHEAST,EAST,SOUTHEAST,SOUTH,SOUTHWEST,WEST,NORTHWEST)
|
||||
for(var/direction in all_step_directions)
|
||||
var/turf/simulated/floor/asteroid/A
|
||||
if(istype(get_step(src, direction), /turf/simulated/floor/asteroid))
|
||||
A = get_step(src, direction)
|
||||
A.updateMineralOverlays()
|
||||
|
||||
/turf/simulated/floor/asteroid/Entered(atom/movable/M as mob|obj)
|
||||
..()
|
||||
if(istype(M,/mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/R = M
|
||||
if(R.module)
|
||||
if(istype(R.module_state_1,/obj/item/weapon/storage/bag/ore))
|
||||
attackby(R.module_state_1,R)
|
||||
else if(istype(R.module_state_2,/obj/item/weapon/storage/bag/ore))
|
||||
attackby(R.module_state_2,R)
|
||||
else if(istype(R.module_state_3,/obj/item/weapon/storage/bag/ore))
|
||||
attackby(R.module_state_3,R)
|
||||
else
|
||||
return
|
||||
if(mineral_name && (mineral_name in ore_data))
|
||||
mineral = ore_data[mineral_name]
|
||||
UpdateMineral()
|
||||
update_icon()
|
||||
|
||||
@@ -8,8 +8,7 @@ var/list/holder_mob_icon_cache = list()
|
||||
slot_flags = SLOT_HEAD | SLOT_HOLSTER
|
||||
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/species/vox/head.dmi',
|
||||
"Resomi" = 'icons/mob/species/resomi/head.dmi'
|
||||
"Vox" = 'icons/mob/species/vox/head.dmi'
|
||||
)
|
||||
|
||||
origin_tech = null
|
||||
|
||||
@@ -165,6 +165,7 @@ var/list/slot_equipment_priority = list( \
|
||||
// Removes an item from inventory and places it in the target atom.
|
||||
// If canremove or other conditions need to be checked then use unEquip instead.
|
||||
/mob/proc/drop_from_inventory(var/obj/item/W, var/atom/Target = null)
|
||||
|
||||
if(W)
|
||||
if(!Target)
|
||||
Target = loc
|
||||
|
||||
@@ -114,25 +114,6 @@
|
||||
new_name = pick(ai_names)
|
||||
return new_name
|
||||
|
||||
/datum/language/resomi
|
||||
name = "Resomi"
|
||||
desc = "A trilling language spoken by the diminutive Resomi."
|
||||
speech_verb = "chirps"
|
||||
ask_verb = "chirrups"
|
||||
exclaim_verb = "trills"
|
||||
colour = "alien"
|
||||
key = "v"
|
||||
flags = WHITELISTED
|
||||
space_chance = 50
|
||||
syllables = list(
|
||||
"ca", "ra", "ma", "sa", "na", "ta", "la", "sha", "scha", "a", "a",
|
||||
"ce", "re", "me", "se", "ne", "te", "le", "she", "sche", "e", "e",
|
||||
"ci", "ri", "mi", "si", "ni", "ti", "li", "shi", "schi", "i", "i"
|
||||
)
|
||||
|
||||
/datum/language/resomi/get_random_name(gender)
|
||||
return ..(gender, 1, 4, 1.5)
|
||||
|
||||
//Syllable Lists
|
||||
/*
|
||||
This list really long, mainly because I can't make up my mind about which mandarin syllables should be removed,
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
|
||||
if(shock_stage >= 10) tally += 3
|
||||
|
||||
if(aiming && aiming.aiming_at) tally += 5 // Iron sights make you slower, it's a well-known fact.
|
||||
|
||||
if(FAT in src.mutations)
|
||||
tally += 1.5
|
||||
if (bodytemperature < 283.222)
|
||||
|
||||
@@ -375,7 +375,7 @@
|
||||
safe_pressure_min *= 1.25
|
||||
|
||||
var/safe_exhaled_max = 10
|
||||
var/safe_toxins_max = 0.005
|
||||
var/safe_toxins_max = 0.2
|
||||
var/SA_para_min = 1
|
||||
var/SA_sleep_min = 5
|
||||
var/inhaled_gas_used = 0
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/datum/species/resomi
|
||||
name = "Resomi"
|
||||
name_plural = "Resomii"
|
||||
blurb = "A race of feathered raptors who developed on a cold world, almost \
|
||||
outside of the Goldilocks zone. Extremely fragile, they developed hunting skills \
|
||||
that emphasized taking out their prey without themselves getting hit. They are an \
|
||||
advanced post-scarcity culture on good terms with Skrellian and Human interests."
|
||||
|
||||
num_alternate_languages = 2
|
||||
secondary_langs = list("Resomi")
|
||||
name_language = "Resomi"
|
||||
|
||||
blood_color = "#D514F7"
|
||||
flesh_color = "#5F7BB0"
|
||||
base_color = "#001144"
|
||||
tail = "resomitail"
|
||||
tail_hair = "feathers"
|
||||
|
||||
icobase = 'icons/mob/human_races/r_resomi.dmi'
|
||||
deform = 'icons/mob/human_races/r_resomi.dmi'
|
||||
damage_overlays = 'icons/mob/human_races/masks/dam_resomi.dmi'
|
||||
damage_mask = 'icons/mob/human_races/masks/dam_mask_resomi.dmi'
|
||||
blood_mask = 'icons/mob/human_races/masks/blood_resomi.dmi'
|
||||
|
||||
eyes = "eyes_resomi"
|
||||
slowdown = -1
|
||||
total_health = 50
|
||||
brute_mod = 1.35
|
||||
burn_mod = 1.35
|
||||
mob_size = MOB_SMALL
|
||||
holder_type = /obj/item/weapon/holder/human
|
||||
short_sighted = 1
|
||||
gluttonous = 1
|
||||
|
||||
spawn_flags = CAN_JOIN | IS_WHITELISTED
|
||||
appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_EYE_COLOR
|
||||
bump_flag = MONKEY
|
||||
swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL
|
||||
push_flags = MONKEY|SLIME|SIMPLE_ANIMAL|ALIEN
|
||||
|
||||
cold_level_1 = 180
|
||||
cold_level_2 = 130
|
||||
cold_level_3 = 70
|
||||
heat_level_1 = 320
|
||||
heat_level_2 = 370
|
||||
heat_level_3 = 600
|
||||
heat_discomfort_level = 292
|
||||
heat_discomfort_strings = list(
|
||||
"Your feathers prickle in the heat.",
|
||||
"You feel uncomfortably warm.",
|
||||
)
|
||||
cold_discomfort_level = 180
|
||||
|
||||
has_limbs = list(
|
||||
"chest" = list("path" = /obj/item/organ/external/chest),
|
||||
"groin" = list("path" = /obj/item/organ/external/groin),
|
||||
"head" = list("path" = /obj/item/organ/external/head),
|
||||
"l_arm" = list("path" = /obj/item/organ/external/arm),
|
||||
"r_arm" = list("path" = /obj/item/organ/external/arm/right),
|
||||
"l_leg" = list("path" = /obj/item/organ/external/leg),
|
||||
"r_leg" = list("path" = /obj/item/organ/external/leg/right),
|
||||
"l_hand" = list("path" = /obj/item/organ/external/hand/resomi),
|
||||
"r_hand" = list("path" = /obj/item/organ/external/hand/right/resomi),
|
||||
"l_foot" = list("path" = /obj/item/organ/external/foot/resomi),
|
||||
"r_foot" = list("path" = /obj/item/organ/external/foot/right/resomi)
|
||||
)
|
||||
|
||||
has_organ = list(
|
||||
"heart" = /obj/item/organ/heart,
|
||||
"lungs" = /obj/item/organ/lungs,
|
||||
"liver" = /obj/item/organ/liver,
|
||||
"kidneys" = /obj/item/organ/kidneys,
|
||||
"brain" = /obj/item/organ/brain,
|
||||
"eyes" = /obj/item/organ/eyes
|
||||
)
|
||||
|
||||
unarmed_types = list(
|
||||
/datum/unarmed_attack/bite/sharp,
|
||||
/datum/unarmed_attack/claws,
|
||||
/datum/unarmed_attack/stomp/weak
|
||||
)
|
||||
|
||||
var/shock_cap = 30
|
||||
var/hallucination_cap = 25
|
||||
|
||||
// I'm... so... ronrery, so ronery...
|
||||
/datum/species/resomi/handle_environment_special(var/mob/living/carbon/human/H)
|
||||
|
||||
// If they're dead or unconcious they're a bit beyond this kind of thing.
|
||||
if(H.stat)
|
||||
return
|
||||
|
||||
// No point processing if we're already stressing the hell out.
|
||||
if(H.hallucination >= hallucination_cap && H.shock_stage >= shock_cap)
|
||||
return
|
||||
|
||||
// Check for company.
|
||||
for(var/mob/living/M in viewers(H))
|
||||
if(M == H || M.stat == DEAD || M.invisibility > H.see_invisible)
|
||||
continue
|
||||
if(M.faction == "neutral" || M.faction == H.faction)
|
||||
return
|
||||
|
||||
// No company? Suffer :(
|
||||
if(H.shock_stage < shock_cap)
|
||||
H.shock_stage += 1
|
||||
if(H.shock_stage >= shock_cap && H.hallucination < hallucination_cap)
|
||||
H.hallucination += 2.5
|
||||
|
||||
/datum/species/resomi/get_vision_flags(var/mob/living/carbon/human/H)
|
||||
if(!(H.sdisabilities & DEAF) && !H.ear_deaf)
|
||||
return SEE_SELF|SEE_MOBS
|
||||
else
|
||||
return SEE_SELF
|
||||
@@ -429,17 +429,6 @@ var/global/list/damage_icon_parts = list()
|
||||
overlays_standing[MUTATIONS_LAYER] = null
|
||||
if(update_icons) update_icons()
|
||||
|
||||
//Call when target overlay should be added/removed
|
||||
/mob/living/carbon/human/update_targeted(var/update_icons=1)
|
||||
if (targeted_by && target_locked)
|
||||
overlays_standing[TARGETED_LAYER] = target_locked
|
||||
else if (!targeted_by && target_locked)
|
||||
qdel(target_locked)
|
||||
if (!targeted_by)
|
||||
overlays_standing[TARGETED_LAYER] = null
|
||||
if(update_icons) update_icons()
|
||||
|
||||
|
||||
/* --------------------------------------- */
|
||||
//For legacy support.
|
||||
/mob/living/carbon/human/regenerate_icons()
|
||||
@@ -502,6 +491,7 @@ var/global/list/damage_icon_parts = list()
|
||||
|
||||
//need to append _s to the icon state for legacy compatibility
|
||||
var/image/standing = image(icon = under_icon, icon_state = "[under_state]_s")
|
||||
standing.color = w_uniform.color
|
||||
|
||||
//apply blood overlay
|
||||
if(w_uniform.blood_DNA)
|
||||
@@ -562,6 +552,7 @@ var/global/list/damage_icon_parts = list()
|
||||
bloodsies.color = gloves.blood_color
|
||||
standing.overlays += bloodsies
|
||||
gloves.screen_loc = ui_gloves
|
||||
standing.color = gloves.color
|
||||
overlays_standing[GLOVES_LAYER] = standing
|
||||
else
|
||||
if(blood_DNA)
|
||||
@@ -637,6 +628,7 @@ var/global/list/damage_icon_parts = list()
|
||||
var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "shoeblood")
|
||||
bloodsies.color = shoes.blood_color
|
||||
standing.overlays += bloodsies
|
||||
standing.color = shoes.color
|
||||
overlays_standing[SHOES_LAYER] = standing
|
||||
else
|
||||
if(feet_blood_DNA)
|
||||
@@ -702,6 +694,7 @@ var/global/list/damage_icon_parts = list()
|
||||
if(hat.on && light_overlay_cache[cache_key])
|
||||
standing.overlays |= light_overlay_cache[cache_key]
|
||||
|
||||
standing.color = head.color
|
||||
overlays_standing[HEAD_LAYER] = standing
|
||||
|
||||
else
|
||||
@@ -736,6 +729,8 @@ var/global/list/damage_icon_parts = list()
|
||||
if(!i_state) i_state = i.icon_state
|
||||
standing.overlays += image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[i_state]")
|
||||
|
||||
standing.color = belt.color
|
||||
|
||||
overlays_standing[belt_layer] = standing
|
||||
else
|
||||
overlays_standing[BELT_LAYER] = null
|
||||
@@ -759,6 +754,7 @@ var/global/list/damage_icon_parts = list()
|
||||
t_icon = wear_suit.item_icons[slot_wear_suit_str]
|
||||
|
||||
standing = image("icon" = t_icon, "icon_state" = "[wear_suit.icon_state]")
|
||||
standing.color = wear_suit.color
|
||||
|
||||
if( istype(wear_suit, /obj/item/clothing/suit/straight_jacket) )
|
||||
drop_from_inventory(handcuffed)
|
||||
@@ -800,6 +796,7 @@ var/global/list/damage_icon_parts = list()
|
||||
standing = image("icon" = wear_mask.sprite_sheets[species.get_bodytype()], "icon_state" = "[wear_mask.icon_state]")
|
||||
else
|
||||
standing = image("icon" = 'icons/mob/mask.dmi', "icon_state" = "[wear_mask.icon_state]")
|
||||
standing.color = wear_mask.color
|
||||
|
||||
if( !istype(wear_mask, /obj/item/clothing/mask/smokable/cigarette) && wear_mask.blood_DNA )
|
||||
var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "maskblood")
|
||||
@@ -839,8 +836,12 @@ var/global/list/damage_icon_parts = list()
|
||||
else
|
||||
overlay_state = back.icon_state
|
||||
|
||||
//apply color
|
||||
var/image/standing = image(icon = overlay_icon, icon_state = overlay_state)
|
||||
standing.color = back.color
|
||||
|
||||
//create the image
|
||||
overlays_standing[BACK_LAYER] = image(icon = overlay_icon, icon_state = overlay_state)
|
||||
overlays_standing[BACK_LAYER] = standing
|
||||
else
|
||||
overlays_standing[BACK_LAYER] = null
|
||||
|
||||
@@ -919,7 +920,11 @@ var/global/list/damage_icon_parts = list()
|
||||
else
|
||||
t_icon = INV_R_HAND_DEF_ICON
|
||||
|
||||
overlays_standing[R_HAND_LAYER] = image(icon = t_icon, icon_state = t_state)
|
||||
//apply color
|
||||
var/image/standing = image(icon = t_icon, icon_state = t_state)
|
||||
standing.color = r_hand.color
|
||||
|
||||
overlays_standing[R_HAND_LAYER] = standing
|
||||
|
||||
if (handcuffed) drop_r_hand() //this should be moved out of icon code
|
||||
else
|
||||
@@ -951,7 +956,11 @@ var/global/list/damage_icon_parts = list()
|
||||
else
|
||||
t_icon = INV_L_HAND_DEF_ICON
|
||||
|
||||
overlays_standing[L_HAND_LAYER] = image(icon = t_icon, icon_state = t_state)
|
||||
//apply color
|
||||
var/image/standing = image(icon = t_icon, icon_state = t_state)
|
||||
standing.color = l_hand.color
|
||||
|
||||
overlays_standing[L_HAND_LAYER] = standing
|
||||
|
||||
if (handcuffed) drop_l_hand() //This probably should not be here
|
||||
else
|
||||
|
||||
@@ -703,14 +703,6 @@
|
||||
icon_state = module_sprites[icontype]
|
||||
return
|
||||
|
||||
//Call when target overlay should be added/removed
|
||||
/mob/living/silicon/robot/update_targeted()
|
||||
if(!targeted_by && target_locked)
|
||||
qdel(target_locked)
|
||||
updateicon()
|
||||
if (targeted_by && target_locked)
|
||||
overlays += target_locked
|
||||
|
||||
/mob/living/silicon/robot/proc/installed_modules()
|
||||
if(weapon_lock)
|
||||
src << "\red Weapon lock active, unable to use modules! Count:[weaponlock_time]"
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
maxHealth = 20
|
||||
health = 20
|
||||
|
||||
harm_intent_damage = 8
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 10
|
||||
harm_intent_damage = 10
|
||||
melee_damage_lower = 3
|
||||
melee_damage_upper = 3
|
||||
attacktext = "bites"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
|
||||
|
||||
@@ -6,14 +6,15 @@
|
||||
icon_state = "otherthing"
|
||||
icon_living = "otherthing"
|
||||
icon_dead = "otherthing-dead"
|
||||
health = 80
|
||||
maxHealth = 80
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 50
|
||||
health = 40
|
||||
maxHealth = 40
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 5
|
||||
attacktext = "chomped"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
faction = "creature"
|
||||
speed = 4
|
||||
speed = 8
|
||||
harm_intent_damage = 10
|
||||
|
||||
/mob/living/simple_animal/hostile/creature/cult
|
||||
faction = "cult"
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
response_help = "passes through"
|
||||
response_disarm = "shoves"
|
||||
response_harm = "hits"
|
||||
speed = -1
|
||||
maxHealth = 80
|
||||
health = 80
|
||||
speed = 8
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
|
||||
harm_intent_damage = 10
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 5
|
||||
attacktext = "gripped"
|
||||
attack_sound = 'sound/hallucinations/growl1.ogg'
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/cult
|
||||
faction = "cult"
|
||||
supernatural = 1
|
||||
|
||||
/mob/living/simple_animal/hostile/faithless/cult/cultify()
|
||||
return
|
||||
|
||||
@@ -365,14 +365,6 @@
|
||||
return (0)
|
||||
return 1
|
||||
|
||||
//Call when target overlay should be added/removed
|
||||
/mob/living/simple_animal/update_targeted()
|
||||
if(!targeted_by && target_locked)
|
||||
qdel(target_locked)
|
||||
overlays = null
|
||||
if (targeted_by && target_locked)
|
||||
overlays += target_locked
|
||||
|
||||
/mob/living/simple_animal/say(var/message)
|
||||
var/verb = "says"
|
||||
if(speak_emote.len)
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
//A very, very simple mob that exists inside other objects to talk and has zero influence on the world.
|
||||
/mob/living/voice
|
||||
name = "unknown"
|
||||
name = "unknown person"
|
||||
desc = "How are you examining me?"
|
||||
// default_language = "Galactic Common"
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
var/obj/item/device/communicator/comm = null
|
||||
|
||||
emote_type = 2 //This lets them emote through containers. The communicator has a image feed of the person calling them so...
|
||||
var/stable_connection = 0 //If set to zero, makes the mob effectively deaf, mute, and blind, due to interferance.
|
||||
|
||||
|
||||
/mob/living/voice/New(loc)
|
||||
add_language("Galactic Common")
|
||||
@@ -20,11 +18,15 @@
|
||||
comm = loc
|
||||
..()
|
||||
|
||||
// Proc: transfer_identity()
|
||||
// Parameters: 1 (speaker - the mob (usually an observer) to copy information from)
|
||||
// Description: Copies the mob's icons, overlays, TOD, gender, currently loaded character slot, and languages, to src.
|
||||
/mob/living/voice/proc/transfer_identity(mob/speaker)
|
||||
if(ismob(speaker))
|
||||
icon = speaker.icon
|
||||
icon_state = speaker.icon_state
|
||||
overlays = speaker.overlays
|
||||
timeofdeath = speaker.timeofdeath
|
||||
|
||||
alpha = 127 //Maybe we'll have hologram calls later.
|
||||
if(speaker.client && speaker.client.prefs)
|
||||
@@ -36,6 +38,9 @@
|
||||
for(var/language in p.alternate_languages)
|
||||
add_language(language)
|
||||
|
||||
// Proc: Login()
|
||||
// Parameters: None
|
||||
// Description: Adds a static overlay to the client's screen.
|
||||
/mob/living/voice/Login()
|
||||
var/obj/screen/static_effect = new() //Since what the player sees is essentially a video feed, from a vast distance away, the view isn't going to be perfect.
|
||||
static_effect.screen_loc = ui_entire_screen
|
||||
@@ -44,10 +49,23 @@
|
||||
static_effect.mouse_opacity = 0 //So the static doesn't get in the way of clicking.
|
||||
client.screen.Add(static_effect)
|
||||
|
||||
// Proc: Destroy()
|
||||
// Parameters: None
|
||||
// Description: Removes reference to the communicator, so it can qdel() successfully.
|
||||
/mob/living/voice/Destroy()
|
||||
comm = null
|
||||
..()
|
||||
|
||||
// Proc: ghostize()
|
||||
// Parameters: None
|
||||
// Description: Sets a timeofdeath variable, to fix the free respawn bug.
|
||||
/mob/living/voice/ghostize()
|
||||
timeofdeath = world.time
|
||||
. = ..()
|
||||
|
||||
// Verb: hang_up()
|
||||
// Parameters: None
|
||||
// Description: Disconnects the voice mob from the communicator.
|
||||
/mob/living/voice/verb/hang_up()
|
||||
set name = "Hang Up"
|
||||
set category = "Communicator"
|
||||
@@ -55,40 +73,53 @@
|
||||
set src = usr
|
||||
|
||||
if(comm)
|
||||
comm.close_connection(src, "[src] hung up")
|
||||
comm.close_connection(user = src, target = src, reason = "[src] hung up")
|
||||
else
|
||||
src << "You appear to not be inside a communicator. This is a bug and you should report it."
|
||||
|
||||
// Verb: change_name()
|
||||
// Parameters: None
|
||||
// Description: Allows the voice mob to change their name, assuming it is valid.
|
||||
/mob/living/voice/verb/change_name()
|
||||
set name = "Change Name"
|
||||
set category = "Communicator"
|
||||
set desc = "Changes your name."
|
||||
set src = usr
|
||||
|
||||
var/new_name = sanitizeSafe(input(src, "Who would you like to be now?", "Communicator", src.client.prefs.real_name) as text, MAX_NAME_LEN)
|
||||
if(new_name)
|
||||
if(comm)
|
||||
comm.visible_message("<span class='notice'>\icon[comm] [src.name] has left, and now you see [new_name].</span>")
|
||||
//Do a bit of logging in-case anyone tries to impersonate other characters for whatever reason.
|
||||
var/msg = "[src.client.key] ([src]) has changed their communicator identity's name to [new_name]."
|
||||
message_admins(msg)
|
||||
log_game(msg)
|
||||
src.name = new_name
|
||||
else
|
||||
src << "<span class='warning'>Invalid name. Rejected.</span>"
|
||||
|
||||
// Proc: Life()
|
||||
// Parameters: None
|
||||
// Description: Checks the active variable on the Exonet node, and kills the mob if it goes down or stops existing.
|
||||
/mob/living/voice/Life()
|
||||
if(comm && comm.server && !comm.server.active)
|
||||
comm.close_connection(src,"Connection to telecommunications array timed out")
|
||||
if(comm)
|
||||
if(!comm.node || !comm.node.on || !comm.node.allow_external_communicators)
|
||||
comm.close_connection(user = src, target = src, reason = "Connection to telecommunications array timed out")
|
||||
..()
|
||||
|
||||
// Proc: say()
|
||||
// Parameters: 4 (generic say() arguments)
|
||||
// Description: Adds a speech bubble to the communicator device, then calls ..() to do the real work.
|
||||
/mob/living/voice/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="")
|
||||
// world << "say() was called. Arguments: ([message], [speaking], [verb], [alt_name])."
|
||||
if(!stable_connection)
|
||||
return 0
|
||||
|
||||
//Speech bubbles.
|
||||
if(comm)
|
||||
var/speech_bubble_test = say_test(message)
|
||||
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
|
||||
var/image/speech_bubble = image('icons/mob/talk.dmi',comm,"h[speech_bubble_test]")
|
||||
spawn(30)
|
||||
qdel(speech_bubble)
|
||||
|
||||
for(var/mob/M in hearers(world.view,comm)) //simplifed since it's just a speech bubble
|
||||
for(var/mob/M in hearers(comm)) //simplifed since it's just a speech bubble
|
||||
M << speech_bubble
|
||||
src << speech_bubble
|
||||
|
||||
..(message, speaking, verb, alt_name) //mob/living/say() can do the actual talking.
|
||||
/*
|
||||
/mob/verb/test_voice_mob()
|
||||
set name = "Make Voice Mob"
|
||||
set category = "Debug"
|
||||
set desc = "For testing only!"
|
||||
set src = usr
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/item/device/communicator/comm = new(T)
|
||||
comm.open_connection(src, src)
|
||||
*/
|
||||
..(message, speaking, verb, alt_name) //mob/living/say() can do the actual talking.
|
||||
@@ -39,7 +39,6 @@
|
||||
pain = null
|
||||
item_use_icon = null
|
||||
gun_move_icon = null
|
||||
gun_run_icon = null
|
||||
gun_setting_icon = null
|
||||
spell_masters = null
|
||||
zone_sel = null
|
||||
@@ -765,8 +764,8 @@
|
||||
|
||||
if(lying)
|
||||
density = 0
|
||||
drop_l_hand()
|
||||
drop_r_hand()
|
||||
if(l_hand) unEquip(l_hand)
|
||||
if(r_hand) unEquip(r_hand)
|
||||
else
|
||||
density = initial(density)
|
||||
|
||||
|
||||
@@ -265,7 +265,7 @@
|
||||
return 0
|
||||
|
||||
move_delay = world.time//set move delay
|
||||
mob.last_move_intent = world.time + 10
|
||||
|
||||
switch(mob.m_intent)
|
||||
if("run")
|
||||
if(mob.drowsyness > 0)
|
||||
|
||||
@@ -375,9 +375,11 @@
|
||||
else // Crew transfer initiated
|
||||
dat += "<font color='red'>The station is currently undergoing crew transfer procedures.</font><br>"
|
||||
|
||||
dat += "Choose from the following open positions:<br>"
|
||||
dat += "Choose from the following open/valid positions:<br>"
|
||||
for(var/datum/job/job in job_master.occupations)
|
||||
if(job && IsJobAvailable(job.title))
|
||||
if(job.minimum_character_age && (client.prefs.age < job.minimum_character_age))
|
||||
continue
|
||||
var/active = 0
|
||||
// Only players with the job assigned and AFK for less than 10 minutes count as active
|
||||
for(var/mob/M in player_list) if(M.mind && M.client && M.mind.assigned_role == job.title && M.client.inactivity <= 10 * 60 * 10)
|
||||
|
||||
@@ -61,21 +61,6 @@
|
||||
name = "Short Hair 2"
|
||||
icon_state = "hair_shorthair3"
|
||||
|
||||
resomi
|
||||
name = "Resomi Plumage"
|
||||
icon_state = "resomi_default"
|
||||
species_allowed = list("Resomi")
|
||||
|
||||
resomi_ears
|
||||
name = "Resomi Ears"
|
||||
icon_state = "resomi_ears"
|
||||
species_allowed = list("Resomi")
|
||||
|
||||
resomi_excited
|
||||
name = "Resomi Spiky"
|
||||
icon_state = "resomi_spiky"
|
||||
species_allowed = list("Resomi")
|
||||
|
||||
cut
|
||||
name = "Cut Hair"
|
||||
icon_state = "hair_c"
|
||||
@@ -152,6 +137,10 @@
|
||||
name = "Side Ponytail"
|
||||
icon_state = "hair_stail"
|
||||
|
||||
sideponytail4 //Not happy about this... but it's for the save files.
|
||||
name = "Side Ponytail 2"
|
||||
icon_state = "hair_ponytailf"
|
||||
|
||||
sideponytail2
|
||||
name = "One Shoulder"
|
||||
icon_state = "hair_oneshoulder"
|
||||
@@ -160,6 +149,10 @@
|
||||
name = "Tress Shoulder"
|
||||
icon_state = "hair_tressshoulder"
|
||||
|
||||
wisp
|
||||
name = "Wisp"
|
||||
icon_state = "hair_wisp"
|
||||
|
||||
parted
|
||||
name = "Parted"
|
||||
icon_state = "hair_parted"
|
||||
|
||||
@@ -15,7 +15,7 @@ var/global/datum/robolimb/basic_robolimb
|
||||
var/desc = "A generic unbranded robotic prosthesis." // Seen when examining a limb.
|
||||
var/icon = 'icons/mob/human_races/robotic.dmi' // Icon base to draw from.
|
||||
var/unavailable_at_chargen // If set, not available at chargen.
|
||||
var/list/species_cannot_use = list("Resomi")
|
||||
var/list/species_cannot_use = list()
|
||||
|
||||
/datum/robolimb/bishop
|
||||
company = "Bishop Cybernetics"
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/obj/item/organ/external/foot/resomi
|
||||
body_hair = "feathers"
|
||||
/obj/item/organ/external/foot/right/resomi
|
||||
body_hair = "feathers"
|
||||
/obj/item/organ/external/hand/resomi
|
||||
body_hair = "feathers"
|
||||
/obj/item/organ/external/hand/right/resomi
|
||||
body_hair = "feathers"
|
||||
@@ -107,7 +107,7 @@
|
||||
if(process_projectile(P, user, user, pick("l_foot", "r_foot")))
|
||||
handle_post_fire(user, user)
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] shoots \himself in the foot with \the [src]!</span>",
|
||||
"<span class='danger'>\The [user] shoots \himself in the foot with \the [src]!</span>",
|
||||
"<span class='danger'>You shoot yourself in the foot with \the [src]!</span>"
|
||||
)
|
||||
M.drop_item()
|
||||
@@ -123,17 +123,17 @@
|
||||
/obj/item/weapon/gun/afterattack(atom/A, mob/living/user, adjacent, params)
|
||||
if(adjacent) return //A is adjacent, is the user, or is on the user's person
|
||||
|
||||
//decide whether to aim or shoot normally
|
||||
var/aiming = 0
|
||||
if(user && user.client && !(A in aim_targets))
|
||||
if(user.client.gun_mode)
|
||||
aiming = PreFire(A,user,params) //They're using the new gun system, locate what they're aiming at.
|
||||
if(!user.aiming)
|
||||
user.aiming = new(user)
|
||||
|
||||
if (!aiming)
|
||||
if(user && user.a_intent == I_HELP) //regardless of what happens, refuse to shoot if help intent is on
|
||||
user << "\red You refrain from firing your [src] as your intent is set to help."
|
||||
else
|
||||
Fire(A,user,params) //Otherwise, fire normally.
|
||||
if(user && user.client && user.aiming && user.aiming.active && user.aiming.aiming_at != A)
|
||||
PreFire(A,user,params) //They're using the new gun system, locate what they're aiming at.
|
||||
return
|
||||
|
||||
if(user && user.a_intent == I_HELP) //regardless of what happens, refuse to shoot if help intent is on
|
||||
user << "<span class='warning'>You refrain from firing your [src] as your intent is set to help.</span>"
|
||||
else
|
||||
Fire(A,user,params) //Otherwise, fire normally.
|
||||
|
||||
/obj/item/weapon/gun/attack(atom/A, mob/living/user, def_zone)
|
||||
if (A == user && user.zone_sel.selecting == "mouth" && !mouthshoot)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user