Repaths C4 (#808)

* Repaths C4

* Delete tgstation.2.1.3.dmm.rej

* Add files via upload

* update CitadelStation-1.2.1.dmm
This commit is contained in:
CitadelStationBot
2017-05-18 00:37:20 -05:00
committed by Poojawa
parent cd122501fc
commit 257cf986c5
99 changed files with 8768 additions and 8760 deletions
+1 -1
View File
@@ -32,7 +32,7 @@
#define BOTANIST (1<<2)
#define COOK (1<<3)
#define JANITOR (1<<4)
#define CURATOR (1<<5)
#define CURATOR (1<<5)
#define QUARTERMASTER (1<<6)
#define CARGOTECH (1<<7)
#define MINER (1<<8)
+1 -1
View File
@@ -457,7 +457,7 @@
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= L.len ? L[I] : null) : L[I]) : null)
#define LAZYLEN(L) length(L)
#define LAZYCLEARLIST(L) if(L) L.Cut()
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
/* Definining a counter as a series of key -> numeric value entries
+603 -603
View File
File diff suppressed because it is too large Load Diff
+33 -33
View File
@@ -1,34 +1,34 @@
GLOBAL_VAR(log_directory)
GLOBAL_PROTECT(log_directory)
GLOBAL_VAR(world_game_log)
GLOBAL_PROTECT(world_game_log)
GLOBAL_VAR(world_runtime_log)
GLOBAL_PROTECT(world_runtime_log)
GLOBAL_VAR(world_attack_log)
GLOBAL_PROTECT(world_attack_log)
GLOBAL_VAR(world_href_log)
GLOBAL_PROTECT(world_href_log)
GLOBAL_VAR(round_id)
GLOBAL_PROTECT(round_id)
GLOBAL_VAR(config_error_log)
GLOBAL_PROTECT(config_error_log)
GLOBAL_LIST_EMPTY(bombers)
GLOBAL_PROTECT(bombers)
GLOBAL_LIST_EMPTY(admin_log)
GLOBAL_PROTECT(admin_log)
GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src] used \ref[src] @ location [src.loc]: [freq]/[code]"
GLOBAL_PROTECT(lastsignalers)
GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was
GLOBAL_PROTECT(lawchanges)
GLOBAL_LIST_EMPTY(combatlog)
GLOBAL_PROTECT(combatlog)
GLOBAL_LIST_EMPTY(IClog)
GLOBAL_PROTECT(IClog)
GLOBAL_LIST_EMPTY(OOClog)
GLOBAL_PROTECT(OOClog)
GLOBAL_LIST_EMPTY(adminlog)
GLOBAL_PROTECT(adminlog)
GLOBAL_VAR(log_directory)
GLOBAL_PROTECT(log_directory)
GLOBAL_VAR(world_game_log)
GLOBAL_PROTECT(world_game_log)
GLOBAL_VAR(world_runtime_log)
GLOBAL_PROTECT(world_runtime_log)
GLOBAL_VAR(world_attack_log)
GLOBAL_PROTECT(world_attack_log)
GLOBAL_VAR(world_href_log)
GLOBAL_PROTECT(world_href_log)
GLOBAL_VAR(round_id)
GLOBAL_PROTECT(round_id)
GLOBAL_VAR(config_error_log)
GLOBAL_PROTECT(config_error_log)
GLOBAL_LIST_EMPTY(bombers)
GLOBAL_PROTECT(bombers)
GLOBAL_LIST_EMPTY(admin_log)
GLOBAL_PROTECT(admin_log)
GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src] used \ref[src] @ location [src.loc]: [freq]/[code]"
GLOBAL_PROTECT(lastsignalers)
GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was
GLOBAL_PROTECT(lawchanges)
GLOBAL_LIST_EMPTY(combatlog)
GLOBAL_PROTECT(combatlog)
GLOBAL_LIST_EMPTY(IClog)
GLOBAL_PROTECT(IClog)
GLOBAL_LIST_EMPTY(OOClog)
GLOBAL_PROTECT(OOClog)
GLOBAL_LIST_EMPTY(adminlog)
GLOBAL_PROTECT(adminlog)
GLOBAL_LIST_EMPTY(active_turfs_startlist)
+80 -80
View File
@@ -111,108 +111,108 @@
W.attack_self(src)
update_inv_hands()
return
//These are always reachable.
//User itself, current loc, and user inventory
if(DirectAccess(A))
//These are always reachable.
//User itself, current loc, and user inventory
if(DirectAccess(A))
if(W)
melee_item_attack_chain(src,W,A,params)
melee_item_attack_chain(src,W,A,params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A)
return
//Can't reach anything else in lockers or other weirdness
if(!loc.AllowClick())
//Can't reach anything else in lockers or other weirdness
if(!loc.AllowClick())
return
//Standard reach turf to turf or reaching inside storage
if(CanReach(A,W))
if(W)
melee_item_attack_chain(src,W,A,params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A,1)
else
if(W)
W.afterattack(A,src,0,params)
else
RangedAttack(A,params)
/atom/movable/proc/CanReach(atom/target,obj/item/tool,view_only = FALSE)
if(isturf(target) || isturf(target.loc) || DirectAccess(target)) //Directly accessible atoms
if(Adjacent(target) || (tool && CheckToolReach(src, target, tool.reach))) //Adjacent or reaching attacks
return TRUE
else
//Things inside storage insde another storage
//Eg Contents of a box in a backpack
var/atom/outer_storage = get_atom_on_turf(target)
if(outer_storage == target) //whatever that is we don't want infinite loop.
return FALSE
if(outer_storage && CanReach(outer_storage,tool) && outer_storage.CanReachStorage(target,src,view_only ? STORAGE_VIEW_DEPTH : INVENTORY_DEPTH))
return TRUE
return FALSE
//Can [target] in this container be reached by [user], can't be more than [depth] levels deep
/atom/proc/CanReachStorage(atom/target,user,depth)
return FALSE
/obj/item/weapon/storage/CanReachStorage(atom/target,user,depth)
while(target && depth > 0)
target = target.loc
depth--
if(target == src)
return TRUE
return FALSE
/atom/movable/proc/DirectAccess(atom/target)
if(target == src)
return TRUE
if(target == loc)
return TRUE
/mob/DirectAccess(atom/target)
if(..())
return TRUE
if(target in contents) //This could probably use moving down and restricting to inventory only
return TRUE
return FALSE
/mob/living/DirectAccess(atom/target)
if(..()) //Lightweight checks first
return TRUE
if(target in GetAllContents())
return TRUE
/atom/proc/AllowClick()
return FALSE
/turf/AllowClick()
return TRUE
//Standard reach turf to turf or reaching inside storage
if(CanReach(A,W))
if(W)
melee_item_attack_chain(src,W,A,params)
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A,1)
else
if(W)
W.afterattack(A,src,0,params)
else
RangedAttack(A,params)
/proc/CheckToolReach(atom/movable/here, atom/movable/there, reach)
/atom/movable/proc/CanReach(atom/target,obj/item/tool,view_only = FALSE)
if(isturf(target) || isturf(target.loc) || DirectAccess(target)) //Directly accessible atoms
if(Adjacent(target) || (tool && CheckToolReach(src, target, tool.reach))) //Adjacent or reaching attacks
return TRUE
else
//Things inside storage insde another storage
//Eg Contents of a box in a backpack
var/atom/outer_storage = get_atom_on_turf(target)
if(outer_storage == target) //whatever that is we don't want infinite loop.
return FALSE
if(outer_storage && CanReach(outer_storage,tool) && outer_storage.CanReachStorage(target,src,view_only ? STORAGE_VIEW_DEPTH : INVENTORY_DEPTH))
return TRUE
return FALSE
//Can [target] in this container be reached by [user], can't be more than [depth] levels deep
/atom/proc/CanReachStorage(atom/target,user,depth)
return FALSE
/obj/item/weapon/storage/CanReachStorage(atom/target,user,depth)
while(target && depth > 0)
target = target.loc
depth--
if(target == src)
return TRUE
return FALSE
/atom/movable/proc/DirectAccess(atom/target)
if(target == src)
return TRUE
if(target == loc)
return TRUE
/mob/DirectAccess(atom/target)
if(..())
return TRUE
if(target in contents) //This could probably use moving down and restricting to inventory only
return TRUE
return FALSE
/mob/living/DirectAccess(atom/target)
if(..()) //Lightweight checks first
return TRUE
if(target in GetAllContents())
return TRUE
/atom/proc/AllowClick()
return FALSE
/turf/AllowClick()
return TRUE
/proc/CheckToolReach(atom/movable/here, atom/movable/there, reach)
if(!here || !there)
return
switch(reach)
if(0)
return FALSE
return FALSE
if(1)
return FALSE //here.Adjacent(there)
return FALSE //here.Adjacent(there)
if(2 to INFINITY)
var/obj/dummy = new(get_turf(here))
var/obj/dummy = new(get_turf(here))
dummy.pass_flags |= PASSTABLE
dummy.invisibility = INVISIBILITY_ABSTRACT
dummy.invisibility = INVISIBILITY_ABSTRACT
for(var/i in 1 to reach) //Limit it to that many tries
var/turf/T = get_step(dummy, get_dir(dummy, there))
if(dummy.CanReach(there))
if(dummy.CanReach(there))
qdel(dummy)
return TRUE
return TRUE
if(!dummy.Move(T)) //we're blocked!
qdel(dummy)
return
qdel(dummy)
qdel(dummy)
// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click)
/mob/proc/DblClickOn(atom/A, params)
+162 -162
View File
@@ -1,162 +1,162 @@
/*
These defines specificy screen locations. For more information, see the byond documentation on the screen_loc var.
The short version:
Everything is encoded as strings because apparently that's how Byond rolls.
"1,1" is the bottom left square of the user's screen. This aligns perfectly with the turf grid.
"1:2,3:4" is the square (1,3) with pixel offsets (+2, +4); slightly right and slightly above the turf grid.
Pixel offsets are used so you don't perfectly hide the turf under them, that would be crappy.
In addition, the keywords NORTH, SOUTH, EAST, WEST and CENTER can be used to represent their respective
screen borders. NORTH-1, for example, is the row just below the upper edge. Useful if you want your
UI to scale with screen size.
The size of the user's screen is defined by client.view (indirectly by world.view), in our case "15x15".
Therefore, the top right corner (except during admin shenanigans) is at "15,15"
*/
//Lower left, persistent menu
#define ui_inventory "WEST:6,SOUTH:5"
//Middle left indicators
#define ui_lingchemdisplay "WEST,CENTER-1:15"
#define ui_lingstingdisplay "WEST:6,CENTER-3:11"
#define ui_crafting "12:-10,1:5"
#define ui_building "12:-10,1:21"
#define ui_language_menu "11:6,2:-11"
#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
//Lower center, persistent menu
#define ui_sstore1 "CENTER-5:10,SOUTH:5"
#define ui_id "CENTER-4:12,SOUTH:5"
#define ui_belt "CENTER-3:14,SOUTH:5"
#define ui_back "CENTER-2:14,SOUTH:5"
/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5)
var/x_off = -(!(i % 2))
var/y_off = round((i-1) / 2)
return"CENTER+[x_off]:16,SOUTH+[y_off]:5"
/proc/ui_equip_position(mob/M)
var/y_off = round((M.held_items.len-1) / 2) //values based on old equip ui position (CENTER: +/-16,SOUTH+1:5)
return "CENTER:-16,SOUTH+[y_off+1]:5"
/proc/ui_swaphand_position(mob/M, which = 1) //values based on old swaphand ui positions (CENTER: +/-16,SOUTH+1:5)
var/x_off = which == 1 ? -1 : 0
var/y_off = round((M.held_items.len-1) / 2)
return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5"
#define ui_storage1 "CENTER+1:18,SOUTH:5"
#define ui_storage2 "CENTER+2:20,SOUTH:5"
#define ui_borg_sensor "CENTER-3:16, SOUTH:5" //borgs
#define ui_borg_lamp "CENTER-4:16, SOUTH:5" //borgs
#define ui_borg_thrusters "CENTER-5:16, SOUTH:5" //borgs
#define ui_inv1 "CENTER-2:16,SOUTH:5" //borgs
#define ui_inv2 "CENTER-1 :16,SOUTH:5" //borgs
#define ui_inv3 "CENTER :16,SOUTH:5" //borgs
#define ui_borg_module "CENTER+1:16,SOUTH:5" //borgs
#define ui_borg_store "CENTER+2:16,SOUTH:5" //borgs
#define ui_borg_camera "CENTER+3:21,SOUTH:5" //borgs
#define ui_borg_album "CENTER+4:21,SOUTH:5" //borgs
#define ui_borg_language_menu "CENTER+4:21,SOUTH+1:5" //borgs
#define ui_monkey_head "CENTER-5:13,SOUTH:5" //monkey
#define ui_monkey_mask "CENTER-4:14,SOUTH:5" //monkey
#define ui_monkey_neck "CENTER-3:15,SOUTH:5" //monkey
#define ui_monkey_back "CENTER-2:16,SOUTH:5" //monkey
#define ui_alien_storage_l "CENTER-2:14,SOUTH:5"//alien
#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"//alien
#define ui_alien_language_menu "EAST-3:26,SOUTH:5" //alien
#define ui_drone_drop "CENTER+1:18,SOUTH:5" //maintenance drones
#define ui_drone_pull "CENTER+2:2,SOUTH:5" //maintenance drones
#define ui_drone_storage "CENTER-2:14,SOUTH:5" //maintenance drones
#define ui_drone_head "CENTER-3:14,SOUTH:5" //maintenance drones
//Lower right, persistent menu
#define ui_drop_throw "EAST-1:28,SOUTH+1:7"
#define ui_pull_resist "EAST-2:26,SOUTH+1:7"
#define ui_movi "EAST-2:26,SOUTH:5"
#define ui_acti "EAST-3:24,SOUTH:5"
#define ui_zonesel "EAST-1:28,SOUTH:5"
#define ui_acti_alt "EAST-1:28,SOUTH:5" //alternative intent switcher for when the interface is hidden (F12)
#define ui_borg_pull "EAST-2:26,SOUTH+1:7"
#define ui_borg_radio "EAST-1:28,SOUTH+1:7"
#define ui_borg_intents "EAST-2:26,SOUTH:5"
//Upper-middle right (alerts)
#define ui_alert1 "EAST-1:28,CENTER+5:27"
#define ui_alert2 "EAST-1:28,CENTER+4:25"
#define ui_alert3 "EAST-1:28,CENTER+3:23"
#define ui_alert4 "EAST-1:28,CENTER+2:21"
#define ui_alert5 "EAST-1:28,CENTER+1:19"
//Middle right (status indicators)
#define ui_healthdoll "EAST-1:28,CENTER-2:13"
#define ui_health "EAST-1:28,CENTER-1:15"
#define ui_internal "EAST-1:28,CENTER:17"
//borgs
#define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator.
//aliens
#define ui_alien_health "EAST,CENTER-1:15" //aliens have the health display where humans have the pressure damage indicator.
#define ui_alienplasmadisplay "EAST,CENTER-2:15"
#define ui_alien_queen_finder "EAST,CENTER-3:15"
//constructs
#define ui_construct_pull "EAST,CENTER-2:15"
#define ui_construct_health "EAST,CENTER:15" //same as borgs and humans
// AI
#define ui_ai_core "SOUTH:6,WEST"
#define ui_ai_camera_list "SOUTH:6,WEST+1"
#define ui_ai_track_with_camera "SOUTH:6,WEST+2"
#define ui_ai_camera_light "SOUTH:6,WEST+3"
#define ui_ai_crew_monitor "SOUTH:6,WEST+4"
#define ui_ai_crew_manifest "SOUTH:6,WEST+5"
#define ui_ai_alerts "SOUTH:6,WEST+6"
#define ui_ai_announcement "SOUTH:6,WEST+7"
#define ui_ai_shuttle "SOUTH:6,WEST+8"
#define ui_ai_state_laws "SOUTH:6,WEST+9"
#define ui_ai_pda_send "SOUTH:6,WEST+10"
#define ui_ai_pda_log "SOUTH:6,WEST+11"
#define ui_ai_take_picture "SOUTH:6,WEST+12"
#define ui_ai_view_images "SOUTH:6,WEST+13"
#define ui_ai_sensor "SOUTH:6,WEST+14"
//Pop-up inventory
#define ui_shoes "WEST+1:8,SOUTH:5"
#define ui_iclothing "WEST:6,SOUTH+1:7"
#define ui_oclothing "WEST+1:8,SOUTH+1:7"
#define ui_gloves "WEST+2:10,SOUTH+1:7"
#define ui_glasses "WEST:6,SOUTH+3:11"
#define ui_mask "WEST+1:8,SOUTH+2:9"
#define ui_ears "WEST+2:10,SOUTH+2:9"
#define ui_neck "WEST:6,SOUTH+2:9"
#define ui_head "WEST+1:8,SOUTH+3:11"
//Ghosts
#define ui_ghost_jumptomob "SOUTH:6,CENTER-2:24"
#define ui_ghost_orbit "SOUTH:6,CENTER-1:24"
#define ui_ghost_reenter_corpse "SOUTH:6,CENTER:24"
#define ui_ghost_teleport "SOUTH:6,CENTER+1:24"
#define ui_ghost_pai "SOUTH: 6, CENTER+2:24"
//Hand of God, god
#define ui_deityhealth "EAST-1:28,CENTER-2:13"
#define ui_deitypower "EAST-1:28,CENTER-1:15"
#define ui_deityfollowers "EAST-1:28,CENTER:17"
/*
These defines specificy screen locations. For more information, see the byond documentation on the screen_loc var.
The short version:
Everything is encoded as strings because apparently that's how Byond rolls.
"1,1" is the bottom left square of the user's screen. This aligns perfectly with the turf grid.
"1:2,3:4" is the square (1,3) with pixel offsets (+2, +4); slightly right and slightly above the turf grid.
Pixel offsets are used so you don't perfectly hide the turf under them, that would be crappy.
In addition, the keywords NORTH, SOUTH, EAST, WEST and CENTER can be used to represent their respective
screen borders. NORTH-1, for example, is the row just below the upper edge. Useful if you want your
UI to scale with screen size.
The size of the user's screen is defined by client.view (indirectly by world.view), in our case "15x15".
Therefore, the top right corner (except during admin shenanigans) is at "15,15"
*/
//Lower left, persistent menu
#define ui_inventory "WEST:6,SOUTH:5"
//Middle left indicators
#define ui_lingchemdisplay "WEST,CENTER-1:15"
#define ui_lingstingdisplay "WEST:6,CENTER-3:11"
#define ui_crafting "12:-10,1:5"
#define ui_building "12:-10,1:21"
#define ui_language_menu "11:6,2:-11"
#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
//Lower center, persistent menu
#define ui_sstore1 "CENTER-5:10,SOUTH:5"
#define ui_id "CENTER-4:12,SOUTH:5"
#define ui_belt "CENTER-3:14,SOUTH:5"
#define ui_back "CENTER-2:14,SOUTH:5"
/proc/ui_hand_position(i) //values based on old hand ui positions (CENTER:-/+16,SOUTH:5)
var/x_off = -(!(i % 2))
var/y_off = round((i-1) / 2)
return"CENTER+[x_off]:16,SOUTH+[y_off]:5"
/proc/ui_equip_position(mob/M)
var/y_off = round((M.held_items.len-1) / 2) //values based on old equip ui position (CENTER: +/-16,SOUTH+1:5)
return "CENTER:-16,SOUTH+[y_off+1]:5"
/proc/ui_swaphand_position(mob/M, which = 1) //values based on old swaphand ui positions (CENTER: +/-16,SOUTH+1:5)
var/x_off = which == 1 ? -1 : 0
var/y_off = round((M.held_items.len-1) / 2)
return "CENTER+[x_off]:16,SOUTH+[y_off+1]:5"
#define ui_storage1 "CENTER+1:18,SOUTH:5"
#define ui_storage2 "CENTER+2:20,SOUTH:5"
#define ui_borg_sensor "CENTER-3:16, SOUTH:5" //borgs
#define ui_borg_lamp "CENTER-4:16, SOUTH:5" //borgs
#define ui_borg_thrusters "CENTER-5:16, SOUTH:5" //borgs
#define ui_inv1 "CENTER-2:16,SOUTH:5" //borgs
#define ui_inv2 "CENTER-1 :16,SOUTH:5" //borgs
#define ui_inv3 "CENTER :16,SOUTH:5" //borgs
#define ui_borg_module "CENTER+1:16,SOUTH:5" //borgs
#define ui_borg_store "CENTER+2:16,SOUTH:5" //borgs
#define ui_borg_camera "CENTER+3:21,SOUTH:5" //borgs
#define ui_borg_album "CENTER+4:21,SOUTH:5" //borgs
#define ui_borg_language_menu "CENTER+4:21,SOUTH+1:5" //borgs
#define ui_monkey_head "CENTER-5:13,SOUTH:5" //monkey
#define ui_monkey_mask "CENTER-4:14,SOUTH:5" //monkey
#define ui_monkey_neck "CENTER-3:15,SOUTH:5" //monkey
#define ui_monkey_back "CENTER-2:16,SOUTH:5" //monkey
#define ui_alien_storage_l "CENTER-2:14,SOUTH:5"//alien
#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"//alien
#define ui_alien_language_menu "EAST-3:26,SOUTH:5" //alien
#define ui_drone_drop "CENTER+1:18,SOUTH:5" //maintenance drones
#define ui_drone_pull "CENTER+2:2,SOUTH:5" //maintenance drones
#define ui_drone_storage "CENTER-2:14,SOUTH:5" //maintenance drones
#define ui_drone_head "CENTER-3:14,SOUTH:5" //maintenance drones
//Lower right, persistent menu
#define ui_drop_throw "EAST-1:28,SOUTH+1:7"
#define ui_pull_resist "EAST-2:26,SOUTH+1:7"
#define ui_movi "EAST-2:26,SOUTH:5"
#define ui_acti "EAST-3:24,SOUTH:5"
#define ui_zonesel "EAST-1:28,SOUTH:5"
#define ui_acti_alt "EAST-1:28,SOUTH:5" //alternative intent switcher for when the interface is hidden (F12)
#define ui_borg_pull "EAST-2:26,SOUTH+1:7"
#define ui_borg_radio "EAST-1:28,SOUTH+1:7"
#define ui_borg_intents "EAST-2:26,SOUTH:5"
//Upper-middle right (alerts)
#define ui_alert1 "EAST-1:28,CENTER+5:27"
#define ui_alert2 "EAST-1:28,CENTER+4:25"
#define ui_alert3 "EAST-1:28,CENTER+3:23"
#define ui_alert4 "EAST-1:28,CENTER+2:21"
#define ui_alert5 "EAST-1:28,CENTER+1:19"
//Middle right (status indicators)
#define ui_healthdoll "EAST-1:28,CENTER-2:13"
#define ui_health "EAST-1:28,CENTER-1:15"
#define ui_internal "EAST-1:28,CENTER:17"
//borgs
#define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator.
//aliens
#define ui_alien_health "EAST,CENTER-1:15" //aliens have the health display where humans have the pressure damage indicator.
#define ui_alienplasmadisplay "EAST,CENTER-2:15"
#define ui_alien_queen_finder "EAST,CENTER-3:15"
//constructs
#define ui_construct_pull "EAST,CENTER-2:15"
#define ui_construct_health "EAST,CENTER:15" //same as borgs and humans
// AI
#define ui_ai_core "SOUTH:6,WEST"
#define ui_ai_camera_list "SOUTH:6,WEST+1"
#define ui_ai_track_with_camera "SOUTH:6,WEST+2"
#define ui_ai_camera_light "SOUTH:6,WEST+3"
#define ui_ai_crew_monitor "SOUTH:6,WEST+4"
#define ui_ai_crew_manifest "SOUTH:6,WEST+5"
#define ui_ai_alerts "SOUTH:6,WEST+6"
#define ui_ai_announcement "SOUTH:6,WEST+7"
#define ui_ai_shuttle "SOUTH:6,WEST+8"
#define ui_ai_state_laws "SOUTH:6,WEST+9"
#define ui_ai_pda_send "SOUTH:6,WEST+10"
#define ui_ai_pda_log "SOUTH:6,WEST+11"
#define ui_ai_take_picture "SOUTH:6,WEST+12"
#define ui_ai_view_images "SOUTH:6,WEST+13"
#define ui_ai_sensor "SOUTH:6,WEST+14"
//Pop-up inventory
#define ui_shoes "WEST+1:8,SOUTH:5"
#define ui_iclothing "WEST:6,SOUTH+1:7"
#define ui_oclothing "WEST+1:8,SOUTH+1:7"
#define ui_gloves "WEST+2:10,SOUTH+1:7"
#define ui_glasses "WEST:6,SOUTH+3:11"
#define ui_mask "WEST+1:8,SOUTH+2:9"
#define ui_ears "WEST+2:10,SOUTH+2:9"
#define ui_neck "WEST:6,SOUTH+2:9"
#define ui_head "WEST+1:8,SOUTH+3:11"
//Ghosts
#define ui_ghost_jumptomob "SOUTH:6,CENTER-2:24"
#define ui_ghost_orbit "SOUTH:6,CENTER-1:24"
#define ui_ghost_reenter_corpse "SOUTH:6,CENTER:24"
#define ui_ghost_teleport "SOUTH:6,CENTER+1:24"
#define ui_ghost_pai "SOUTH: 6, CENTER+2:24"
//Hand of God, god
#define ui_deityhealth "EAST-1:28,CENTER-2:13"
#define ui_deitypower "EAST-1:28,CENTER-1:15"
#define ui_deityfollowers "EAST-1:28,CENTER:17"
+4 -4
View File
@@ -68,10 +68,10 @@
using.screen_loc = ui_ghost_pai
static_inventory += using
using = new /obj/screen/language_menu
using.icon = ui_style
static_inventory += using
using = new /obj/screen/language_menu
using.icon = ui_style
static_inventory += using
/datum/hud/ghost/show_hud(version = 0, mob/viewmob)
..()
if(!mymob.client.prefs.ghost_hud)
+2 -2
View File
@@ -265,6 +265,6 @@
E.screen_loc = ui_equip_position(mymob)
if(mymob.hud_used)
show_hud(HUD_STYLE_STANDARD,mymob)
/datum/hud/proc/update_locked_slots()
/datum/hud/proc/update_locked_slots()
return
+12 -12
View File
@@ -313,18 +313,18 @@
inv_slots[inv.slot_id] = inv
inv.update_icon()
/datum/hud/human/update_locked_slots()
if(!mymob)
return
var/mob/living/carbon/human/H = mymob
var/datum/species/S = H.dna.species
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
if(inv.slot_id in S.no_equip)
inv.alpha = 128
else
inv.alpha = initial(inv.alpha)
/datum/hud/human/update_locked_slots()
if(!mymob)
return
var/mob/living/carbon/human/H = mymob
var/datum/species/S = H.dna.species
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
if(inv.slot_id in S.no_equip)
inv.alpha = 128
else
inv.alpha = initial(inv.alpha)
/datum/hud/human/hidden_inventory_update(mob/viewer)
if(!mymob)
return
+160 -160
View File
@@ -1,160 +1,160 @@
#define HOLOPAD_MAX_DIAL_TIME 200
/mob/camera/aiEye/remote/holo/setLoc()
. = ..()
var/obj/machinery/holopad/H = origin
H.move_hologram(eye_user, loc)
//this datum manages it's own references
/datum/holocall
var/mob/living/user //the one that called
var/obj/machinery/holopad/calling_holopad //the one that sent the call
var/obj/machinery/holopad/connected_holopad //the one that answered the call (may be null)
var/list/dialed_holopads //all things called, will be cleared out to just connected_holopad once answered
var/mob/camera/aiEye/remote/holo/eye //user's eye, once connected
var/obj/effect/overlay/holo_pad_hologram/hologram //user's hologram, once connected
var/call_start_time
//creates a holocall made by `caller` from `calling_pad` to `callees`
/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees)
call_start_time = world.time
user = caller
calling_pad.outgoing_call = src
calling_holopad = calling_pad
dialed_holopads = list()
for(var/I in callees)
var/obj/machinery/holopad/H = I
if(!QDELETED(H) && H.is_operational())
dialed_holopads += H
LAZYADD(H.holo_calls, src)
if(!dialed_holopads.len)
calling_pad.say("Connection failure.")
qdel(src)
return
testing("Holocall started")
//cleans up ALL references :)
/datum/holocall/Destroy()
QDEL_NULL(eye)
user.reset_perspective()
user = null
hologram.HC = null
hologram = null
calling_holopad.outgoing_call = null
for(var/I in dialed_holopads)
var/obj/machinery/holopad/H = I
LAZYREMOVE(H.holo_calls, src)
dialed_holopads.Cut()
if(calling_holopad)
calling_holopad.SetLightsAndPower()
calling_holopad = null
if(connected_holopad)
connected_holopad.SetLightsAndPower()
connected_holopad = null
testing("Holocall destroyed")
return ..()
//Gracefully disconnects a holopad `H` from a call. Pads not in the call are ignored. Notifies participants of the disconnection
/datum/holocall/proc/Disconnect(obj/machinery/holopad/H)
testing("Holocall disconnect")
if(H == connected_holopad)
calling_holopad.say("[usr] disconnected.")
else if(H == calling_holopad && connected_holopad)
connected_holopad.say("[usr] disconnected.")
ConnectionFailure(H, TRUE)
//Forcefully disconnects a holopad `H` from a call. Pads not in the call are ignored.
/datum/holocall/proc/ConnectionFailure(obj/machinery/holopad/H, graceful = FALSE)
testing("Holocall connection failure: graceful [graceful]")
if(H == connected_holopad || H == calling_holopad)
if(!graceful)
calling_holopad.say("Connection failure.")
qdel(src)
return
LAZYREMOVE(H.holo_calls, src)
dialed_holopads -= H
if(!dialed_holopads.len)
if(graceful)
calling_holopad.say("Call rejected.")
testing("No recipients, terminating")
qdel(src)
//Answers a call made to a holopad `H` which cannot be the calling holopad. Pads not in the call are ignored
/datum/holocall/proc/Answer(obj/machinery/holopad/H)
testing("Holocall answer")
if(H == calling_holopad)
CRASH("How cute, a holopad tried to answer itself.")
if(!(H in dialed_holopads))
return
if(connected_holopad)
CRASH("Multi-connection holocall")
for(var/I in dialed_holopads)
if(I == H)
continue
Disconnect(I)
for(var/I in H.holo_calls)
var/datum/holocall/HC = I
if(HC != src)
HC.Disconnect(H)
connected_holopad = H
if(!Check())
return
hologram = H.activate_holo(user)
hologram.HC = src
//eyeobj code is horrid, this is the best copypasta I could make
eye = new
eye.origin = H
eye.eye_initialized = TRUE
eye.eye_user = user
eye.name = "Camera Eye ([user.name])"
user.remote_control = eye
user.reset_perspective(eye)
eye.setLoc(H.loc)
//Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise
/datum/holocall/proc/Check()
for(var/I in dialed_holopads)
var/obj/machinery/holopad/H = I
if(!H.is_operational())
ConnectionFailure(H)
if(QDELETED(src))
return FALSE
. = !QDELETED(user) && !user.incapacitated() && !QDELETED(calling_holopad) && calling_holopad.is_operational() && user.loc == calling_holopad.loc
if(.)
if(connected_holopad)
. = !QDELETED(connected_holopad) && connected_holopad.is_operational()
else
. = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME)
if(!.)
calling_holopad.say("No answer recieved.")
calling_holopad.temp = ""
if(!.)
testing("Holocall Check fail")
qdel(src)
#define HOLOPAD_MAX_DIAL_TIME 200
/mob/camera/aiEye/remote/holo/setLoc()
. = ..()
var/obj/machinery/holopad/H = origin
H.move_hologram(eye_user, loc)
//this datum manages it's own references
/datum/holocall
var/mob/living/user //the one that called
var/obj/machinery/holopad/calling_holopad //the one that sent the call
var/obj/machinery/holopad/connected_holopad //the one that answered the call (may be null)
var/list/dialed_holopads //all things called, will be cleared out to just connected_holopad once answered
var/mob/camera/aiEye/remote/holo/eye //user's eye, once connected
var/obj/effect/overlay/holo_pad_hologram/hologram //user's hologram, once connected
var/call_start_time
//creates a holocall made by `caller` from `calling_pad` to `callees`
/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees)
call_start_time = world.time
user = caller
calling_pad.outgoing_call = src
calling_holopad = calling_pad
dialed_holopads = list()
for(var/I in callees)
var/obj/machinery/holopad/H = I
if(!QDELETED(H) && H.is_operational())
dialed_holopads += H
LAZYADD(H.holo_calls, src)
if(!dialed_holopads.len)
calling_pad.say("Connection failure.")
qdel(src)
return
testing("Holocall started")
//cleans up ALL references :)
/datum/holocall/Destroy()
QDEL_NULL(eye)
user.reset_perspective()
user = null
hologram.HC = null
hologram = null
calling_holopad.outgoing_call = null
for(var/I in dialed_holopads)
var/obj/machinery/holopad/H = I
LAZYREMOVE(H.holo_calls, src)
dialed_holopads.Cut()
if(calling_holopad)
calling_holopad.SetLightsAndPower()
calling_holopad = null
if(connected_holopad)
connected_holopad.SetLightsAndPower()
connected_holopad = null
testing("Holocall destroyed")
return ..()
//Gracefully disconnects a holopad `H` from a call. Pads not in the call are ignored. Notifies participants of the disconnection
/datum/holocall/proc/Disconnect(obj/machinery/holopad/H)
testing("Holocall disconnect")
if(H == connected_holopad)
calling_holopad.say("[usr] disconnected.")
else if(H == calling_holopad && connected_holopad)
connected_holopad.say("[usr] disconnected.")
ConnectionFailure(H, TRUE)
//Forcefully disconnects a holopad `H` from a call. Pads not in the call are ignored.
/datum/holocall/proc/ConnectionFailure(obj/machinery/holopad/H, graceful = FALSE)
testing("Holocall connection failure: graceful [graceful]")
if(H == connected_holopad || H == calling_holopad)
if(!graceful)
calling_holopad.say("Connection failure.")
qdel(src)
return
LAZYREMOVE(H.holo_calls, src)
dialed_holopads -= H
if(!dialed_holopads.len)
if(graceful)
calling_holopad.say("Call rejected.")
testing("No recipients, terminating")
qdel(src)
//Answers a call made to a holopad `H` which cannot be the calling holopad. Pads not in the call are ignored
/datum/holocall/proc/Answer(obj/machinery/holopad/H)
testing("Holocall answer")
if(H == calling_holopad)
CRASH("How cute, a holopad tried to answer itself.")
if(!(H in dialed_holopads))
return
if(connected_holopad)
CRASH("Multi-connection holocall")
for(var/I in dialed_holopads)
if(I == H)
continue
Disconnect(I)
for(var/I in H.holo_calls)
var/datum/holocall/HC = I
if(HC != src)
HC.Disconnect(H)
connected_holopad = H
if(!Check())
return
hologram = H.activate_holo(user)
hologram.HC = src
//eyeobj code is horrid, this is the best copypasta I could make
eye = new
eye.origin = H
eye.eye_initialized = TRUE
eye.eye_user = user
eye.name = "Camera Eye ([user.name])"
user.remote_control = eye
user.reset_perspective(eye)
eye.setLoc(H.loc)
//Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise
/datum/holocall/proc/Check()
for(var/I in dialed_holopads)
var/obj/machinery/holopad/H = I
if(!H.is_operational())
ConnectionFailure(H)
if(QDELETED(src))
return FALSE
. = !QDELETED(user) && !user.incapacitated() && !QDELETED(calling_holopad) && calling_holopad.is_operational() && user.loc == calling_holopad.loc
if(.)
if(connected_holopad)
. = !QDELETED(connected_holopad) && connected_holopad.is_operational()
else
. = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME)
if(!.)
calling_holopad.say("No answer recieved.")
calling_holopad.temp = ""
if(!.)
testing("Holocall Check fail")
qdel(src)
+1642 -1642
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -13,16 +13,16 @@
/datum/wires/explosive/c4
holder_type = /obj/item/weapon/c4
holder_type = /obj/item/weapon/grenade/plastic/c4
randomize = TRUE //Same behaviour since no wire actually disarms it
/datum/wires/explosive/c4/interactable(mob/user)
var/obj/item/weapon/c4/P = holder
var/obj/item/weapon/grenade/plastic/c4/P = holder
if(P.open_panel)
return TRUE
/datum/wires/explosive/c4/explode()
var/obj/item/weapon/c4/P = holder
var/obj/item/weapon/grenade/plastic/c4/P = holder
P.explode()
+2 -2
View File
@@ -155,8 +155,8 @@
if(!(check_usability(user)))
return
to_chat(user, "<span class='notice'>You activate [src] and wait for confirmation.</span>")
var/list/nuke_candidates = pollCandidatesForMob("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 150, POLL_IGNORE_SYNDICATE, src)
to_chat(user, "<span class='notice'>You activate [src] and wait for confirmation.</span>")
var/list/nuke_candidates = pollCandidatesForMob("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg":"operative"]?", ROLE_OPERATIVE, null, ROLE_OPERATIVE, 150, POLL_IGNORE_SYNDICATE, src)
if(nuke_candidates.len)
if(!(check_usability(user)))
return
+6 -6
View File
@@ -17,7 +17,7 @@
var/atom/movable/constant_target = null //The thing we're always focused on, if we're in the right mode
var/target_x = 0 //The target coordinates if we're tracking those
var/target_y = 0
var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination
var/minimum_range = 0 //at what range the pinpointer declares you to be at your destination
var/nuke_warning = FALSE // If we've set off a miniature alarm about an armed nuke
var/mode = TRACK_NUKE_DISK //What are we looking for?
@@ -112,7 +112,7 @@
var/mob/living/closest_operative = get_closest_atom(/mob/living/carbon/human, possible_targets, here)
if(closest_operative)
target = closest_operative
if(TRACK_ATOM)
if(TRACK_ATOM)
if(constant_target)
target = constant_target
if(TRACK_COORDINATES)
@@ -130,7 +130,7 @@
if(here.z != there.z)
icon_state = "pinon[nuke_warning ? "alert" : ""]null"
return
if(get_dist_euclidian(here,there)<=minimum_range)
if(get_dist_euclidian(here,there)<=minimum_range)
icon_state = "pinon[nuke_warning ? "alert" : ""]direct"
else
setDir(get_dir(here, there))
@@ -172,6 +172,6 @@
desc = "An integrated tracking device, jury-rigged to search for living Syndicate operatives."
mode = TRACK_OPERATIVES
flags = NODROP
File diff suppressed because it is too large Load Diff
+499 -499
View File
@@ -1,499 +1,499 @@
//Cloning revival method.
//The pod handles the actual cloning while the computer manages the clone profiles
//Potential replacement for genetics revives or something I dunno (?)
#define CLONE_INITIAL_DAMAGE 190 //Clones in clonepods start with 190 cloneloss damage and 190 brainloss damage, thats just logical
#define MINIMUM_HEAL_LEVEL 40
#define SPEAK(message) radio.talk_into(src, message, radio_channel, get_spans(), get_default_language())
/obj/machinery/clonepod
anchored = 1
name = "cloning pod"
desc = "An electronically-lockable pod for growing organic tissue."
density = 1
icon = 'icons/obj/cloning.dmi'
icon_state = "pod_0"
req_access = list(GLOB.access_cloning) //For premature unlocking.
verb_say = "states"
var/heal_level //The clone is released once its health reaches this level.
var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine.
var/mess = FALSE //Need to clean out it if it's full of exploded clone.
var/attempting = FALSE //One clone attempt at a time thanks
var/speed_coeff
var/efficiency
var/datum/mind/clonemind
var/grab_ghost_when = CLONER_MATURE_CLONE
var/obj/item/device/radio/radio
var/radio_key = /obj/item/device/encryptionkey/headset_med
var/radio_channel = "Medical"
var/obj/effect/countdown/clonepod/countdown
var/list/unattached_flesh
var/flesh_number = 0
// The "brine" is the reagents that are automatically added in small
// amounts to the occupant.
var/static/list/brine_types = list(
"salbutamol", // anti-oxyloss
"bicaridine", // NOBREATHE species take brute in crit
"corazone", // prevents cardiac arrest damage
"mimesbane") // stops them gasping from lack of air.
/obj/machinery/clonepod/New()
..()
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/clonepod(null)
B.apply_default_parts(src)
countdown = new(src)
radio = new(src)
radio.keyslot = new radio_key
radio.subspace_transmission = 1
radio.canhear_range = 0
radio.recalculateChannels()
/obj/machinery/clonepod/Destroy()
go_out()
qdel(radio)
radio = null
qdel(countdown)
countdown = null
if(connected)
connected.DetachCloner(src)
for(var/i in unattached_flesh)
qdel(i)
LAZYCLEARLIST(unattached_flesh)
unattached_flesh = null
. = ..()
/obj/machinery/clonepod/RefreshParts()
speed_coeff = 0
efficiency = 0
for(var/obj/item/weapon/stock_parts/scanning_module/S in component_parts)
efficiency += S.rating
for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts)
speed_coeff += P.rating
heal_level = (efficiency * 15) + 10
if(heal_level < MINIMUM_HEAL_LEVEL)
heal_level = MINIMUM_HEAL_LEVEL
if(heal_level > 100)
heal_level = 100
/obj/item/weapon/circuitboard/machine/clonepod
name = "Clone Pod (Machine Board)"
build_path = /obj/machinery/clonepod
origin_tech = "programming=2;biotech=2"
req_components = list(
/obj/item/stack/cable_coil = 2,
/obj/item/weapon/stock_parts/scanning_module = 2,
/obj/item/weapon/stock_parts/manipulator = 2,
/obj/item/stack/sheet/glass = 1)
//The return of data disks?? Just for transferring between genetics machine/cloning machine.
//TO-DO: Make the genetics machine accept them.
/obj/item/weapon/disk/data
name = "cloning data disk"
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
var/list/fields = list()
var/read_only = 0 //Well,it's still a floppy disk
//Disk stuff.
/obj/item/weapon/disk/data/New()
..()
icon_state = "datadisk[rand(0,6)]"
add_overlay("datadisk_gene")
/obj/item/weapon/disk/data/attack_self(mob/user)
read_only = !read_only
to_chat(user, "<span class='notice'>You flip the write-protect tab to [read_only ? "protected" : "unprotected"].</span>")
/obj/item/weapon/disk/data/examine(mob/user)
..()
to_chat(user, "The write-protect tab is set to [read_only ? "protected" : "unprotected"].")
//Clonepod
/obj/machinery/clonepod/examine(mob/user)
..()
var/mob/living/mob_occupant = occupant
if(mess)
to_chat(user, "It's filled with blood and viscera. You swear you can see it moving...")
if(is_operational() && mob_occupant)
if(mob_occupant.stat != DEAD)
to_chat(user, "Current clone cycle is [round(get_completion())]% complete.")
/obj/machinery/clonepod/return_air()
// We want to simulate the clone not being in contact with
// the atmosphere, so we'll put them in a constant pressure
// nitrogen. They'll breathe through the chemicals we pump into them.
var/static/datum/gas_mixture/immutable/cloner/GM //global so that there's only one instance made for all cloning pods
if(!GM)
GM = new
return GM
/obj/machinery/clonepod/proc/get_completion()
. = FALSE
var/mob/living/mob_occupant = occupant
if(mob_occupant)
. = (100 * ((mob_occupant.health + 100) / (heal_level + 100)))
/obj/machinery/clonepod/attack_ai(mob/user)
return examine(user)
//Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, se, mindref, datum/species/mrace, list/features, factions)
if(panel_open)
return FALSE
if(mess || attempting)
return FALSE
clonemind = locate(mindref)
if(!istype(clonemind)) //not a mind
return FALSE
if( clonemind.current && clonemind.current.stat != DEAD ) //mind is associated with a non-dead body
return FALSE
if(clonemind.active) //somebody is using that mind
if( ckey(clonemind.key)!=ckey )
return FALSE
else
// get_ghost() will fail if they're unable to reenter their body
var/mob/dead/observer/G = clonemind.get_ghost()
if(!G)
return FALSE
if(clonemind.damnation_type) //Can't clone the damned.
INVOKE_ASYNC(src, .proc/horrifyingsound)
mess = TRUE
icon_state = "pod_g"
update_icon()
return FALSE
attempting = TRUE //One at a time!!
countdown.start()
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
if(clonemind.changeling)
var/obj/item/organ/brain/B = H.getorganslot("brain")
B.vital = FALSE
B.decoy_override = TRUE
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
if(efficiency > 2)
var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations)
H.dna.remove_mutation_group(unclean_mutations)
if(efficiency > 5 && prob(20))
H.randmutvg()
if(efficiency < 3 && prob(50))
var/mob/M = H.randmutb()
if(ismob(M))
H = M
H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment.
occupant = H
if(!clonename) //to prevent null names
clonename = "clone ([rand(0,999)])"
H.real_name = clonename
icon_state = "pod_1"
//Get the clone body ready
maim_clone(H)
check_brine() // put in chemicals NOW to stop death via cardiac arrest
H.Paralyse(4)
clonemind.transfer_to(H)
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
to_chat(H, "<span class='notice'><b>Consciousness slowly creeps over you as your body regenerates.</b><br><i>So this is what cloning feels like?</i></span>")
if(grab_ghost_when == CLONER_MATURE_CLONE)
H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost
to_chat(H.get_ghost(TRUE), "<span class='notice'>Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.</span>")
if(H)
H.faction |= factions
H.set_cloned_appearance()
H.suiciding = FALSE
attempting = FALSE
return TRUE
//Grow clones to maturity then kick them out. FREELOADERS
/obj/machinery/clonepod/process()
var/mob/living/mob_occupant = occupant
if(!is_operational()) //Autoeject if power is lost
if(mob_occupant)
go_out()
connected_message("Clone Ejected: Loss of power.")
else if(mob_occupant && (mob_occupant.loc == src))
if((mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes.
connected_message("Clone Rejected: Deceased.")
SPEAK("The cloning of [mob_occupant.real_name] has been \
aborted due to unrecoverable tissue failure.")
go_out()
else if(mob_occupant.cloneloss > (100 - heal_level))
mob_occupant.Paralyse(4)
//Slowly get that clone healed and finished.
mob_occupant.adjustCloneLoss(-((speed_coeff/2) * config.damage_multiplier))
var/progress = CLONE_INITIAL_DAMAGE - mob_occupant.getCloneLoss()
// To avoid the default cloner making incomplete clones
progress += (100 - MINIMUM_HEAL_LEVEL)
var/milestone = CLONE_INITIAL_DAMAGE / flesh_number
var/installed = flesh_number - unattached_flesh.len
if((progress / milestone) >= installed)
// attach some flesh
var/obj/item/I = pick_n_take(unattached_flesh)
if(isorgan(I))
var/obj/item/organ/O = I
O.Insert(mob_occupant)
else if(isbodypart(I))
var/obj/item/bodypart/BP = I
BP.attach_limb(mob_occupant)
//Premature clones may have brain damage.
mob_occupant.adjustBrainLoss(-((speed_coeff/2) * config.damage_multiplier))
check_brine()
use_power(7500) //This might need tweaking.
else if((mob_occupant.cloneloss <= (100 - heal_level)))
connected_message("Cloning Process Complete.")
SPEAK("The cloning cycle of [mob_occupant.real_name] is complete.")
go_out()
else if (!mob_occupant || mob_occupant.loc != src)
occupant = null
if (!mess && !panel_open)
icon_state = "pod_0"
use_power(200)
//Let's unlock this early I guess. Might be too early, needs tweaking.
/obj/machinery/clonepod/attackby(obj/item/weapon/W, mob/user, params)
if(!(occupant || mess))
if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]",W))
return
if(exchange_parts(user, W))
return
if(default_deconstruction_crowbar(W))
return
if(istype(W,/obj/item/device/multitool))
var/obj/item/device/multitool/P = W
if(istype(P.buffer, /obj/machinery/computer/cloning))
if(get_area(P.buffer) != get_area(src))
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
P.buffer = null
return
to_chat(user, "<font color = #666633>-% Successfully linked [P.buffer] with [src] %-</font color>")
var/obj/machinery/computer/cloning/comp = P.buffer
if(connected)
connected.DetachCloner(src)
comp.AttachCloner(src)
else
P.buffer = src
to_chat(user, "<font color = #666633>-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-</font color>")
return
var/mob/living/mob_occupant = occupant
if(W.GetID())
if(!check_access(W))
to_chat(user, "<span class='danger'>Access Denied.</span>")
return
if(!(mob_occupant || mess))
to_chat(user, "<span class='danger'>Error: Pod has no occupant.</span>")
return
else
connected_message("Authorized Ejection")
SPEAK("An authorized ejection of [clonemind.name] has occurred.")
to_chat(user, "<span class='notice'>You force an emergency ejection. </span>")
go_out()
else
return ..()
/obj/machinery/clonepod/emag_act(mob/user)
if(!occupant)
return
to_chat(user, "<span class='warning'>You corrupt the genetic compiler.</span>")
malfunction()
//Put messages in the connected computer's temp var for display.
/obj/machinery/clonepod/proc/connected_message(message)
if ((isnull(connected)) || (!istype(connected, /obj/machinery/computer/cloning)))
return FALSE
if (!message)
return FALSE
connected.temp = message
connected.updateUsrDialog()
return TRUE
/obj/machinery/clonepod/proc/go_out()
countdown.stop()
var/mob/living/mob_occupant = occupant
if(mess) //Clean that mess and dump those gibs!
mess = FALSE
new /obj/effect/gibspawner/generic(loc)
audible_message("<span class='italics'>You hear a splat.</span>")
icon_state = "pod_0"
return
if(!mob_occupant)
return
if(grab_ghost_when == CLONER_MATURE_CLONE)
mob_occupant.grab_ghost()
to_chat(occupant, "<span class='notice'><b>There is a bright flash!</b><br><i>You feel like a new being.</i></span>")
mob_occupant.flash_act()
var/turf/T = get_turf(src)
occupant.forceMove(T)
icon_state = "pod_0"
mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
occupant = null
/obj/machinery/clonepod/proc/malfunction()
var/mob/living/mob_occupant = occupant
if(mob_occupant)
connected_message("Critical Error!")
SPEAK("Critical error! Please contact a Thinktronic Systems \
technician, as your warranty may be affected.")
mess = TRUE
for(var/obj/item/O in unattached_flesh)
qdel(O)
icon_state = "pod_g"
if(mob_occupant.mind != clonemind)
clonemind.transfer_to(mob_occupant)
mob_occupant.grab_ghost() // We really just want to make you suffer.
flash_color(mob_occupant, flash_color="#960000", flash_time=100)
to_chat(mob_occupant, "<span class='warning'><b>Agony blazes across your consciousness as your body is torn apart.</b><br><i>Is this what dying is like? Yes it is.</i></span>")
playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 50, 0)
mob_occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
QDEL_IN(mob_occupant, 40)
/obj/machinery/clonepod/relaymove(mob/user)
if(user.stat == CONSCIOUS)
go_out()
/obj/machinery/clonepod/emp_act(severity)
var/mob/living/mob_occupant = occupant
if(mob_occupant && prob(100/(severity*efficiency)))
connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [mob_occupant.real_name] prematurely." ,0))
go_out()
..()
/obj/machinery/clonepod/ex_act(severity, target)
..()
if(!QDELETED(src))
go_out()
/obj/machinery/clonepod/handle_atom_del(atom/A)
if(A == occupant)
occupant = null
countdown.stop()
/obj/machinery/clonepod/proc/horrifyingsound()
for(var/i in 1 to 5)
playsound(loc,pick('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg'), 100, rand(0.95,1.05))
sleep(1)
sleep(10)
playsound(loc,'sound/hallucinations/wail.ogg',100,1)
/obj/machinery/clonepod/deconstruct(disassembled = TRUE)
if(occupant)
go_out()
..()
/obj/machinery/clonepod/proc/maim_clone(mob/living/carbon/human/H)
if(!unattached_flesh)
unattached_flesh = list()
else
for(var/fl in unattached_flesh)
qdel(fl)
unattached_flesh.Cut()
H.setCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health
H.setBrainLoss(CLONE_INITIAL_DAMAGE)
// In addition to being cellularly damaged and having barely any
// brain function, they also have no limbs or internal organs.
var/static/list/zones = list("r_arm", "l_arm", "r_leg", "l_leg")
for(var/zone in zones)
var/obj/item/bodypart/BP = H.get_bodypart(zone)
BP.drop_limb()
BP.forceMove(src)
unattached_flesh += BP
for(var/o in H.internal_organs)
var/obj/item/organ/organ = o
if(!istype(organ) || organ.vital)
continue
organ.Remove(H, special=TRUE)
organ.forceMove(src)
unattached_flesh += organ
flesh_number = unattached_flesh.len
/obj/machinery/clonepod/proc/check_brine()
// Clones are in a pickled bath of mild chemicals, keeping
// them alive, despite their lack of internal organs
for(var/bt in brine_types)
if(occupant.reagents.get_reagent_amount(bt) < 1)
occupant.reagents.add_reagent(bt, 1)
/*
* Manual -- A big ol' manual.
*/
/obj/item/weapon/paper/Cloning
name = "paper - 'H-87 Cloning Apparatus Manual"
info = {"<h4>Getting Started</h4>
Congratulations, your station has purchased the H-87 industrial cloning device!<br>
Using the H-87 is almost as simple as brain surgery! Simply insert the target humanoid into the scanning chamber and select the scan option to create a new profile!<br>
<b>That's all there is to it!</b><br>
<i>Notice, cloning system cannot scan inorganic life or small primates. Scan may fail if subject has suffered extreme brain damage.</i><br>
<p>Clone profiles may be viewed through the profiles menu. Scanning implants a complementary HEALTH MONITOR IMPLANT into the subject, which may be viewed from each profile.
Profile Deletion has been restricted to \[Station Head\] level access.</p>
<h4>Cloning from a profile</h4>
Cloning is as simple as pressing the CLONE option at the bottom of the desired profile.<br>
Per your company's EMPLOYEE PRIVACY RIGHTS agreement, the H-87 has been blocked from cloning crewmembers while they are still alive.<br>
<br>
<p>The provided CLONEPOD SYSTEM will produce the desired clone. Standard clone maturation times (With SPEEDCLONE technology) are roughly 90 seconds.
The cloning pod may be unlocked early with any \[Medical Researcher\] ID after initial maturation is complete.</p><br>
<i>Please note that resulting clones may have a small DEVELOPMENTAL DEFECT as a result of genetic drift.</i><br>
<h4>Profile Management</h4>
<p>The H-87 (as well as your station's standard genetics machine) can accept STANDARD DATA DISKETTES.
These diskettes are used to transfer genetic information between machines and profiles.
A load/save dialog will become available in each profile if a disk is inserted.</p><br>
<i>A good diskette is a great way to counter aforementioned genetic drift!</i><br>
<br>
<font size=1>This technology produced under license from Thinktronic Systems, LTD.</font>"}
#undef CLONE_INITIAL_DAMAGE
#undef SPEAK
#undef MINIMUM_HEAL_LEVEL
//Cloning revival method.
//The pod handles the actual cloning while the computer manages the clone profiles
//Potential replacement for genetics revives or something I dunno (?)
#define CLONE_INITIAL_DAMAGE 190 //Clones in clonepods start with 190 cloneloss damage and 190 brainloss damage, thats just logical
#define MINIMUM_HEAL_LEVEL 40
#define SPEAK(message) radio.talk_into(src, message, radio_channel, get_spans(), get_default_language())
/obj/machinery/clonepod
anchored = 1
name = "cloning pod"
desc = "An electronically-lockable pod for growing organic tissue."
density = 1
icon = 'icons/obj/cloning.dmi'
icon_state = "pod_0"
req_access = list(GLOB.access_cloning) //For premature unlocking.
verb_say = "states"
var/heal_level //The clone is released once its health reaches this level.
var/obj/machinery/computer/cloning/connected = null //So we remember the connected clone machine.
var/mess = FALSE //Need to clean out it if it's full of exploded clone.
var/attempting = FALSE //One clone attempt at a time thanks
var/speed_coeff
var/efficiency
var/datum/mind/clonemind
var/grab_ghost_when = CLONER_MATURE_CLONE
var/obj/item/device/radio/radio
var/radio_key = /obj/item/device/encryptionkey/headset_med
var/radio_channel = "Medical"
var/obj/effect/countdown/clonepod/countdown
var/list/unattached_flesh
var/flesh_number = 0
// The "brine" is the reagents that are automatically added in small
// amounts to the occupant.
var/static/list/brine_types = list(
"salbutamol", // anti-oxyloss
"bicaridine", // NOBREATHE species take brute in crit
"corazone", // prevents cardiac arrest damage
"mimesbane") // stops them gasping from lack of air.
/obj/machinery/clonepod/New()
..()
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/clonepod(null)
B.apply_default_parts(src)
countdown = new(src)
radio = new(src)
radio.keyslot = new radio_key
radio.subspace_transmission = 1
radio.canhear_range = 0
radio.recalculateChannels()
/obj/machinery/clonepod/Destroy()
go_out()
qdel(radio)
radio = null
qdel(countdown)
countdown = null
if(connected)
connected.DetachCloner(src)
for(var/i in unattached_flesh)
qdel(i)
LAZYCLEARLIST(unattached_flesh)
unattached_flesh = null
. = ..()
/obj/machinery/clonepod/RefreshParts()
speed_coeff = 0
efficiency = 0
for(var/obj/item/weapon/stock_parts/scanning_module/S in component_parts)
efficiency += S.rating
for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts)
speed_coeff += P.rating
heal_level = (efficiency * 15) + 10
if(heal_level < MINIMUM_HEAL_LEVEL)
heal_level = MINIMUM_HEAL_LEVEL
if(heal_level > 100)
heal_level = 100
/obj/item/weapon/circuitboard/machine/clonepod
name = "Clone Pod (Machine Board)"
build_path = /obj/machinery/clonepod
origin_tech = "programming=2;biotech=2"
req_components = list(
/obj/item/stack/cable_coil = 2,
/obj/item/weapon/stock_parts/scanning_module = 2,
/obj/item/weapon/stock_parts/manipulator = 2,
/obj/item/stack/sheet/glass = 1)
//The return of data disks?? Just for transferring between genetics machine/cloning machine.
//TO-DO: Make the genetics machine accept them.
/obj/item/weapon/disk/data
name = "cloning data disk"
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
var/list/fields = list()
var/read_only = 0 //Well,it's still a floppy disk
//Disk stuff.
/obj/item/weapon/disk/data/New()
..()
icon_state = "datadisk[rand(0,6)]"
add_overlay("datadisk_gene")
/obj/item/weapon/disk/data/attack_self(mob/user)
read_only = !read_only
to_chat(user, "<span class='notice'>You flip the write-protect tab to [read_only ? "protected" : "unprotected"].</span>")
/obj/item/weapon/disk/data/examine(mob/user)
..()
to_chat(user, "The write-protect tab is set to [read_only ? "protected" : "unprotected"].")
//Clonepod
/obj/machinery/clonepod/examine(mob/user)
..()
var/mob/living/mob_occupant = occupant
if(mess)
to_chat(user, "It's filled with blood and viscera. You swear you can see it moving...")
if(is_operational() && mob_occupant)
if(mob_occupant.stat != DEAD)
to_chat(user, "Current clone cycle is [round(get_completion())]% complete.")
/obj/machinery/clonepod/return_air()
// We want to simulate the clone not being in contact with
// the atmosphere, so we'll put them in a constant pressure
// nitrogen. They'll breathe through the chemicals we pump into them.
var/static/datum/gas_mixture/immutable/cloner/GM //global so that there's only one instance made for all cloning pods
if(!GM)
GM = new
return GM
/obj/machinery/clonepod/proc/get_completion()
. = FALSE
var/mob/living/mob_occupant = occupant
if(mob_occupant)
. = (100 * ((mob_occupant.health + 100) / (heal_level + 100)))
/obj/machinery/clonepod/attack_ai(mob/user)
return examine(user)
//Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, se, mindref, datum/species/mrace, list/features, factions)
if(panel_open)
return FALSE
if(mess || attempting)
return FALSE
clonemind = locate(mindref)
if(!istype(clonemind)) //not a mind
return FALSE
if( clonemind.current && clonemind.current.stat != DEAD ) //mind is associated with a non-dead body
return FALSE
if(clonemind.active) //somebody is using that mind
if( ckey(clonemind.key)!=ckey )
return FALSE
else
// get_ghost() will fail if they're unable to reenter their body
var/mob/dead/observer/G = clonemind.get_ghost()
if(!G)
return FALSE
if(clonemind.damnation_type) //Can't clone the damned.
INVOKE_ASYNC(src, .proc/horrifyingsound)
mess = TRUE
icon_state = "pod_g"
update_icon()
return FALSE
attempting = TRUE //One at a time!!
countdown.start()
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
if(clonemind.changeling)
var/obj/item/organ/brain/B = H.getorganslot("brain")
B.vital = FALSE
B.decoy_override = TRUE
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
if(efficiency > 2)
var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations)
H.dna.remove_mutation_group(unclean_mutations)
if(efficiency > 5 && prob(20))
H.randmutvg()
if(efficiency < 3 && prob(50))
var/mob/M = H.randmutb()
if(ismob(M))
H = M
H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment.
occupant = H
if(!clonename) //to prevent null names
clonename = "clone ([rand(0,999)])"
H.real_name = clonename
icon_state = "pod_1"
//Get the clone body ready
maim_clone(H)
check_brine() // put in chemicals NOW to stop death via cardiac arrest
H.Paralyse(4)
clonemind.transfer_to(H)
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
to_chat(H, "<span class='notice'><b>Consciousness slowly creeps over you as your body regenerates.</b><br><i>So this is what cloning feels like?</i></span>")
if(grab_ghost_when == CLONER_MATURE_CLONE)
H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost
to_chat(H.get_ghost(TRUE), "<span class='notice'>Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.</span>")
if(H)
H.faction |= factions
H.set_cloned_appearance()
H.suiciding = FALSE
attempting = FALSE
return TRUE
//Grow clones to maturity then kick them out. FREELOADERS
/obj/machinery/clonepod/process()
var/mob/living/mob_occupant = occupant
if(!is_operational()) //Autoeject if power is lost
if(mob_occupant)
go_out()
connected_message("Clone Ejected: Loss of power.")
else if(mob_occupant && (mob_occupant.loc == src))
if((mob_occupant.stat == DEAD) || (mob_occupant.suiciding) || mob_occupant.hellbound) //Autoeject corpses and suiciding dudes.
connected_message("Clone Rejected: Deceased.")
SPEAK("The cloning of [mob_occupant.real_name] has been \
aborted due to unrecoverable tissue failure.")
go_out()
else if(mob_occupant.cloneloss > (100 - heal_level))
mob_occupant.Paralyse(4)
//Slowly get that clone healed and finished.
mob_occupant.adjustCloneLoss(-((speed_coeff/2) * config.damage_multiplier))
var/progress = CLONE_INITIAL_DAMAGE - mob_occupant.getCloneLoss()
// To avoid the default cloner making incomplete clones
progress += (100 - MINIMUM_HEAL_LEVEL)
var/milestone = CLONE_INITIAL_DAMAGE / flesh_number
var/installed = flesh_number - unattached_flesh.len
if((progress / milestone) >= installed)
// attach some flesh
var/obj/item/I = pick_n_take(unattached_flesh)
if(isorgan(I))
var/obj/item/organ/O = I
O.Insert(mob_occupant)
else if(isbodypart(I))
var/obj/item/bodypart/BP = I
BP.attach_limb(mob_occupant)
//Premature clones may have brain damage.
mob_occupant.adjustBrainLoss(-((speed_coeff/2) * config.damage_multiplier))
check_brine()
use_power(7500) //This might need tweaking.
else if((mob_occupant.cloneloss <= (100 - heal_level)))
connected_message("Cloning Process Complete.")
SPEAK("The cloning cycle of [mob_occupant.real_name] is complete.")
go_out()
else if (!mob_occupant || mob_occupant.loc != src)
occupant = null
if (!mess && !panel_open)
icon_state = "pod_0"
use_power(200)
//Let's unlock this early I guess. Might be too early, needs tweaking.
/obj/machinery/clonepod/attackby(obj/item/weapon/W, mob/user, params)
if(!(occupant || mess))
if(default_deconstruction_screwdriver(user, "[icon_state]_maintenance", "[initial(icon_state)]",W))
return
if(exchange_parts(user, W))
return
if(default_deconstruction_crowbar(W))
return
if(istype(W,/obj/item/device/multitool))
var/obj/item/device/multitool/P = W
if(istype(P.buffer, /obj/machinery/computer/cloning))
if(get_area(P.buffer) != get_area(src))
to_chat(user, "<font color = #666633>-% Cannot link machines across power zones. Buffer cleared %-</font color>")
P.buffer = null
return
to_chat(user, "<font color = #666633>-% Successfully linked [P.buffer] with [src] %-</font color>")
var/obj/machinery/computer/cloning/comp = P.buffer
if(connected)
connected.DetachCloner(src)
comp.AttachCloner(src)
else
P.buffer = src
to_chat(user, "<font color = #666633>-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-</font color>")
return
var/mob/living/mob_occupant = occupant
if(W.GetID())
if(!check_access(W))
to_chat(user, "<span class='danger'>Access Denied.</span>")
return
if(!(mob_occupant || mess))
to_chat(user, "<span class='danger'>Error: Pod has no occupant.</span>")
return
else
connected_message("Authorized Ejection")
SPEAK("An authorized ejection of [clonemind.name] has occurred.")
to_chat(user, "<span class='notice'>You force an emergency ejection. </span>")
go_out()
else
return ..()
/obj/machinery/clonepod/emag_act(mob/user)
if(!occupant)
return
to_chat(user, "<span class='warning'>You corrupt the genetic compiler.</span>")
malfunction()
//Put messages in the connected computer's temp var for display.
/obj/machinery/clonepod/proc/connected_message(message)
if ((isnull(connected)) || (!istype(connected, /obj/machinery/computer/cloning)))
return FALSE
if (!message)
return FALSE
connected.temp = message
connected.updateUsrDialog()
return TRUE
/obj/machinery/clonepod/proc/go_out()
countdown.stop()
var/mob/living/mob_occupant = occupant
if(mess) //Clean that mess and dump those gibs!
mess = FALSE
new /obj/effect/gibspawner/generic(loc)
audible_message("<span class='italics'>You hear a splat.</span>")
icon_state = "pod_0"
return
if(!mob_occupant)
return
if(grab_ghost_when == CLONER_MATURE_CLONE)
mob_occupant.grab_ghost()
to_chat(occupant, "<span class='notice'><b>There is a bright flash!</b><br><i>You feel like a new being.</i></span>")
mob_occupant.flash_act()
var/turf/T = get_turf(src)
occupant.forceMove(T)
icon_state = "pod_0"
mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest.
occupant = null
/obj/machinery/clonepod/proc/malfunction()
var/mob/living/mob_occupant = occupant
if(mob_occupant)
connected_message("Critical Error!")
SPEAK("Critical error! Please contact a Thinktronic Systems \
technician, as your warranty may be affected.")
mess = TRUE
for(var/obj/item/O in unattached_flesh)
qdel(O)
icon_state = "pod_g"
if(mob_occupant.mind != clonemind)
clonemind.transfer_to(mob_occupant)
mob_occupant.grab_ghost() // We really just want to make you suffer.
flash_color(mob_occupant, flash_color="#960000", flash_time=100)
to_chat(mob_occupant, "<span class='warning'><b>Agony blazes across your consciousness as your body is torn apart.</b><br><i>Is this what dying is like? Yes it is.</i></span>")
playsound(src.loc, 'sound/machines/warning-buzzer.ogg', 50, 0)
mob_occupant << sound('sound/hallucinations/veryfar_noise.ogg',0,1,50)
QDEL_IN(mob_occupant, 40)
/obj/machinery/clonepod/relaymove(mob/user)
if(user.stat == CONSCIOUS)
go_out()
/obj/machinery/clonepod/emp_act(severity)
var/mob/living/mob_occupant = occupant
if(mob_occupant && prob(100/(severity*efficiency)))
connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of [mob_occupant.real_name] prematurely." ,0))
go_out()
..()
/obj/machinery/clonepod/ex_act(severity, target)
..()
if(!QDELETED(src))
go_out()
/obj/machinery/clonepod/handle_atom_del(atom/A)
if(A == occupant)
occupant = null
countdown.stop()
/obj/machinery/clonepod/proc/horrifyingsound()
for(var/i in 1 to 5)
playsound(loc,pick('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg'), 100, rand(0.95,1.05))
sleep(1)
sleep(10)
playsound(loc,'sound/hallucinations/wail.ogg',100,1)
/obj/machinery/clonepod/deconstruct(disassembled = TRUE)
if(occupant)
go_out()
..()
/obj/machinery/clonepod/proc/maim_clone(mob/living/carbon/human/H)
if(!unattached_flesh)
unattached_flesh = list()
else
for(var/fl in unattached_flesh)
qdel(fl)
unattached_flesh.Cut()
H.setCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health
H.setBrainLoss(CLONE_INITIAL_DAMAGE)
// In addition to being cellularly damaged and having barely any
// brain function, they also have no limbs or internal organs.
var/static/list/zones = list("r_arm", "l_arm", "r_leg", "l_leg")
for(var/zone in zones)
var/obj/item/bodypart/BP = H.get_bodypart(zone)
BP.drop_limb()
BP.forceMove(src)
unattached_flesh += BP
for(var/o in H.internal_organs)
var/obj/item/organ/organ = o
if(!istype(organ) || organ.vital)
continue
organ.Remove(H, special=TRUE)
organ.forceMove(src)
unattached_flesh += organ
flesh_number = unattached_flesh.len
/obj/machinery/clonepod/proc/check_brine()
// Clones are in a pickled bath of mild chemicals, keeping
// them alive, despite their lack of internal organs
for(var/bt in brine_types)
if(occupant.reagents.get_reagent_amount(bt) < 1)
occupant.reagents.add_reagent(bt, 1)
/*
* Manual -- A big ol' manual.
*/
/obj/item/weapon/paper/Cloning
name = "paper - 'H-87 Cloning Apparatus Manual"
info = {"<h4>Getting Started</h4>
Congratulations, your station has purchased the H-87 industrial cloning device!<br>
Using the H-87 is almost as simple as brain surgery! Simply insert the target humanoid into the scanning chamber and select the scan option to create a new profile!<br>
<b>That's all there is to it!</b><br>
<i>Notice, cloning system cannot scan inorganic life or small primates. Scan may fail if subject has suffered extreme brain damage.</i><br>
<p>Clone profiles may be viewed through the profiles menu. Scanning implants a complementary HEALTH MONITOR IMPLANT into the subject, which may be viewed from each profile.
Profile Deletion has been restricted to \[Station Head\] level access.</p>
<h4>Cloning from a profile</h4>
Cloning is as simple as pressing the CLONE option at the bottom of the desired profile.<br>
Per your company's EMPLOYEE PRIVACY RIGHTS agreement, the H-87 has been blocked from cloning crewmembers while they are still alive.<br>
<br>
<p>The provided CLONEPOD SYSTEM will produce the desired clone. Standard clone maturation times (With SPEEDCLONE technology) are roughly 90 seconds.
The cloning pod may be unlocked early with any \[Medical Researcher\] ID after initial maturation is complete.</p><br>
<i>Please note that resulting clones may have a small DEVELOPMENTAL DEFECT as a result of genetic drift.</i><br>
<h4>Profile Management</h4>
<p>The H-87 (as well as your station's standard genetics machine) can accept STANDARD DATA DISKETTES.
These diskettes are used to transfer genetic information between machines and profiles.
A load/save dialog will become available in each profile if a disk is inserted.</p><br>
<i>A good diskette is a great way to counter aforementioned genetic drift!</i><br>
<br>
<font size=1>This technology produced under license from Thinktronic Systems, LTD.</font>"}
#undef CLONE_INITIAL_DAMAGE
#undef SPEAK
#undef MINIMUM_HEAL_LEVEL
+8 -8
View File
@@ -186,23 +186,23 @@
// Scanner
if (!isnull(src.scanner))
var/mob/living/scanner_occupant = scanner.occupant
var/mob/living/scanner_occupant = scanner.occupant
dat += "<h3>Scanner Functions</h3>"
dat += "<div class='statusDisplay'>"
if(!scanner_occupant)
if(!scanner_occupant)
dat += "Scanner Unoccupied"
else if(loading)
dat += "[scanner_occupant] => Scanning..."
dat += "[scanner_occupant] => Scanning..."
else
if(scanner_occupant.ckey != scantemp_ckey)
if(scanner_occupant.ckey != scantemp_ckey)
scantemp = "Ready to Scan"
scantemp_ckey = scanner_occupant.ckey
dat += "[scanner_occupant] => [scantemp]"
scantemp_ckey = scanner_occupant.ckey
dat += "[scanner_occupant] => [scantemp]"
dat += "</div>"
if(scanner_occupant)
if(scanner_occupant)
dat += "<a href='byond://?src=\ref[src];scan=1'>Start Scan</a>"
dat += "<br><a href='byond://?src=\ref[src];lock=1'>[src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]</a>"
else
+3 -3
View File
@@ -113,8 +113,8 @@
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
R.ResetSecurityCodes()
else
var/turf/T = get_turf(R)
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] detonated [key_name(R, R.client)][ADMIN_JMP(T)]!</span>")
var/turf/T = get_turf(R)
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] detonated [key_name(R, R.client)][ADMIN_JMP(T)]!</span>")
log_game("\<span class='notice'>[key_name(usr)] detonated [key_name(R)]!</span>")
if(R.connected_ai)
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
@@ -128,7 +128,7 @@
if(can_control(usr, R))
var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm" && can_control(usr, R) && !..())
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [R.canmove ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [R.canmove ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [key_name(R)]!")
R.SetLockdown(!R.lockcharge)
to_chat(R, "[!R.lockcharge ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
@@ -58,12 +58,12 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1)
if(uplinkholder && linkedboss)
if(amt < 0)
linkedboss.storedcrystals += uplinkholder.hidden_uplink.telecrystals
if(addLog)
linkedboss.logTransfer("[src] donated [uplinkholder.hidden_uplink.telecrystals] telecrystals to [linkedboss].")
uplinkholder.hidden_uplink.telecrystals = 0
else if(amt <= uplinkholder.hidden_uplink.telecrystals)
if(amt < 0)
linkedboss.storedcrystals += uplinkholder.hidden_uplink.telecrystals
if(addLog)
linkedboss.logTransfer("[src] donated [uplinkholder.hidden_uplink.telecrystals] telecrystals to [linkedboss].")
uplinkholder.hidden_uplink.telecrystals = 0
else if(amt <= uplinkholder.hidden_uplink.telecrystals)
uplinkholder.hidden_uplink.telecrystals -= amt
linkedboss.storedcrystals += amt
if(addLog)
@@ -71,12 +71,12 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1)
if(uplinkholder && linkedboss)
if(amt < 0)
uplinkholder.hidden_uplink.telecrystals += linkedboss.storedcrystals
if(addLog)
linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].")
linkedboss.storedcrystals = 0
else if(amt <= linkedboss.storedcrystals)
if(amt < 0)
uplinkholder.hidden_uplink.telecrystals += linkedboss.storedcrystals
if(addLog)
linkedboss.logTransfer("[src] received [linkedboss.storedcrystals] telecrystals from [linkedboss].")
linkedboss.storedcrystals = 0
else if(amt <= linkedboss.storedcrystals)
uplinkholder.hidden_uplink.telecrystals += amt
linkedboss.storedcrystals -= amt
if(addLog)
@@ -99,7 +99,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(uplinkholder)
dat += "[uplinkholder.hidden_uplink.telecrystals] telecrystals remain in this uplink.<BR>"
if(linkedboss)
dat += "Donate TC: <a href='byond://?src=\ref[src];donate=1'>1</a> | <a href='byond://?src=\ref[src];donate=5'>5</a> | <a href='byond://?src=\ref[src];donate=-1'>All</a>"
dat += "Donate TC: <a href='byond://?src=\ref[src];donate=1'>1</a> | <a href='byond://?src=\ref[src];donate=5'>5</a> | <a href='byond://?src=\ref[src];donate=-1'>All</a>"
dat += "<br><a href='byond://?src=\ref[src];eject=1'>Eject Uplink</a>"
@@ -113,9 +113,9 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(..())
return
if(href_list["donate"])
var/tcamt = text2num(href_list["donate"])
donateTC(tcamt)
if(href_list["donate"])
var/tcamt = text2num(href_list["donate"])
donateTC(tcamt)
if(href_list["eject"])
ejectuplink()
@@ -170,7 +170,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
var/dat = ""
dat += "<a href='byond://?src=\ref[src];scan=1'>Scan for TC stations.</a><BR>"
dat += "[storedcrystals] telecrystals are available for distribution. <BR>"
dat += "[storedcrystals] telecrystals are available for distribution. <BR>"
dat += "<BR><BR>"
@@ -179,10 +179,10 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(A.uplinkholder)
dat += "[A.uplinkholder.hidden_uplink.telecrystals] telecrystals."
if(storedcrystals)
dat+= "<BR>Add TC: <a href ='?src=\ref[src];target=\ref[A];give=1'>1</a> | <a href ='?src=\ref[src];target=\ref[A];give=5'>5</a> | <a href ='?src=\ref[src];target=\ref[A];give=10'>10</a> | <a href ='?src=\ref[src];target=\ref[A];give=-1'>All</a>"
dat+= "<BR>Add TC: <a href ='?src=\ref[src];target=\ref[A];give=1'>1</a> | <a href ='?src=\ref[src];target=\ref[A];give=5'>5</a> | <a href ='?src=\ref[src];target=\ref[A];give=10'>10</a> | <a href ='?src=\ref[src];target=\ref[A];give=-1'>All</a>"
dat += "<BR>"
if(TCstations.len && storedcrystals)
if(TCstations.len && storedcrystals)
dat += "<BR><BR><a href='byond://?src=\ref[src];distrib=1'>Evenly distribute remaining TC.</a><BR><BR>"
@@ -203,11 +203,11 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(href_list["scan"])
scanUplinkers()
if(href_list["give"])
var/tcamt = text2num(href_list["give"])
if(TCstations.len) // sanity
var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["target"]) in TCstations
A.giveTC(tcamt)
if(href_list["give"])
var/tcamt = text2num(href_list["give"])
if(TCstations.len) // sanity
var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["target"]) in TCstations
A.giveTC(tcamt)
if(href_list["distrib"])
var/sanity = 0
+1 -1
View File
@@ -121,7 +121,7 @@
var/atom/movable/AM = i
var/obj/item/bodypart/head/as_head = AM
var/obj/item/device/mmi/as_mmi = AM
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /mob/living/brain)
var/brain_holder = istype(AM, /obj/item/organ/brain) || (istype(as_head) && as_head.brain) || (istype(as_mmi) && as_mmi.brain) || istype(AM, /mob/living/brain)
if(isliving(AM) || brain_holder)
if(emagged)
if(!brain_holder)
+9 -9
View File
@@ -211,13 +211,13 @@
uv = TRUE
locked = TRUE
update_icon()
if(occupant)
var/mob/living/mob_occupant = occupant
if(occupant)
var/mob/living/mob_occupant = occupant
if(uv_super)
mob_occupant.adjustFireLoss(rand(20, 36))
mob_occupant.adjustFireLoss(rand(20, 36))
else
mob_occupant.adjustFireLoss(rand(10, 16))
mob_occupant.emote("scream")
mob_occupant.adjustFireLoss(rand(10, 16))
mob_occupant.emote("scream")
addtimer(CALLBACK(src, .proc/cook), 50)
else
uv_cycles = initial(uv_cycles)
@@ -368,15 +368,15 @@
else if(!helmet && !mask && !suit && !storage && !occupant)
return
else
if(occupant)
var/mob/living/mob_occupant = occupant
to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>")
if(occupant)
var/mob/living/mob_occupant = occupant
to_chat(mob_occupant, "<span class='userdanger'>[src]'s confines grow warm, then hot, then scorching. You're being burned [!mob_occupant.stat ? "alive" : "away"]!</span>")
cook()
. = TRUE
if("dispense")
if(!state_open)
return
var/static/list/valid_items = list("helmet", "suit", "mask", "storage")
var/item_name = params["item"]
if(item_name in valid_items)
+3 -3
View File
@@ -107,7 +107,7 @@
icon_state = "mecha_ion"
origin_tech = "materials=4;engineering=4;combat=6;magnets=6"
energy_drain = 500
projectile = /obj/item/projectile/energy/tesla/cannon
projectile = /obj/item/projectile/energy/tesla/cannon
fire_sound = 'sound/magic/lightningbolt.ogg'
@@ -337,8 +337,8 @@
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/proj_init(var/obj/item/weapon/grenade/flashbang/F)
var/turf/T = get_turf(src)
message_admins("[ADMIN_LOOKUPFLW(chassis.occupant)] fired a [src] in [ADMIN_COORDJMP(T)]",0,1)
log_game("[key_name(chassis.occupant)] fired a [src] [COORD(T)]")
message_admins("[ADMIN_LOOKUPFLW(chassis.occupant)] fired a [src] in [ADMIN_COORDJMP(T)]",0,1)
log_game("[key_name(chassis.occupant)] fired a [src] [COORD(T)]")
addtimer(CALLBACK(F, /obj/item/weapon/grenade/flashbang.proc/prime), det_time)
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/launcher/flashbang/clusterbang //Because I am a heartless bastard -Sieve //Heartless? for making the poor man's honkblast? - Kaze
+1 -1
View File
@@ -94,7 +94,7 @@
name = "Head of Personnel"
/obj/effect/landmark/start/librarian
name = "Curator"
name = "Curator"
/obj/effect/landmark/start/lawyer
name = "Lawyer"
+1 -1
View File
@@ -63,7 +63,7 @@
return
if (istype(M, /atom/movable))
if(ismegafauna(M))
message_admins("[M] [ADMIN_FLW(M)] has teleported through [src].")
message_admins("[M] [ADMIN_FLW(M)] has teleported through [src].")
do_teleport(M, target, precision) ///You will appear adjacent to the beacon
+1 -1
View File
@@ -108,7 +108,7 @@
access_mime = 1
var/mime_charges = 5
/obj/item/weapon/cartridge/curator
/obj/item/weapon/cartridge/curator
name = "\improper Lib-Tweet cartridge"
icon_state = "cart-s"
access_newscaster = 1
+80 -80
View File
@@ -12,9 +12,9 @@ GLOBAL_LIST_EMPTY(GPS_list)
var/emped = FALSE
var/turf/locked_location
var/tracking = TRUE
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
/obj/item/device/gps/Initialize()
..()
@@ -31,7 +31,7 @@ GLOBAL_LIST_EMPTY(GPS_list)
cut_overlay("working")
add_overlay("emp")
addtimer(CALLBACK(src, .proc/reboot), 300, TIMER_OVERRIDE) //if a new EMP happens, remove the old timer so it doesn't reactivate early
SStgui.close_uis(src) //Close the UI control if it is open.
SStgui.close_uis(src) //Close the UI control if it is open.
/obj/item/device/gps/proc/reboot()
emped = FALSE
@@ -39,9 +39,9 @@ GLOBAL_LIST_EMPTY(GPS_list)
add_overlay("working")
/obj/item/device/gps/AltClick(mob/user)
toggletracking(user)
/obj/item/device/gps/proc/toggletracking(mob/user)
toggletracking(user)
/obj/item/device/gps/proc/toggletracking(mob/user)
if(!user.canUseTopic(src, be_close=TRUE))
return //user not valid to use gps
if(emped)
@@ -57,80 +57,80 @@ GLOBAL_LIST_EMPTY(GPS_list)
tracking = TRUE
/obj/item/device/gps/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
/obj/item/device/gps/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
if(emped)
to_chat(user, "[src] fizzles weakly.")
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
var/gps_window_height = 300 + GLOB.GPS_list.len * 20 // Variable window height, depending on how many GPS units there are to show
ui = new(user, src, ui_key, "gps", "Global Positioning System", 600, gps_window_height, master_ui, state) //width, height
ui.open()
ui.set_autoupdate(state = updating)
/obj/item/device/gps/ui_data(mob/user)
var/list/data = list()
data["power"] = tracking
data["tag"] = gpstag
data["updating"] = updating
data["globalmode"] = global_mode
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
return data
var/turf/curr = get_turf(src)
data["current"] = "[get_area_name(curr)] ([curr.x], [curr.y], [curr.z])"
var/list/signals = list()
data["signals"] = list()
for(var/gps in GLOB.GPS_list)
var/obj/item/device/gps/G = gps
if(G.emped || !G.tracking || G == src)
continue
var/turf/pos = get_turf(G)
if(!global_mode && pos.z != curr.z)
continue
var/area/gps_area = get_area_name(G)
var/list/signal = list()
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
signal["area"] = format_text(gps_area)
signal["coord"] = "[pos.x], [pos.y], [pos.z]"
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
var/direction = uppertext(dir2text(get_dir(curr, pos))) //Direction text (East, etc). Not as precise, but still helpful.
if(!direction)
direction = "CENTER"
signal["degrees"] = "N/A"
signal["direction"] = direction
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
return data
/obj/item/device/gps/ui_act(action, params)
if(..())
return
switch(action)
if("rename")
var/a = input("Please enter desired tag.", name, gpstag) as text
a = uppertext(copytext(sanitize(a), 1, 5))
gpstag = a
name = "global positioning system ([gpstag])"
. = TRUE
if("power")
toggletracking(usr)
. = TRUE
if("updating")
updating = !updating
. = TRUE
if("globalmode")
global_mode = !global_mode
. = TRUE
to_chat(user, "[src] fizzles weakly.")
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
var/gps_window_height = 300 + GLOB.GPS_list.len * 20 // Variable window height, depending on how many GPS units there are to show
ui = new(user, src, ui_key, "gps", "Global Positioning System", 600, gps_window_height, master_ui, state) //width, height
ui.open()
ui.set_autoupdate(state = updating)
/obj/item/device/gps/ui_data(mob/user)
var/list/data = list()
data["power"] = tracking
data["tag"] = gpstag
data["updating"] = updating
data["globalmode"] = global_mode
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
return data
var/turf/curr = get_turf(src)
data["current"] = "[get_area_name(curr)] ([curr.x], [curr.y], [curr.z])"
var/list/signals = list()
data["signals"] = list()
for(var/gps in GLOB.GPS_list)
var/obj/item/device/gps/G = gps
if(G.emped || !G.tracking || G == src)
continue
var/turf/pos = get_turf(G)
if(!global_mode && pos.z != curr.z)
continue
var/area/gps_area = get_area_name(G)
var/list/signal = list()
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
signal["area"] = format_text(gps_area)
signal["coord"] = "[pos.x], [pos.y], [pos.z]"
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
var/direction = uppertext(dir2text(get_dir(curr, pos))) //Direction text (East, etc). Not as precise, but still helpful.
if(!direction)
direction = "CENTER"
signal["degrees"] = "N/A"
signal["direction"] = direction
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
return data
/obj/item/device/gps/ui_act(action, params)
if(..())
return
switch(action)
if("rename")
var/a = input("Please enter desired tag.", name, gpstag) as text
a = uppertext(copytext(sanitize(a), 1, 5))
gpstag = a
name = "global positioning system ([gpstag])"
. = TRUE
if("power")
toggletracking(usr)
. = TRUE
if("updating")
updating = !updating
. = TRUE
if("globalmode")
global_mode = !global_mode
. = TRUE
/obj/item/device/gps/Topic(href, href_list)
..()
+2 -2
View File
@@ -95,8 +95,8 @@
"[user] activates \the [src]!", \
"<span class='notice'>You activate \the [src].</span>",
"<span class='italics'>You hear a click.</span>")
message_admins("Power sink activated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_COORDJMP(src)]")
log_game("Power sink activated by [key_name(user)] at [COORD(src)]")
message_admins("Power sink activated by [ADMIN_LOOKUPFLW(user)] at [ADMIN_COORDJMP(src)]")
log_game("Power sink activated by [key_name(user)] at [COORD(src)]")
set_mode(OPERATING)
if(OPERATING)
@@ -178,21 +178,21 @@
var/log_attacher = ""
if(attacher)
log_attacher = "[ADMIN_QUE(attacher)] [ADMIN_FLW(attacher)]"
log_attacher = "[ADMIN_QUE(attacher)] [ADMIN_FLW(attacher)]"
var/mob/mob = get_mob_by_key(src.fingerprintslast)
var/last_touch_info = ""
if(mob)
last_touch_info = "[ADMIN_QUE(mob)] [ADMIN_FLW(mob)]"
last_touch_info = "[ADMIN_QUE(mob)] [ADMIN_FLW(mob)]"
var/log_str3 = " Last touched by: [key_name_admin(mob)]"
var/bomb_message = "[log_str1] [A.name][ADMIN_JMP(bombturf)] [log_str2][log_attacher] [log_str3][last_touch_info]"
var/bomb_message = "[log_str1] [A.name][ADMIN_JMP(bombturf)] [log_str2][log_attacher] [log_str3][last_touch_info]"
GLOB.bombers += bomb_message
message_admins(bomb_message, 0, 1)
log_game("[log_str1] [A.name][COORD(bombturf)] [log_str2] [log_str3]")
log_game("[log_str1] [A.name][COORD(bombturf)] [log_str2] [log_str3]")
merge_gases()
spawn(20) // In case one tank bursts
for (var/i=0,i<5,i++)
@@ -237,7 +237,7 @@
/obj/item/borg/upgrade/selfrepair/proc/check_dropped()
if(loc != cyborg)
toggle_action.Remove(cyborg)
QDEL_NULL(toggle_action)
QDEL_NULL(toggle_action)
cyborg = null
deactivate()
@@ -400,4 +400,4 @@
return
R.make_shell(src)
return TRUE
return TRUE
@@ -1,115 +0,0 @@
//In this file: C4
/obj/item/weapon/c4
name = "C-4"
desc = "Used to put holes in specific areas without too much extra hole."
gender = PLURAL
icon = 'icons/obj/grenade.dmi'
icon_state = "plastic-explosive0"
item_state = "plasticx"
flags = NOBLUDGEON
w_class = WEIGHT_CLASS_SMALL
origin_tech = "syndicate=1"
var/timer = 10
var/open_panel = 0
parent_type = /obj/item/weapon/grenade/plastic/c4
/obj/item/weapon/c4/New()
wires = new /datum/wires/explosive/c4(src)
plastic_overlay = mutable_appearance(icon, "plastic-explosive2")
..()
/obj/item/weapon/c4/Destroy()
qdel(wires)
wires = null
target = null
return ..()
/obj/item/weapon/c4/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] activates the [src.name] and holds it above [user.p_their()] head! It looks like [user.p_theyre()] going out with a bang!</span>")
var/message_say = "FOR NO RAISIN!"
if(user.mind)
if(user.mind.special_role)
var/role = lowertext(user.mind.special_role)
if(role == "traitor" || role == "syndicate")
message_say = "FOR THE SYNDICATE!"
else if(role == "changeling")
message_say = "FOR THE HIVE!"
else if(role == "cultist")
message_say = "FOR NAR-SIE!"
else if(role == "revolutionary" || role == "head revolutionary")
message_say = "VIVA LA REVOLUTION!"
else if(user.mind.gang_datum)
message_say = "[uppertext(user.mind.gang_datum.name)] RULES!"
user.say(message_say)
target = user
message_admins("[ADMIN_LOOKUPFLW(user)] suicided with [name] at [ADMIN_COORDJMP(src)]",0,1)
message_admins("[key_name(user)] suicided with [name] at ([x],[y],[z])")
sleep(10)
explode(get_turf(user))
user.gib(1, 1)
/obj/item/weapon/c4/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/screwdriver))
open_panel = !open_panel
to_chat(user, "<span class='notice'>You [open_panel ? "open" : "close"] the wire panel.</span>")
else if(is_wire_tool(I))
wires.interact(user)
else
return ..()
/obj/item/weapon/c4/attack_self(mob/user)
var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num
if(user.get_active_held_item() == src)
newtime = Clamp(newtime, 10, 60000)
timer = newtime
to_chat(user, "Timer set for [timer] seconds.")
/obj/item/weapon/c4/afterattack(atom/movable/AM, mob/user, flag)
if (!flag)
return
if (ismob(AM))
return
if(loc == AM)
return
if((istype(AM, /obj/item/weapon/storage/)) && !((istype(AM, /obj/item/weapon/storage/secure)) || (istype(AM, /obj/item/weapon/storage/lockbox)))) //If its storage but not secure storage OR a lockbox, then place it inside.
return
if((istype(AM,/obj/item/weapon/storage/secure)) || (istype(AM, /obj/item/weapon/storage/lockbox)))
var/obj/item/weapon/storage/secure/S = AM
if(!S.locked) //Literal hacks, this works for lockboxes despite incorrect type casting, because they both share the locked var. But if its unlocked, place it inside, otherwise PLANTING C4!
return
to_chat(user, "<span class='notice'>You start planting the bomb...</span>")
if(do_after(user, 50, target = AM))
if(!user.temporarilyRemoveItemFromInventory(src))
return
src.target = AM
forceMove(null)
var/message = "[ADMIN_LOOKUPFLW(user)] planted [name] on [target.name] at [ADMIN_COORDJMP(target)] with [timer] second fuse"
GLOB.bombers += message
message_admins(message,0,1)
log_game("[key_name(user)] planted [name] on [target.name] at [COORD(target)] with [timer] second fuse")
target.add_overlay(plastic_overlay, 1)
to_chat(user, "<span class='notice'>You plant the bomb. Timer counting down from [timer].</span>")
addtimer(CALLBACK(src, .proc/explode), timer * 10)
/obj/item/weapon/c4/proc/explode()
if(QDELETED(src))
return
var/turf/location
if(target)
if(!QDELETED(target))
location = get_turf(target)
target.cut_overlay(plastic_overlay, TRUE)
else
location = get_turf(src)
if(location)
location.ex_act(2, target)
explosion(location,0,0,3)
qdel(src)
/obj/item/weapon/c4/attack(mob/M, mob/user, def_zone)
return
@@ -154,6 +154,115 @@
/obj/item/weapon/grenade/plastic/c4
name = "C4"
desc = "Used to put holes in specific areas without too much extra hole. A saboteur's favorite."
gender = PLURAL
icon = 'icons/obj/grenade.dmi'
icon_state = "plastic-explosive0"
item_state = "plasticx"
flags = NOBLUDGEON
w_class = WEIGHT_CLASS_SMALL
origin_tech = "syndicate=1"
var/timer = 10
var/open_panel = 0
/obj/item/weapon/grenade/plastic/c4/New()
wires = new /datum/wires/explosive/c4(src)
plastic_overlay = mutable_appearance(icon, "plastic-explosive2")
..()
/obj/item/weapon/grenade/plastic/c4/Destroy()
qdel(wires)
wires = null
target = null
return ..()
/obj/item/weapon/grenade/plastic/c4/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] activates the [src.name] and holds it above [user.p_their()] head! It looks like [user.p_theyre()] going out with a bang!</span>")
var/message_say = "FOR NO RAISIN!"
if(user.mind)
if(user.mind.special_role)
var/role = lowertext(user.mind.special_role)
if(role == "traitor" || role == "syndicate")
message_say = "FOR THE SYNDICATE!"
else if(role == "changeling")
message_say = "FOR THE HIVE!"
else if(role == "cultist")
message_say = "FOR NAR-SIE!"
else if(role == "revolutionary" || role == "head revolutionary")
message_say = "VIVA LA REVOLUTION!"
else if(user.mind.gang_datum)
message_say = "[uppertext(user.mind.gang_datum.name)] RULES!"
user.say(message_say)
target = user
message_admins("[ADMIN_LOOKUPFLW(user)] suicided with [name] at [ADMIN_COORDJMP(src)]",0,1)
message_admins("[key_name(user)] suicided with [name] at ([x],[y],[z])")
sleep(10)
explode(get_turf(user))
user.gib(1, 1)
/obj/item/weapon/grenade/plastic/c4/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/screwdriver))
open_panel = !open_panel
to_chat(user, "<span class='notice'>You [open_panel ? "open" : "close"] the wire panel.</span>")
else if(is_wire_tool(I))
wires.interact(user)
else
return ..()
/obj/item/weapon/grenade/plastic/c4/attack_self(mob/user)
var/newtime = input(usr, "Please set the timer.", "Timer", 10) as num
if(user.get_active_held_item() == src)
newtime = Clamp(newtime, 10, 60000)
timer = newtime
to_chat(user, "Timer set for [timer] seconds.")
/obj/item/weapon/grenade/plastic/c4/afterattack(atom/movable/AM, mob/user, flag)
if (!flag)
return
if (ismob(AM))
return
if(loc == AM)
return
if((istype(AM, /obj/item/weapon/storage/)) && !((istype(AM, /obj/item/weapon/storage/secure)) || (istype(AM, /obj/item/weapon/storage/lockbox)))) //If its storage but not secure storage OR a lockbox, then place it inside.
return
if((istype(AM,/obj/item/weapon/storage/secure)) || (istype(AM, /obj/item/weapon/storage/lockbox)))
var/obj/item/weapon/storage/secure/S = AM
if(!S.locked) //Literal hacks, this works for lockboxes despite incorrect type casting, because they both share the locked var. But if its unlocked, place it inside, otherwise PLANTING C4!
return
to_chat(user, "<span class='notice'>You start planting the bomb...</span>")
if(do_after(user, 50, target = AM))
if(!user.temporarilyRemoveItemFromInventory(src))
return
src.target = AM
forceMove(null)
var/message = "[ADMIN_LOOKUPFLW(user)] planted [name] on [target.name] at [ADMIN_COORDJMP(target)] with [timer] second fuse"
GLOB.bombers += message
message_admins(message,0,1)
log_game("[key_name(user)] planted [name] on [target.name] at [COORD(target)] with [timer] second fuse")
target.add_overlay(plastic_overlay, 1)
to_chat(user, "<span class='notice'>You plant the bomb. Timer counting down from [timer].</span>")
addtimer(CALLBACK(src, .proc/explode), timer * 10)
/obj/item/weapon/grenade/plastic/c4/proc/explode()
if(QDELETED(src))
return
var/turf/location
if(target)
if(!QDELETED(target))
location = get_turf(target)
target.cut_overlay(plastic_overlay, TRUE)
else
location = get_turf(src)
if(location)
location.ex_act(2, target)
explosion(location,0,0,3)
qdel(src)
/obj/item/weapon/grenade/plastic/c4/attack(mob/M, mob/user, def_zone)
return
// X4 is an upgraded directional variant of c4 which is relatively safe to be standing next to. And much less safe to be standing on the other side of.
// C4 is intended to be used for infiltration, and destroying tech. X4 is intended to be used for heavy breaching and tight spaces.
@@ -1,5 +1,5 @@
/obj/item/weapon/grenade/spawnergrenade
desc = "It will unleash an unspecified anomaly into the vicinity."
desc = "It will unleash an unspecified anomaly into the vicinity."
name = "delivery grenade"
icon = 'icons/obj/grenade.dmi'
icon_state = "delivery"
@@ -41,10 +41,10 @@
data["open"] = state_open
data["occupant"] = list()
if(occupant)
var/mob/living/mob_occupant = occupant
data["occupant"]["name"] = mob_occupant.name
data["occupant"]["stat"] = mob_occupant.stat
if(occupant)
var/mob/living/mob_occupant = occupant
data["occupant"]["name"] = mob_occupant.name
data["occupant"]["stat"] = mob_occupant.stat
data["special_name"] = special ? special_name : null
data["ready_implants"] = ready_implants
@@ -16,7 +16,7 @@
var/brightness_on = 3
/obj/item/weapon/melee/energy/Initialize()
. = ..()
. = ..()
if(LAZYLEN(possible_colors))
item_color = pick(possible_colors)
switch(item_color)//Only run this check if the color was picked randomly, so that colors can be manually set for non-random colored energy weapons.
@@ -183,8 +183,8 @@
light_color = "#40ceff"
possible_colors = null
/obj/item/weapon/melee/energy/sword/cyborg/saw/Initialize()
. = ..()
/obj/item/weapon/melee/energy/sword/cyborg/saw/Initialize()
. = ..()
icon_state = "esaw_0"
item_color = null
@@ -207,9 +207,9 @@
/obj/item/weapon/melee/energy/sword/saber/attackby(obj/item/weapon/W, mob/living/user, params)
if(istype(W, /obj/item/device/multitool))
if(!hacked)
hacked = TRUE
if(istype(W, /obj/item/device/multitool))
if(!hacked)
hacked = TRUE
item_color = "rainbow"
to_chat(user, "<span class='warning'>RNBW_ENGAGE</span>")
@@ -243,8 +243,8 @@
sharpness = IS_SHARP
//Most of the other special functions are handled in their own files. aka special snowflake code so kewl
/obj/item/weapon/melee/energy/blade/Initialize()
. = ..()
/obj/item/weapon/melee/energy/blade/Initialize()
. = ..()
spark_system = new /datum/effect_system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
@@ -296,7 +296,7 @@
/obj/item/weapon/lighter,
/obj/item/device/multitool,
/obj/item/weapon/reagent_containers/food/drinks/bottle/molotov,
/obj/item/weapon/c4,
/obj/item/weapon/grenade/plastic/c4,
)
/obj/item/weapon/storage/belt/grenade/full/PopulateContents()
new /obj/item/weapon/grenade/flashbang(src)
@@ -71,9 +71,9 @@
icon_state = "refill_clothes"
charges = list(31, 4, 4)// of 101 standard, 12 contraband, 10 premium(?)
init_charges = list(31, 4, 4)
/obj/item/weapon/vending_refill/medical
machine_name = "NanoMed"
icon_state = "refill_medical"
charges = list(26, 5, 3)// of 76 standard, 13 contraband, 8 premium
/obj/item/weapon/vending_refill/medical
machine_name = "NanoMed"
icon_state = "refill_medical"
charges = list(26, 5, 3)// of 76 standard, 13 contraband, 8 premium
init_charges = list(26, 5, 3)
+11 -11
View File
@@ -390,7 +390,7 @@
desc = "A chainsaw that has replaced your arm."
icon_state = "chainsaw_on"
item_state = "mounted_chainsaw"
flags = NODROP | ABSTRACT | DROPDEL
flags = NODROP | ABSTRACT | DROPDEL
w_class = WEIGHT_CLASS_HUGE
force = 21
throwforce = 0
@@ -400,17 +400,17 @@
attack_verb = list("sawed", "torn", "cut", "chopped", "diced")
hitsound = 'sound/weapons/chainsawhit.ogg'
/obj/item/weapon/mounted_chainsaw/Destroy()
var/obj/item/bodypart/part
/obj/item/weapon/mounted_chainsaw/Destroy()
var/obj/item/bodypart/part
new /obj/item/weapon/twohanded/required/chainsaw(get_turf(src))
if(iscarbon(loc))
var/mob/living/carbon/holder = loc
var/index = holder.get_held_index_of_item(src)
if(index)
part = holder.hand_bodyparts[index]
. = ..()
if(part)
part.drop_limb()
if(iscarbon(loc))
var/mob/living/carbon/holder = loc
var/index = holder.get_held_index_of_item(src)
if(index)
part = holder.hand_bodyparts[index]
. = ..()
if(part)
part.drop_limb()
/obj/item/weapon/statuebust
name = "bust"
+5 -5
View File
@@ -106,11 +106,11 @@ LINEN BINS
icon_state = "sheetrd"
item_color = "director"
// for Free Golems.
/obj/item/weapon/bedsheet/rd/royal_cape
name = "Royal Cape of the Liberator"
desc = "Majestic."
// for Free Golems.
/obj/item/weapon/bedsheet/rd/royal_cape
name = "Royal Cape of the Liberator"
desc = "Majestic."
/obj/item/weapon/bedsheet/medical
name = "medical blanket"
desc = "It's a sterilized* blanket commonly used in the Medbay. *Sterilization is voided if a virologist is present onboard the station."
@@ -11,7 +11,7 @@
else
new /obj/item/weapon/storage/backpack/satchel/cap(src)
new /obj/item/clothing/neck/cloak/cap(src)
new /obj/item/weapon/storage/daki(src)
new /obj/item/weapon/storage/daki(src)
new /obj/item/weapon/storage/backpack/dufflebag/captain(src)
new /obj/item/clothing/head/crown/fancy(src)
new /obj/item/clothing/suit/captunic(src)
+361 -361
View File
@@ -1,361 +1,361 @@
/obj/structure/displaycase
name = "display case"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "glassbox0"
desc = "A display case for prized possessions."
density = 1
anchored = 1
resistance_flags = ACID_PROOF
armor = list(melee = 30, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 0, rad = 0, fire = 70, acid = 100)
obj_integrity = 200
max_integrity = 200
integrity_failure = 50
var/obj/item/showpiece = null
var/alert = TRUE
var/open = FALSE
var/openable = TRUE
var/obj/item/weapon/electronics/airlock/electronics
var/start_showpiece_type = null //add type for items on display
/obj/structure/displaycase/Initialize()
. = ..()
if(start_showpiece_type)
showpiece = new start_showpiece_type (src)
update_icon()
/obj/structure/displaycase/Destroy()
if(electronics)
QDEL_NULL(electronics)
if(showpiece)
QDEL_NULL(showpiece)
return ..()
/obj/structure/displaycase/examine(mob/user)
..()
if(alert)
to_chat(user, "<span class='notice'>Hooked up with an anti-theft system.</span>")
if(showpiece)
to_chat(user, "<span class='notice'>There's [showpiece] inside.</span>")
/obj/structure/displaycase/proc/dump()
if (showpiece)
showpiece.forceMove(loc)
showpiece = null
/obj/structure/displaycase/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BRUTE)
playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
if(BURN)
playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
/obj/structure/displaycase/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
dump()
if(!disassembled)
new /obj/item/weapon/shard( src.loc )
trigger_alarm()
qdel(src)
/obj/structure/displaycase/obj_break(damage_flag)
if(!broken && !(flags & NODECONSTRUCT))
density = 0
broken = 1
new /obj/item/weapon/shard( src.loc )
playsound(src, "shatter", 70, 1)
update_icon()
trigger_alarm()
/obj/structure/displaycase/proc/trigger_alarm()
//Activate Anti-theft
if(alert)
var/area/alarmed = get_area(src)
alarmed.burglaralert(src)
playsound(src, 'sound/effects/alert.ogg', 50, 1)
/*
*/
/obj/structure/displaycase/proc/is_directional(atom/A)
try
getFlatIcon(A,defdir=4)
catch
return FALSE
return TRUE
/obj/structure/displaycase/proc/get_flat_icon_directional(atom/A)
//Get flatIcon even if dir is mismatched for directionless icons
//SLOW
var/icon/I
if(is_directional(A))
I = getFlatIcon(A)
else
var/old_dir = A.dir
A.setDir(2)
I = getFlatIcon(A)
A.setDir(old_dir)
return I
/obj/structure/displaycase/update_icon()
var/icon/I
if(open)
I = icon('icons/obj/stationobjs.dmi',"glassbox_open")
else
I = icon('icons/obj/stationobjs.dmi',"glassbox0")
if(broken)
I = icon('icons/obj/stationobjs.dmi',"glassboxb0")
if(showpiece)
var/icon/S = get_flat_icon_directional(showpiece)
S.Scale(17,17)
I.Blend(S,ICON_UNDERLAY,8,8)
src.icon = I
return
/obj/structure/displaycase/attackby(obj/item/weapon/W, mob/user, params)
if(W.GetID() && !broken && openable)
if(allowed(user))
to_chat(user, "<span class='notice'>You [open ? "close":"open"] the [src]</span>")
toggle_lock(user)
else
to_chat(user, "<span class='warning'>Access denied.</span>")
else if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent == INTENT_HELP && !broken)
var/obj/item/weapon/weldingtool/WT = W
if(obj_integrity < max_integrity && WT.remove_fuel(5, user))
to_chat(user, "<span class='notice'>You begin repairing [src].</span>")
playsound(loc, WT.usesound, 40, 1)
if(do_after(user, 40*W.toolspeed, target = src))
obj_integrity = max_integrity
playsound(loc, 'sound/items/Welder2.ogg', 50, 1)
update_icon()
to_chat(user, "<span class='notice'>You repair [src].</span>")
else
to_chat(user, "<span class='warning'>[src] is already in good condition!</span>")
return
else if(!alert && istype(W,/obj/item/weapon/crowbar) && openable) //Only applies to the lab cage and player made display cases
if(broken)
if(showpiece)
to_chat(user, "<span class='notice'>Remove the displayed object first.</span>")
else
to_chat(user, "<span class='notice'>You remove the destroyed case</span>")
qdel(src)
else
to_chat(user, "<span class='notice'>You start to [open ? "close":"open"] the [src]</span>")
if(do_after(user, 20*W.toolspeed, target = src))
to_chat(user, "<span class='notice'>You [open ? "close":"open"] the [src]</span>")
toggle_lock(user)
else if(open && !showpiece)
if(user.transferItemToLoc(W, src))
showpiece = W
to_chat(user, "<span class='notice'>You put [W] on display</span>")
update_icon()
else if(istype(W, /obj/item/stack/sheet/glass) && broken)
var/obj/item/stack/sheet/glass/G = W
if(G.get_amount() < 2)
to_chat(user, "<span class='warning'>You need two glass sheets to fix the case!</span>")
return
to_chat(user, "<span class='notice'>You start fixing [src]...</span>")
if(do_after(user, 20, target = src))
G.use(2)
broken = 0
obj_integrity = max_integrity
update_icon()
else
return ..()
/obj/structure/displaycase/proc/toggle_lock(mob/user)
open = !open
update_icon()
/obj/structure/displaycase/attack_paw(mob/user)
return src.attack_hand(user)
/obj/structure/displaycase/attack_hand(mob/user)
user.changeNext_move(CLICK_CD_MELEE)
if (showpiece && (broken || open))
to_chat(user, "<span class='notice'>You deactivate the hover field built into the case.</span>")
dump()
src.add_fingerprint(user)
update_icon()
return
else
//prevents remote "kicks" with TK
if (!Adjacent(user))
return
user.visible_message("<span class='danger'>[user] kicks the display case.</span>", null, null, COMBAT_MESSAGE_RANGE)
user.do_attack_animation(src, ATTACK_EFFECT_KICK)
take_damage(2)
/obj/structure/displaycase_chassis
anchored = 1
density = 0
name = "display case chassis"
desc = "wooden base of display case"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "glassbox_chassis"
var/obj/item/weapon/electronics/airlock/electronics
/obj/structure/displaycase_chassis/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/wrench)) //The player can only deconstruct the wooden frame
to_chat(user, "<span class='notice'>You start disassembling [src]...</span>")
playsound(src.loc, I.usesound, 50, 1)
if(do_after(user, 30*I.toolspeed, target = src))
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
new /obj/item/stack/sheet/mineral/wood(get_turf(src), 5)
qdel(src)
else if(istype(I, /obj/item/weapon/electronics/airlock))
to_chat(user, "<span class='notice'>You start installing the electronics into [src]...</span>")
playsound(src.loc, I.usesound, 50, 1)
if(do_after(user, 30, target = src) && user.transferItemToLoc(I,src))
electronics = I
to_chat(user, "<span class='notice'>You install the airlock electronics.</span>")
else if(istype(I, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = I
if(G.get_amount() < 10)
to_chat(user, "<span class='warning'>You need ten glass sheets to do this!</span>")
return
to_chat(user, "<span class='notice'>You start adding [G] to [src]...</span>")
if(do_after(user, 20, target = src))
G.use(10)
var/obj/structure/displaycase/display = new(src.loc)
if(electronics)
electronics.loc = display
display.electronics = electronics
if(electronics.one_access)
display.req_one_access = electronics.accesses
else
display.req_access = electronics.accesses
qdel(src)
else
return ..()
//The captains display case requiring specops ID access is intentional.
//The lab cage and captains display case do not spawn with electronics, which is why req_access is needed.
/obj/structure/displaycase/captain
alert = 1
start_showpiece_type = /obj/item/weapon/gun/energy/laser/captain
req_access = list(GLOB.access_cent_specops)
/obj/structure/displaycase/labcage
name = "lab cage"
desc = "A glass lab container for storing interesting creatures."
start_showpiece_type = /obj/item/clothing/mask/facehugger/lamarr
req_access = list(GLOB.access_rd)
/obj/structure/displaycase/trophy
name = "trophy display case"
desc = "Store your trophies of accomplishment in here, and they will stay forever."
var/trophy_message = ""
var/placer_key = ""
var/added_roundstart = TRUE
var/is_locked = TRUE
alert = TRUE
integrity_failure = 0
openable = FALSE
/obj/structure/displaycase/trophy/Initialize()
. = ..()
GLOB.trophy_cases += src
/obj/structure/displaycase/trophy/Destroy()
GLOB.trophy_cases -= src
return ..()
/obj/structure/displaycase/trophy/examine(mob/user)
..()
if(trophy_message)
to_chat(user, "The plaque reads:")
to_chat(user, trophy_message)
/obj/structure/displaycase/trophy/attackby(obj/item/weapon/W, mob/user, params)
if(!user.Adjacent(src)) //no TK museology
return
if(user.a_intent == INTENT_HARM)
return ..()
if(user.is_holding_item_of_type(/obj/item/key/displaycase))
if(added_roundstart)
is_locked = !is_locked
to_chat(user, "You [!is_locked ? "un" : ""]lock the case.")
else
to_chat(user, "<span class='danger'>The lock is stuck shut!</span>")
return
if(is_locked)
to_chat(user, "<span class='danger'>The case is shut tight with an old fashioned physical lock. Maybe you should ask the curator for the key?</span>")
return
if(!added_roundstart)
to_chat(user, "You've already put something new in this case.")
return
if(is_type_in_typecache(W, GLOB.blacklisted_cargo_types))
to_chat(user, "<span class='danger'>The case rejects the [W].</span>")
return
for(var/a in W.GetAllContents())
if(is_type_in_typecache(a, GLOB.blacklisted_cargo_types))
to_chat(user, "<span class='danger'>The case rejects the [W].</span>")
return
if(user.transferItemToLoc(W, src))
if(showpiece)
to_chat(user, "You press a button, and [showpiece] descends into the floor of the case.")
QDEL_NULL(showpiece)
to_chat(user, "You insert [W] into the case.")
showpiece = W
added_roundstart = FALSE
update_icon()
placer_key = user.ckey
trophy_message = W.desc //default value
var/chosen_plaque = stripped_input(user, "What would you like the plaque to say? Default value is item's description.", "Trophy Plaque")
if(chosen_plaque)
if(user.Adjacent(src))
trophy_message = chosen_plaque
to_chat(user, "You set the plaque's text.")
else
to_chat(user, "You are too far to set the plaque's text.")
SSpersistence.SaveTrophy(src)
return TRUE
else
to_chat(user, "<span class='warning'>\The [W] is stuck to your hand, you can't put it in the [src.name]!</span>")
return
/obj/structure/displaycase/trophy/dump()
if (showpiece)
if(added_roundstart)
visible_message("<span class='danger'>The [showpiece] crumbles to dust!</span>")
new /obj/effect/decal/cleanable/ash(loc)
QDEL_NULL(showpiece)
else
..()
/obj/item/key/displaycase
name = "display case key"
desc = "The key to the curator's display cases."
/obj/item/showpiece_dummy
name = "Cheap replica"
/obj/item/showpiece_dummy/Initialize(mapload, path)
. = ..()
var/obj/item/I = path
name = initial(I.name)
icon = initial(I.icon)
icon_state = initial(I.icon_state)
/obj/structure/displaycase
name = "display case"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "glassbox0"
desc = "A display case for prized possessions."
density = 1
anchored = 1
resistance_flags = ACID_PROOF
armor = list(melee = 30, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 0, rad = 0, fire = 70, acid = 100)
obj_integrity = 200
max_integrity = 200
integrity_failure = 50
var/obj/item/showpiece = null
var/alert = TRUE
var/open = FALSE
var/openable = TRUE
var/obj/item/weapon/electronics/airlock/electronics
var/start_showpiece_type = null //add type for items on display
/obj/structure/displaycase/Initialize()
. = ..()
if(start_showpiece_type)
showpiece = new start_showpiece_type (src)
update_icon()
/obj/structure/displaycase/Destroy()
if(electronics)
QDEL_NULL(electronics)
if(showpiece)
QDEL_NULL(showpiece)
return ..()
/obj/structure/displaycase/examine(mob/user)
..()
if(alert)
to_chat(user, "<span class='notice'>Hooked up with an anti-theft system.</span>")
if(showpiece)
to_chat(user, "<span class='notice'>There's [showpiece] inside.</span>")
/obj/structure/displaycase/proc/dump()
if (showpiece)
showpiece.forceMove(loc)
showpiece = null
/obj/structure/displaycase/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BRUTE)
playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
if(BURN)
playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
/obj/structure/displaycase/deconstruct(disassembled = TRUE)
if(!(flags & NODECONSTRUCT))
dump()
if(!disassembled)
new /obj/item/weapon/shard( src.loc )
trigger_alarm()
qdel(src)
/obj/structure/displaycase/obj_break(damage_flag)
if(!broken && !(flags & NODECONSTRUCT))
density = 0
broken = 1
new /obj/item/weapon/shard( src.loc )
playsound(src, "shatter", 70, 1)
update_icon()
trigger_alarm()
/obj/structure/displaycase/proc/trigger_alarm()
//Activate Anti-theft
if(alert)
var/area/alarmed = get_area(src)
alarmed.burglaralert(src)
playsound(src, 'sound/effects/alert.ogg', 50, 1)
/*
*/
/obj/structure/displaycase/proc/is_directional(atom/A)
try
getFlatIcon(A,defdir=4)
catch
return FALSE
return TRUE
/obj/structure/displaycase/proc/get_flat_icon_directional(atom/A)
//Get flatIcon even if dir is mismatched for directionless icons
//SLOW
var/icon/I
if(is_directional(A))
I = getFlatIcon(A)
else
var/old_dir = A.dir
A.setDir(2)
I = getFlatIcon(A)
A.setDir(old_dir)
return I
/obj/structure/displaycase/update_icon()
var/icon/I
if(open)
I = icon('icons/obj/stationobjs.dmi',"glassbox_open")
else
I = icon('icons/obj/stationobjs.dmi',"glassbox0")
if(broken)
I = icon('icons/obj/stationobjs.dmi',"glassboxb0")
if(showpiece)
var/icon/S = get_flat_icon_directional(showpiece)
S.Scale(17,17)
I.Blend(S,ICON_UNDERLAY,8,8)
src.icon = I
return
/obj/structure/displaycase/attackby(obj/item/weapon/W, mob/user, params)
if(W.GetID() && !broken && openable)
if(allowed(user))
to_chat(user, "<span class='notice'>You [open ? "close":"open"] the [src]</span>")
toggle_lock(user)
else
to_chat(user, "<span class='warning'>Access denied.</span>")
else if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent == INTENT_HELP && !broken)
var/obj/item/weapon/weldingtool/WT = W
if(obj_integrity < max_integrity && WT.remove_fuel(5, user))
to_chat(user, "<span class='notice'>You begin repairing [src].</span>")
playsound(loc, WT.usesound, 40, 1)
if(do_after(user, 40*W.toolspeed, target = src))
obj_integrity = max_integrity
playsound(loc, 'sound/items/Welder2.ogg', 50, 1)
update_icon()
to_chat(user, "<span class='notice'>You repair [src].</span>")
else
to_chat(user, "<span class='warning'>[src] is already in good condition!</span>")
return
else if(!alert && istype(W,/obj/item/weapon/crowbar) && openable) //Only applies to the lab cage and player made display cases
if(broken)
if(showpiece)
to_chat(user, "<span class='notice'>Remove the displayed object first.</span>")
else
to_chat(user, "<span class='notice'>You remove the destroyed case</span>")
qdel(src)
else
to_chat(user, "<span class='notice'>You start to [open ? "close":"open"] the [src]</span>")
if(do_after(user, 20*W.toolspeed, target = src))
to_chat(user, "<span class='notice'>You [open ? "close":"open"] the [src]</span>")
toggle_lock(user)
else if(open && !showpiece)
if(user.transferItemToLoc(W, src))
showpiece = W
to_chat(user, "<span class='notice'>You put [W] on display</span>")
update_icon()
else if(istype(W, /obj/item/stack/sheet/glass) && broken)
var/obj/item/stack/sheet/glass/G = W
if(G.get_amount() < 2)
to_chat(user, "<span class='warning'>You need two glass sheets to fix the case!</span>")
return
to_chat(user, "<span class='notice'>You start fixing [src]...</span>")
if(do_after(user, 20, target = src))
G.use(2)
broken = 0
obj_integrity = max_integrity
update_icon()
else
return ..()
/obj/structure/displaycase/proc/toggle_lock(mob/user)
open = !open
update_icon()
/obj/structure/displaycase/attack_paw(mob/user)
return src.attack_hand(user)
/obj/structure/displaycase/attack_hand(mob/user)
user.changeNext_move(CLICK_CD_MELEE)
if (showpiece && (broken || open))
to_chat(user, "<span class='notice'>You deactivate the hover field built into the case.</span>")
dump()
src.add_fingerprint(user)
update_icon()
return
else
//prevents remote "kicks" with TK
if (!Adjacent(user))
return
user.visible_message("<span class='danger'>[user] kicks the display case.</span>", null, null, COMBAT_MESSAGE_RANGE)
user.do_attack_animation(src, ATTACK_EFFECT_KICK)
take_damage(2)
/obj/structure/displaycase_chassis
anchored = 1
density = 0
name = "display case chassis"
desc = "wooden base of display case"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "glassbox_chassis"
var/obj/item/weapon/electronics/airlock/electronics
/obj/structure/displaycase_chassis/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/wrench)) //The player can only deconstruct the wooden frame
to_chat(user, "<span class='notice'>You start disassembling [src]...</span>")
playsound(src.loc, I.usesound, 50, 1)
if(do_after(user, 30*I.toolspeed, target = src))
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
new /obj/item/stack/sheet/mineral/wood(get_turf(src), 5)
qdel(src)
else if(istype(I, /obj/item/weapon/electronics/airlock))
to_chat(user, "<span class='notice'>You start installing the electronics into [src]...</span>")
playsound(src.loc, I.usesound, 50, 1)
if(do_after(user, 30, target = src) && user.transferItemToLoc(I,src))
electronics = I
to_chat(user, "<span class='notice'>You install the airlock electronics.</span>")
else if(istype(I, /obj/item/stack/sheet/glass))
var/obj/item/stack/sheet/glass/G = I
if(G.get_amount() < 10)
to_chat(user, "<span class='warning'>You need ten glass sheets to do this!</span>")
return
to_chat(user, "<span class='notice'>You start adding [G] to [src]...</span>")
if(do_after(user, 20, target = src))
G.use(10)
var/obj/structure/displaycase/display = new(src.loc)
if(electronics)
electronics.loc = display
display.electronics = electronics
if(electronics.one_access)
display.req_one_access = electronics.accesses
else
display.req_access = electronics.accesses
qdel(src)
else
return ..()
//The captains display case requiring specops ID access is intentional.
//The lab cage and captains display case do not spawn with electronics, which is why req_access is needed.
/obj/structure/displaycase/captain
alert = 1
start_showpiece_type = /obj/item/weapon/gun/energy/laser/captain
req_access = list(GLOB.access_cent_specops)
/obj/structure/displaycase/labcage
name = "lab cage"
desc = "A glass lab container for storing interesting creatures."
start_showpiece_type = /obj/item/clothing/mask/facehugger/lamarr
req_access = list(GLOB.access_rd)
/obj/structure/displaycase/trophy
name = "trophy display case"
desc = "Store your trophies of accomplishment in here, and they will stay forever."
var/trophy_message = ""
var/placer_key = ""
var/added_roundstart = TRUE
var/is_locked = TRUE
alert = TRUE
integrity_failure = 0
openable = FALSE
/obj/structure/displaycase/trophy/Initialize()
. = ..()
GLOB.trophy_cases += src
/obj/structure/displaycase/trophy/Destroy()
GLOB.trophy_cases -= src
return ..()
/obj/structure/displaycase/trophy/examine(mob/user)
..()
if(trophy_message)
to_chat(user, "The plaque reads:")
to_chat(user, trophy_message)
/obj/structure/displaycase/trophy/attackby(obj/item/weapon/W, mob/user, params)
if(!user.Adjacent(src)) //no TK museology
return
if(user.a_intent == INTENT_HARM)
return ..()
if(user.is_holding_item_of_type(/obj/item/key/displaycase))
if(added_roundstart)
is_locked = !is_locked
to_chat(user, "You [!is_locked ? "un" : ""]lock the case.")
else
to_chat(user, "<span class='danger'>The lock is stuck shut!</span>")
return
if(is_locked)
to_chat(user, "<span class='danger'>The case is shut tight with an old fashioned physical lock. Maybe you should ask the curator for the key?</span>")
return
if(!added_roundstart)
to_chat(user, "You've already put something new in this case.")
return
if(is_type_in_typecache(W, GLOB.blacklisted_cargo_types))
to_chat(user, "<span class='danger'>The case rejects the [W].</span>")
return
for(var/a in W.GetAllContents())
if(is_type_in_typecache(a, GLOB.blacklisted_cargo_types))
to_chat(user, "<span class='danger'>The case rejects the [W].</span>")
return
if(user.transferItemToLoc(W, src))
if(showpiece)
to_chat(user, "You press a button, and [showpiece] descends into the floor of the case.")
QDEL_NULL(showpiece)
to_chat(user, "You insert [W] into the case.")
showpiece = W
added_roundstart = FALSE
update_icon()
placer_key = user.ckey
trophy_message = W.desc //default value
var/chosen_plaque = stripped_input(user, "What would you like the plaque to say? Default value is item's description.", "Trophy Plaque")
if(chosen_plaque)
if(user.Adjacent(src))
trophy_message = chosen_plaque
to_chat(user, "You set the plaque's text.")
else
to_chat(user, "You are too far to set the plaque's text.")
SSpersistence.SaveTrophy(src)
return TRUE
else
to_chat(user, "<span class='warning'>\The [W] is stuck to your hand, you can't put it in the [src.name]!</span>")
return
/obj/structure/displaycase/trophy/dump()
if (showpiece)
if(added_roundstart)
visible_message("<span class='danger'>The [showpiece] crumbles to dust!</span>")
new /obj/effect/decal/cleanable/ash(loc)
QDEL_NULL(showpiece)
else
..()
/obj/item/key/displaycase
name = "display case key"
desc = "The key to the curator's display cases."
/obj/item/showpiece_dummy
name = "Cheap replica"
/obj/item/showpiece_dummy/Initialize(mapload, path)
. = ..()
var/obj/item/I = path
name = initial(I.name)
icon = initial(I.icon)
icon_state = initial(I.icon_state)
@@ -188,9 +188,9 @@
/obj/structure/mineral_door/transparent/plasma/attackby(obj/item/weapon/W, mob/user, params)
if(W.is_hot())
var/turf/T = get_turf(src)
message_admins("Plasma mineral door ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(T)]",0,1)
log_game("Plasma mineral door ignited by [key_name(user)] in [COORD(T)]")
var/turf/T = get_turf(src)
message_admins("Plasma mineral door ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(T)]",0,1)
log_game("Plasma mineral door ignited by [key_name(user)] in [COORD(T)]")
TemperatureAct()
else
return ..()
+5 -5
View File
@@ -71,13 +71,13 @@
computerid = bancid
ip = banip
var/datum/DBQuery/query_add_ban_get_ckey = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
if(!query_add_ban_get_ckey.warn_execute())
var/datum/DBQuery/query_add_ban_get_ckey = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[ckey]'")
if(!query_add_ban_get_ckey.warn_execute())
return
if(!query_add_ban_get_ckey.NextRow())
if(!query_add_ban_get_ckey.NextRow())
if(!banned_mob || (banned_mob && !IsGuestKey(banned_mob.key)))
if(alert(usr, "[ckey] has not been seen before, are you sure you want to create a ban for them?", "Unknown ckey", "Yes", "No", "Cancel") != "Yes")
return
if(alert(usr, "[ckey] has not been seen before, are you sure you want to create a ban for them?", "Unknown ckey", "Yes", "No", "Cancel") != "Yes")
return
var/a_ckey
var/a_computerid
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -1,21 +1,21 @@
atom/proc/investigate_log(message, subject)
if(!message || !subject)
return
var/F = file("[GLOB.log_directory]/[subject].html")
F << "<small>[time_stamp()] \ref[src] ([x],[y],[z])</small> || [src] [message]<br>"
/client/proc/investigate_show( subject in list("hrefs","notes, memos, watchlist","singulo","wires","telesci", "gravity", "records", "cargo", "supermatter", "atmos", "experimentor", "botany") )
set name = "Investigate"
set category = "Admin"
if(!holder)
return
switch(subject)
if("notes, memos, watchlist")
browse_messages()
else
var/F = file("[GLOB.log_directory]/[subject].html")
if(!fexists(F))
to_chat(src, "<span class='danger'>No [subject] logfile was found.</span>")
return
atom/proc/investigate_log(message, subject)
if(!message || !subject)
return
var/F = file("[GLOB.log_directory]/[subject].html")
F << "<small>[time_stamp()] \ref[src] ([x],[y],[z])</small> || [src] [message]<br>"
/client/proc/investigate_show( subject in list("hrefs","notes, memos, watchlist","singulo","wires","telesci", "gravity", "records", "cargo", "supermatter", "atmos", "experimentor", "botany") )
set name = "Investigate"
set category = "Admin"
if(!holder)
return
switch(subject)
if("notes, memos, watchlist")
browse_messages()
else
var/F = file("[GLOB.log_directory]/[subject].html")
if(!fexists(F))
to_chat(src, "<span class='danger'>No [subject] logfile was found.</span>")
return
src << browse(F,"window=investigate[subject];size=800x300")
+2 -2
View File
@@ -93,10 +93,10 @@
if(href_list["time"])
timing = text2num(href_list["time"])
if(timing && istype(holder, /obj/item/device/transfer_valve))
var/timer_message = "[ADMIN_LOOKUPFLW(usr)] activated [src] attachment on [holder]."
var/timer_message = "[ADMIN_LOOKUPFLW(usr)] activated [src] attachment on [holder]."
message_admins(timer_message)
GLOB.bombers += timer_message
log_game("[key_name(usr)] activated [src] attachment on [holder]")
log_game("[key_name(usr)] activated [src] attachment on [holder]")
update_icon()
if(href_list["repeat"])
loop = text2num(href_list["repeat"])
@@ -16,11 +16,11 @@
armor = list(melee = 0, bullet = 0, laser = 0, energy = 100, bomb = 0, bio = 100, rad = 100, fire = 40, acid = 0)
/obj/machinery/meter/Initialize(mapload)
. = ..()
/obj/machinery/meter/Initialize(mapload)
. = ..()
SSair.atmos_machinery += src
if (mapload && !target)
target = locate(/obj/machinery/atmospherics/pipe) in loc
if (mapload && !target)
target = locate(/obj/machinery/atmospherics/pipe) in loc
/obj/machinery/meter/Destroy()
SSair.atmos_machinery -= src
@@ -103,9 +103,9 @@
var/plasma = air_contents.gases["plasma"]
var/n2o = air_contents.gases["n2o"]
if(n2o || plasma)
var/area/A = get_area(src)
message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [A][ADMIN_JMP(src)]")
log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [A][COORD(src)]")
var/area/A = get_area(src)
message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [A][ADMIN_JMP(src)]")
log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [A][COORD(src)]")
. = TRUE
if("direction")
if(direction == PUMP_OUT)
+1 -1
View File
@@ -227,7 +227,7 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
if(check_exile_implant(C))
say("Rejecting [AM]: Exile implant detected in contained lifeform.")
return
if(AM.has_buckled_mobs())
if(AM.has_buckled_mobs())
for(var/mob/living/carbon/C in AM.buckled_mobs)
if(check_exile_implant(C))
say("Rejecting [AM]: Exile implant detected in close proximity lifeform.")
@@ -64,18 +64,18 @@
next_check = world.time + cooldown
/obj/structure/academy_wizard_spawner/proc/give_control()
set waitfor = FALSE
set waitfor = FALSE
if(!current_wizard)
return
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as Wizard Academy Defender?", "wizard", null, be_special_flag = ROLE_WIZARD, M = current_wizard)
var/mob/dead/observer/chosen = null
if(candidates.len)
chosen = pick(candidates)
message_admins("[key_name_admin(chosen)] was spawned as Wizard Academy Defender")
current_wizard.ghostize() // on the off chance braindead defender gets back in
current_wizard.key = chosen.key
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as Wizard Academy Defender?", "wizard", null, be_special_flag = ROLE_WIZARD, M = current_wizard)
var/mob/dead/observer/chosen = null
if(candidates.len)
chosen = pick(candidates)
message_admins("[key_name_admin(chosen)] was spawned as Wizard Academy Defender")
current_wizard.ghostize() // on the off chance braindead defender gets back in
current_wizard.key = chosen.key
/obj/structure/academy_wizard_spawner/proc/summon_wizard()
var/turf/T = src.loc
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -161,9 +161,9 @@
/obj/item/clothing/obj_break(damage_flag)
if(!damaged_clothes)
update_clothes_damaged_state(TRUE)
if(ismob(loc)) //It's not important enough to warrant a message if nobody's wearing it
var/mob/M = loc
M.visible_message("<span class='warning'>[M]'s [name] starts to fall apart!", "<span class='warning'>Your [name] starts to fall apart!")
if(ismob(loc)) //It's not important enough to warrant a message if nobody's wearing it
var/mob/M = loc
M.visible_message("<span class='warning'>[M]'s [name] starts to fall apart!", "<span class='warning'>Your [name] starts to fall apart!")
/obj/item/clothing/proc/update_clothes_damaged_state(damaging = TRUE)
var/index = "\ref[initial(icon)]-[initial(icon_state)]"
+1 -1
View File
@@ -30,7 +30,7 @@
/obj/item/clothing/head/collectable/paper
name = "collectable paper hat"
desc = "What looks like an ordinary paper hat is actually a rare and valuable collector's edition paper hat. Keep away from water, fire, and Curators."
desc = "What looks like an ordinary paper hat is actually a rare and valuable collector's edition paper hat. Keep away from water, fire, and Curators."
icon_state = "paper"
dog_fashion = /datum/dog_fashion/head
+1 -1
View File
@@ -158,5 +158,5 @@
name = "treasure hunter's fedora"
desc = "You got red text today kid, but it doesn't mean you have to like it."
icon_state = "curator"
armor = list(melee = 25, bullet = 5, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0, fire = 30, acid = 50)
armor = list(melee = 25, bullet = 5, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0, fire = 30, acid = 50)
pockets = /obj/item/weapon/storage/internal/pocket/small
+1 -1
View File
@@ -182,7 +182,7 @@
item_state = "curator"
blood_overlay_type = "coat"
body_parts_covered = CHEST|ARMS
allowed = list(/obj/item/weapon/tank/internals, /obj/item/weapon/melee/curator_whip)
allowed = list(/obj/item/weapon/tank/internals, /obj/item/weapon/melee/curator_whip)
armor = list(melee = 25, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 45)
cold_protection = CHEST|ARMS
heat_protection = CHEST|ARMS
+4 -4
View File
@@ -13,8 +13,8 @@
var/scanning = 0
var/list/log = list()
origin_tech = "engineering=4;biotech=2;programming=5"
var/range = 8
var/view_check = TRUE
var/range = 8
var/view_check = TRUE
/obj/item/device/detective_scanner/attack_self(mob/user)
if(log.len && !scanning)
@@ -45,7 +45,7 @@
log = list()
scanning = 0
/obj/item/device/detective_scanner/afterattack(atom/A, mob/user, params)
/obj/item/device/detective_scanner/afterattack(atom/A, mob/user, params)
scan(A, user)
return FALSE
@@ -53,7 +53,7 @@
set waitfor = 0
if(!scanning)
// Can remotely scan objects and mobs.
if((get_dist(A, user) > range) || (!(A in view(range, user)) && view_check) || (loc != user))
if((get_dist(A, user) > range) || (!(A in view(range, user)) && view_check) || (loc != user))
return
scanning = 1
+1 -1
View File
@@ -459,7 +459,7 @@ GLOBAL_VAR_CONST(access_away_generic4, 208)
/proc/get_all_jobs()
return list("Assistant", "Captain", "Head of Personnel", "Bartender", "Cook", "Botanist", "Quartermaster", "Cargo Technician",
"Shaft Miner", "Clown", "Mime", "Janitor", "Curator", "Lawyer", "Chaplain", "Chief Engineer", "Station Engineer",
"Shaft Miner", "Clown", "Mime", "Janitor", "Curator", "Lawyer", "Chaplain", "Chief Engineer", "Station Engineer",
"Atmospheric Technician", "Chief Medical Officer", "Medical Doctor", "Chemist", "Geneticist", "Virologist",
"Research Director", "Scientist", "Roboticist", "Head of Security", "Warden", "Detective", "Security Officer")
+1 -1
View File
@@ -39,7 +39,7 @@ GLOBAL_LIST_INIT(civilian_positions, list(
"Botanist",
"Cook",
"Janitor",
"Curator",
"Curator",
"Lawyer",
"Chaplain",
"Clown",
+13 -13
View File
@@ -1,15 +1,15 @@
diff a/code/modules/language/language.dm b/code/modules/language/language.dm (rejected hunks)
@@ -16,10 +16,10 @@
// If key is null, then the language isn't real or learnable.
var/flags // Various language flags.
var/list/syllables // Used when scrambling text for a non-speaker.
- var/list/sentence_chance = 5 // Likelihood of making a new sentence after each syllable.
- var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string
+ var/sentence_chance = 5 // Likelihood of making a new sentence after each syllable.
+ var/space_chance = 55 // Likelihood of getting a space in the random scramble string
var/list/spans = list()
- var/static/list/scramble_cache = list()
+ var/list/scramble_cache = list()
var/default_priority = 0 // the language that an atom knows with the highest "default_priority" is selected by default.
// if you are seeing someone speak popcorn language, then something is wrong.
// If key is null, then the language isn't real or learnable.
var/flags // Various language flags.
var/list/syllables // Used when scrambling text for a non-speaker.
- var/list/sentence_chance = 5 // Likelihood of making a new sentence after each syllable.
- var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string
+ var/sentence_chance = 5 // Likelihood of making a new sentence after each syllable.
+ var/space_chance = 55 // Likelihood of getting a space in the random scramble string
var/list/spans = list()
- var/static/list/scramble_cache = list()
+ var/list/scramble_cache = list()
var/default_priority = 0 // the language that an atom knows with the highest "default_priority" is selected by default.
// if you are seeing someone speak popcorn language, then something is wrong.
+4 -4
View File
@@ -22,7 +22,7 @@
------------
A place for the crew to go, relax, and enjoy a good book.
Aspiring authors can even self publish and, if they're lucky
convince the on-staff Curator to submit it to the Archives
convince the on-staff Curator to submit it to the Archives
to be chronicled in history forever - some say even persisting
through alternate dimensions.
@@ -49,12 +49,12 @@
// Ideas for the future
// ---------------------
// - Visitor's computer should be able to search the current in-round library inventory (that the Curator has stocked and checked in)
// - Visitor's computer should be able to search the current in-round library inventory (that the Curator has stocked and checked in)
// -- Give computer other features like an Instant Messenger application, or the ability to edit, save, and print documents.
// - Admin interface directly tied to the Archive DB. Right now there's no way to delete uploaded books in-game.
// -- If this gets implemented, allow Curators to "tag" or "suggest" books to be deleted. The DB ID of the tagged books gets saved to a text file (or another table in the DB maybe?).
// -- If this gets implemented, allow Curators to "tag" or "suggest" books to be deleted. The DB ID of the tagged books gets saved to a text file (or another table in the DB maybe?).
// The admin interface would automatically take these IDs and SELECT them all from the DB to be displayed along with a Delete link to drop the row from the table.
// - When the game sets up and the round begins, have it automatically pick random books from the DB to populate the library with. Even if the Curator is a useless fuck there are at least a few books around.
// - When the game sets up and the round begins, have it automatically pick random books from the DB to populate the library with. Even if the Curator is a useless fuck there are at least a few books around.
// - Allow books to be "hollowed out" like the Chaplain's Bible, allowing you to store one pocket-sized item inside.
// - Make books/book cases burn when exposed to flame.
// - Make book binder hackable.
+3 -3
View File
@@ -20,7 +20,7 @@
if(ruins && ruins.len)
ruin = ruins[pick(ruins)]
else
log_world("Ruin loader had no ruins to pick from with [budget] left to spend.")
log_world("Ruin loader had no ruins to pick from with [budget] left to spend.")
break
// Can we afford it
if(ruin.cost > budget)
@@ -47,7 +47,7 @@
if(!valid)
continue
log_world("Ruin \"[ruin.name]\" placed at ([T.x], [T.y], [T.z])")
log_world("Ruin \"[ruin.name]\" placed at ([T.x], [T.y], [T.z])")
var/obj/effect/ruin_loader/R = new /obj/effect/ruin_loader(T)
R.Load(ruins,ruin)
@@ -57,7 +57,7 @@
break
if(!overall_sanity)
log_world("Ruin loader gave up with [budget] left to spend.")
log_world("Ruin loader gave up with [budget] left to spend.")
/obj/effect/ruin_loader
+25 -25
View File
@@ -1,25 +1,25 @@
/mob/dead/observer/say(message)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
if (!message)
return
log_say("Ghost/[src.key] : [message]")
. = src.say_dead(message)
/mob/dead/observer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
var/atom/movable/to_follow = speaker
if(radio_freq)
var/atom/movable/virtualspeaker/V = speaker
if(isAI(V.source))
var/mob/living/silicon/ai/S = V.source
to_follow = S.eyeobj
else
to_follow = V.source
var/link = FOLLOW_LINK(src, to_follow)
// Recompose the message, because it's scrambled by default
message = compose_message(speaker, message_language, raw_message, radio_freq, spans)
to_chat(src, "[link] [message]")
/mob/dead/observer/say(message)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
if (!message)
return
log_say("Ghost/[src.key] : [message]")
. = src.say_dead(message)
/mob/dead/observer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
var/atom/movable/to_follow = speaker
if(radio_freq)
var/atom/movable/virtualspeaker/V = speaker
if(isAI(V.source))
var/mob/living/silicon/ai/S = V.source
to_follow = S.eyeobj
else
to_follow = V.source
var/link = FOLLOW_LINK(src, to_follow)
// Recompose the message, because it's scrambled by default
message = compose_message(speaker, message_language, raw_message, radio_freq, spans)
to_chat(src, "[link] [message]")
@@ -1,134 +1,134 @@
// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability
// It functions almost identically (see code/datums/diseases/alien_embryo.dm)
/obj/item/organ/body_egg/alien_embryo
name = "alien embryo"
icon = 'icons/mob/alien.dmi'
icon_state = "larva0_dead"
var/stage = 0
var/bursting = FALSE
/obj/item/organ/body_egg/alien_embryo/on_find(mob/living/finder)
..()
if(stage < 4)
to_chat(finder, "It's small and weak, barely the size of a foetus.")
else
to_chat(finder, "It's grown quite large, and writhes slightly as you look at it.")
if(prob(10))
AttemptGrow(0)
/obj/item/organ/body_egg/alien_embryo/prepare_eat()
var/obj/S = ..()
S.reagents.add_reagent("sacid", 10)
return S
/obj/item/organ/body_egg/alien_embryo/on_life()
switch(stage)
if(2, 3)
if(prob(2))
owner.emote("sneeze")
if(prob(2))
owner.emote("cough")
if(prob(2))
to_chat(owner, "<span class='danger'>Your throat feels sore.</span>")
if(prob(2))
to_chat(owner, "<span class='danger'>Mucous runs down the back of your throat.</span>")
if(4)
if(prob(2))
owner.emote("sneeze")
if(prob(2))
owner.emote("cough")
if(prob(4))
to_chat(owner, "<span class='danger'>Your muscles ache.</span>")
if(prob(20))
owner.take_bodypart_damage(1)
if(prob(4))
to_chat(owner, "<span class='danger'>Your stomach hurts.</span>")
if(prob(20))
owner.adjustToxLoss(1)
if(5)
to_chat(owner, "<span class='danger'>You feel something tearing its way out of your stomach...</span>")
owner.adjustToxLoss(10)
/obj/item/organ/body_egg/alien_embryo/egg_process()
if(stage < 5 && prob(3))
stage++
INVOKE_ASYNC(src, .proc/RefreshInfectionImage)
if(stage == 5 && prob(50))
for(var/datum/surgery/S in owner.surgeries)
if(S.location == "chest" && istype(S.get_surgery_step(), /datum/surgery_step/manipulate_organs))
AttemptGrow(0)
return
AttemptGrow()
/obj/item/organ/body_egg/alien_embryo/proc/AttemptGrow(gib_on_success=TRUE)
if(!owner || bursting)
return
bursting = TRUE
var/list/candidates = pollGhostCandidates("Do you want to play as an alien larva that will burst out of [owner]?", ROLE_ALIEN, null, ROLE_ALIEN, 100, POLL_IGNORE_ALIEN_LARVA)
if(QDELETED(src) || QDELETED(owner))
return
if(!candidates.len || !owner)
bursting = FALSE
stage = 4
return
var/mob/dead/observer/ghost = pick(candidates)
var/mutable_appearance/overlay = mutable_appearance('icons/mob/alien.dmi', "burst_lie")
owner.add_overlay(overlay)
var/atom/xeno_loc = get_turf(owner)
var/mob/living/carbon/alien/larva/new_xeno = new(xeno_loc)
new_xeno.key = ghost.key
new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100) //To get the player's attention
new_xeno.canmove = 0 //so we don't move during the bursting animation
new_xeno.notransform = 1
new_xeno.invisibility = INVISIBILITY_MAXIMUM
sleep(6)
if(QDELETED(src) || QDELETED(owner))
return
if(new_xeno)
new_xeno.canmove = 1
new_xeno.notransform = 0
new_xeno.invisibility = 0
if(gib_on_success)
new_xeno.visible_message("<span class='danger'>[new_xeno] bursts out of [owner] in a shower of gore!</span>", "<span class='userdanger'>You exit [owner], your previous host.</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
owner.gib(TRUE)
else
new_xeno.visible_message("<span class='danger'>[new_xeno] wriggles out of [owner]!</span>", "<span class='userdanger'>You exit [owner], your previous host.</span>")
owner.adjustBruteLoss(40)
owner.cut_overlay(overlay)
qdel(src)
/*----------------------------------------
Proc: AddInfectionImages(C)
Des: Adds the infection image to all aliens for this embryo
----------------------------------------*/
/obj/item/organ/body_egg/alien_embryo/AddInfectionImages()
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
if(alien.client)
var/I = image('icons/mob/alien.dmi', loc = owner, icon_state = "infected[stage]")
alien.client.images += I
/*----------------------------------------
Proc: RemoveInfectionImage(C)
Des: Removes all images from the mob infected by this embryo
----------------------------------------*/
/obj/item/organ/body_egg/alien_embryo/RemoveInfectionImages()
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
if(alien.client)
for(var/image/I in alien.client.images)
if(dd_hasprefix_case(I.icon_state, "infected") && I.loc == owner)
qdel(I)
// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability
// It functions almost identically (see code/datums/diseases/alien_embryo.dm)
/obj/item/organ/body_egg/alien_embryo
name = "alien embryo"
icon = 'icons/mob/alien.dmi'
icon_state = "larva0_dead"
var/stage = 0
var/bursting = FALSE
/obj/item/organ/body_egg/alien_embryo/on_find(mob/living/finder)
..()
if(stage < 4)
to_chat(finder, "It's small and weak, barely the size of a foetus.")
else
to_chat(finder, "It's grown quite large, and writhes slightly as you look at it.")
if(prob(10))
AttemptGrow(0)
/obj/item/organ/body_egg/alien_embryo/prepare_eat()
var/obj/S = ..()
S.reagents.add_reagent("sacid", 10)
return S
/obj/item/organ/body_egg/alien_embryo/on_life()
switch(stage)
if(2, 3)
if(prob(2))
owner.emote("sneeze")
if(prob(2))
owner.emote("cough")
if(prob(2))
to_chat(owner, "<span class='danger'>Your throat feels sore.</span>")
if(prob(2))
to_chat(owner, "<span class='danger'>Mucous runs down the back of your throat.</span>")
if(4)
if(prob(2))
owner.emote("sneeze")
if(prob(2))
owner.emote("cough")
if(prob(4))
to_chat(owner, "<span class='danger'>Your muscles ache.</span>")
if(prob(20))
owner.take_bodypart_damage(1)
if(prob(4))
to_chat(owner, "<span class='danger'>Your stomach hurts.</span>")
if(prob(20))
owner.adjustToxLoss(1)
if(5)
to_chat(owner, "<span class='danger'>You feel something tearing its way out of your stomach...</span>")
owner.adjustToxLoss(10)
/obj/item/organ/body_egg/alien_embryo/egg_process()
if(stage < 5 && prob(3))
stage++
INVOKE_ASYNC(src, .proc/RefreshInfectionImage)
if(stage == 5 && prob(50))
for(var/datum/surgery/S in owner.surgeries)
if(S.location == "chest" && istype(S.get_surgery_step(), /datum/surgery_step/manipulate_organs))
AttemptGrow(0)
return
AttemptGrow()
/obj/item/organ/body_egg/alien_embryo/proc/AttemptGrow(gib_on_success=TRUE)
if(!owner || bursting)
return
bursting = TRUE
var/list/candidates = pollGhostCandidates("Do you want to play as an alien larva that will burst out of [owner]?", ROLE_ALIEN, null, ROLE_ALIEN, 100, POLL_IGNORE_ALIEN_LARVA)
if(QDELETED(src) || QDELETED(owner))
return
if(!candidates.len || !owner)
bursting = FALSE
stage = 4
return
var/mob/dead/observer/ghost = pick(candidates)
var/mutable_appearance/overlay = mutable_appearance('icons/mob/alien.dmi', "burst_lie")
owner.add_overlay(overlay)
var/atom/xeno_loc = get_turf(owner)
var/mob/living/carbon/alien/larva/new_xeno = new(xeno_loc)
new_xeno.key = ghost.key
new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100) //To get the player's attention
new_xeno.canmove = 0 //so we don't move during the bursting animation
new_xeno.notransform = 1
new_xeno.invisibility = INVISIBILITY_MAXIMUM
sleep(6)
if(QDELETED(src) || QDELETED(owner))
return
if(new_xeno)
new_xeno.canmove = 1
new_xeno.notransform = 0
new_xeno.invisibility = 0
if(gib_on_success)
new_xeno.visible_message("<span class='danger'>[new_xeno] bursts out of [owner] in a shower of gore!</span>", "<span class='userdanger'>You exit [owner], your previous host.</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
owner.gib(TRUE)
else
new_xeno.visible_message("<span class='danger'>[new_xeno] wriggles out of [owner]!</span>", "<span class='userdanger'>You exit [owner], your previous host.</span>")
owner.adjustBruteLoss(40)
owner.cut_overlay(overlay)
qdel(src)
/*----------------------------------------
Proc: AddInfectionImages(C)
Des: Adds the infection image to all aliens for this embryo
----------------------------------------*/
/obj/item/organ/body_egg/alien_embryo/AddInfectionImages()
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
if(alien.client)
var/I = image('icons/mob/alien.dmi', loc = owner, icon_state = "infected[stage]")
alien.client.images += I
/*----------------------------------------
Proc: RemoveInfectionImage(C)
Des: Removes all images from the mob infected by this embryo
----------------------------------------*/
/obj/item/organ/body_egg/alien_embryo/RemoveInfectionImages()
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
if(alien.client)
for(var/image/I in alien.client.images)
if(dd_hasprefix_case(I.icon_state, "infected") && I.loc == owner)
qdel(I)
@@ -171,8 +171,8 @@
dna.species.mutant_bodyparts -= "wingsopen"
dna.species.mutant_bodyparts |= "wings"
update_body()
if(isturf(loc))
var/turf/T = loc
T.Entered(src)
if(isturf(loc))
var/turf/T = loc
T.Entered(src)
//Ayy lmao
@@ -48,4 +48,4 @@
var/datum/personal_crafting/handcrafting
can_buckle = TRUE
buckle_lying = FALSE
can_ride_typecache = list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot)
can_ride_typecache = list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot)
@@ -142,12 +142,12 @@
return not_handled //For future deeper overrides
/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE)
var/index = get_held_index_of_item(I)
var/index = get_held_index_of_item(I)
. = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should.
if(!. || !I)
return
if(index && dna.species.mutanthands)
put_in_hand(new dna.species.mutanthands(), index)
if(index && dna.species.mutanthands)
put_in_hand(new dna.species.mutanthands(), index)
if(I == wear_suit)
if(s_store && invdrop)
dropItemToGround(s_store, TRUE) //It makes no sense for your suit storage to stay on you if you drop your suit.
@@ -2,7 +2,7 @@
name = "Flyperson"
id = "fly"
say_mod = "buzzes"
mutanttongue = /obj/item/organ/tongue/fly
mutanttongue = /obj/item/organ/tongue/fly
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/fly
/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
File diff suppressed because it is too large Load Diff
@@ -17,9 +17,9 @@
skinned_type = /obj/item/stack/sheet/animalhide/lizard
exotic_bloodtype = "L"
/datum/species/lizard/after_equip_job(datum/job/J, mob/living/carbon/human/H)
H.grant_language(/datum/language/draconic)
/datum/species/lizard/after_equip_job(datum/job/J, mob/living/carbon/human/H)
H.grant_language(/datum/language/draconic)
/datum/species/lizard/random_name(gender,unique,lastname)
if(unique)
return random_unique_lizard_name(gender)
@@ -13,11 +13,11 @@
name = "Infectious Zombie"
id = "memezombies"
limbs_id = "zombie"
mutanthands = /obj/item/zombie_hand
mutanthands = /obj/item/zombie_hand
no_equip = list(slot_wear_mask, slot_head)
armor = 20 // 120 damage to KO a zombie, which kills it
speedmod = 2
mutanteyes = /obj/item/organ/eyes/night_vision/zombie
mutanteyes = /obj/item/organ/eyes/night_vision/zombie
/datum/species/zombie/infectious/spec_life(mob/living/carbon/C)
. = ..()
@@ -30,14 +30,14 @@
/datum/species/zombie/infectious/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
// Deal with the source of this zombie corruption
// Infection organ needs to be handled separately from mutant_organs
// because it persists through species transitions
// Deal with the source of this zombie corruption
// Infection organ needs to be handled separately from mutant_organs
// because it persists through species transitions
var/obj/item/organ/zombie_infection/infection
infection = C.getorganslot("zombie_infection")
if(!infection)
infection = new()
infection.Insert(C)
infection = new()
infection.Insert(C)
// Your skin falls off
+1 -1
View File
@@ -49,7 +49,7 @@
timeofdeath = world.time
tod = worldtime2text()
var/turf/T = get_turf(src)
var/area/A = get_area(T)
var/area/A = get_area(T)
if(mind && mind.name && mind.active && (!(T.flags & NO_DEATHRATTLE)))
var/rendered = "<span class='deadsay'><b>[mind.name]</b> has died at <b>[A.name]</b>.</span>"
deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE)
+1 -1
View File
@@ -6,7 +6,7 @@
verb_ask = "queries"
verb_exclaim = "declares"
verb_yell = "alarms"
initial_language_holder = /datum/language_holder/synthetic
initial_language_holder = /datum/language_holder/synthetic
see_in_dark = 8
bubble_icon = "machine"
weather_immunities = list("ash")
@@ -20,7 +20,7 @@
verb_ask = "queries"
verb_exclaim = "declares"
verb_yell = "alarms"
initial_language_holder = /datum/language_holder/synthetic
initial_language_holder = /datum/language_holder/synthetic
bubble_icon = "machine"
faction = list("neutral", "silicon" , "turret")
@@ -287,13 +287,13 @@
to_chat(user, "<span class='warning'>The welder must be on for this task!</span>")
else
if(W.force) //if force is non-zero
do_sparks(5, TRUE, src)
do_sparks(5, TRUE, src)
..()
/mob/living/simple_animal/bot/bullet_act(obj/item/projectile/Proj)
if(Proj && (Proj.damage_type == BRUTE || Proj.damage_type == BURN))
if(prob(75) && Proj.damage > 0)
do_sparks(5, TRUE, src)
do_sparks(5, TRUE, src)
return ..()
/mob/living/simple_animal/bot/emp_act(severity)
@@ -397,7 +397,7 @@ Auto Patrol: []"},
if(prob(50))
new /obj/item/bodypart/l_arm/robot(Tsec)
do_sparks(3, TRUE, src)
do_sparks(3, TRUE, src)
new /obj/effect/decal/cleanable/oil(loc)
..()
@@ -216,7 +216,7 @@
if(change)
if(change > 0)
if(M && stat != DEAD)
new /obj/effect/overlay/temp/heart(loc)
new /obj/effect/overlay/temp/heart(loc)
emote("me", 1, "purrs!")
else
if(M && stat != DEAD)
@@ -51,12 +51,12 @@
src.visible_message("<span class='notice'>[src] calms down.</span>")
if(stat == CONSCIOUS)
udder.generateMilk()
eat_plants()
eat_plants()
if(!pulledby)
for(var/direction in shuffle(list(1,2,4,8,5,6,9,10)))
var/step = get_step(src, direction)
if(step)
if(locate(/obj/structure/spacevine) in step || locate(/obj/structure/glowshroom) in step)
if(locate(/obj/structure/spacevine) in step || locate(/obj/structure/glowshroom) in step)
Move(step, get_dir(src, step))
/mob/living/simple_animal/hostile/retaliate/goat/Retaliate()
@@ -66,22 +66,22 @@
/mob/living/simple_animal/hostile/retaliate/goat/Move()
..()
if(!stat)
eat_plants()
/mob/living/simple_animal/hostile/retaliate/goat/proc/eat_plants()
var/eaten = FALSE
var/obj/structure/spacevine/SV = locate(/obj/structure/spacevine) in loc
if(SV)
SV.eat(src)
eaten = TRUE
var/obj/structure/glowshroom/GS = locate(/obj/structure/glowshroom) in loc
if(GS)
qdel(GS)
eaten = TRUE
if(eaten && prob(10))
say("Nom")
eat_plants()
/mob/living/simple_animal/hostile/retaliate/goat/proc/eat_plants()
var/eaten = FALSE
var/obj/structure/spacevine/SV = locate(/obj/structure/spacevine) in loc
if(SV)
SV.eat(src)
eaten = TRUE
var/obj/structure/glowshroom/GS = locate(/obj/structure/glowshroom) in loc
if(GS)
qdel(GS)
eaten = TRUE
if(eaten && prob(10))
say("Nom")
/mob/living/simple_animal/hostile/retaliate/goat/attackby(obj/item/O, mob/user, params)
if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass))
@@ -311,7 +311,7 @@
name = "udder"
/obj/item/udder/Initialize()
create_reagents(50)
create_reagents(50)
reagents.add_reagent("milk", 20)
..()
@@ -53,5 +53,5 @@
ranged = 1
/mob/living/simple_animal/hostile/hivebot/death(gibbed)
do_sparks(3, TRUE, src)
do_sparks(3, TRUE, src)
..(1)
@@ -28,8 +28,8 @@
status_flags = CANPUSH
movement_type = FLYING
loot = list(/obj/item/weapon/ectoplasm)
del_on_death = TRUE
initial_language_holder = /datum/language_holder/construct
del_on_death = TRUE
initial_language_holder = /datum/language_holder/construct
/mob/living/simple_animal/shade/death()
deathmessage = "lets out a contented sigh as [p_their()] form unwinds."
+8 -8
View File
@@ -12,20 +12,20 @@
slot_flags = SLOT_BELT
resistance_flags = FLAMMABLE
/obj/item/weapon/clipboard/Initialize()
/obj/item/weapon/clipboard/Initialize()
update_icon()
. = ..()
. = ..()
/obj/item/weapon/clipboard/Destroy()
QDEL_NULL(haspen)
QDEL_NULL(toppaper) //let movable/Destroy handle the rest
return ..()
/obj/item/weapon/clipboard/Destroy()
QDEL_NULL(haspen)
QDEL_NULL(toppaper) //let movable/Destroy handle the rest
return ..()
/obj/item/weapon/clipboard/update_icon()
cut_overlays()
if(toppaper)
add_overlay(toppaper.icon_state)
copy_overlays(toppaper)
copy_overlays(toppaper)
if(haspen)
add_overlay("clipboard_pen")
add_overlay("clipboard_over")
@@ -119,4 +119,4 @@
//Update everything
attack_self(usr)
update_icon()
update_icon()
+493 -493
View File
@@ -1,493 +1,493 @@
/obj/machinery/power/emitter
name = "Emitter"
desc = "A heavy duty industrial laser.\n<span class='notice'>Alt-click to rotate it clockwise.</span>"
icon = 'icons/obj/singularity.dmi'
icon_state = "emitter"
var/icon_state_on = "emitter_+a"
anchored = 0
density = 1
req_access = list(GLOB.access_engine_equip)
// The following 3 vars are mostly for the prototype
var/manual = FALSE
var/charge = 0
var/atom/target = null
use_power = 0
idle_power_usage = 10
active_power_usage = 300
var/active = 0
var/powered = 0
var/fire_delay = 100
var/maximum_fire_delay = 100
var/minimum_fire_delay = 20
var/last_shot = 0
var/shot_number = 0
var/state = 0
var/locked = 0
var/projectile_type = /obj/item/projectile/beam/emitter
var/projectile_sound = 'sound/weapons/emitter.ogg'
var/datum/effect_system/spark_spread/sparks
/obj/machinery/power/emitter/New()
..()
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/emitter(null)
B.apply_default_parts(src)
RefreshParts()
wires = new /datum/wires/emitter(src)
/obj/item/weapon/circuitboard/machine/emitter
name = "Emitter (Machine Board)"
build_path = /obj/machinery/power/emitter
origin_tech = "programming=3;powerstorage=4;engineering=4"
req_components = list(
/obj/item/weapon/stock_parts/micro_laser = 1,
/obj/item/weapon/stock_parts/manipulator = 1)
/obj/machinery/power/emitter/RefreshParts()
var/max_firedelay = 120
var/firedelay = 120
var/min_firedelay = 24
var/power_usage = 350
for(var/obj/item/weapon/stock_parts/micro_laser/L in component_parts)
max_firedelay -= 20 * L.rating
min_firedelay -= 4 * L.rating
firedelay -= 20 * L.rating
maximum_fire_delay = max_firedelay
minimum_fire_delay = min_firedelay
fire_delay = firedelay
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
power_usage -= 50 * M.rating
active_power_usage = power_usage
/obj/machinery/power/emitter/verb/rotate()
set name = "Rotate"
set category = "Object"
set src in oview(1)
if(usr.stat || !usr.canmove || usr.restrained())
return
if (src.anchored)
to_chat(usr, "<span class='warning'>It is fastened to the floor!</span>")
return 0
src.setDir(turn(src.dir, 270))
return 1
/obj/machinery/power/emitter/AltClick(mob/user)
..()
if(user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user))
return
else
rotate()
/obj/machinery/power/emitter/Initialize()
. = ..()
if(state == 2 && anchored)
connect_to_network()
sparks = new
sparks.attach(src)
sparks.set_up(5, TRUE, src)
/obj/machinery/power/emitter/Destroy()
if(SSticker && SSticker.IsRoundInProgress())
message_admins("Emitter deleted at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Emitter deleted at ([x],[y],[z])")
investigate_log("<font color='red'>deleted</font> at ([x],[y],[z]) at [get_area(src)]","singulo")
QDEL_NULL(sparks)
return ..()
/obj/machinery/power/emitter/update_icon()
if (active && powernet && avail(active_power_usage))
icon_state = icon_state_on
else
icon_state = initial(icon_state)
/obj/machinery/power/emitter/attack_hand(mob/user)
src.add_fingerprint(user)
if(state == 2)
if(!powernet)
to_chat(user, "<span class='warning'>The emitter isn't connected to a wire!</span>")
return 1
if(!src.locked)
if(src.active==1)
src.active = 0
to_chat(user, "<span class='notice'>You turn off \the [src].</span>")
message_admins("Emitter turned off by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(src)]",0,1)
log_game("Emitter turned off by [key_name(user)] in [COORD(src)]")
investigate_log("turned <font color='red'>off</font> by [key_name(user)] at [get_area(src)]","singulo")
else
src.active = 1
to_chat(user, "<span class='notice'>You turn on \the [src].</span>")
src.shot_number = 0
src.fire_delay = maximum_fire_delay
investigate_log("turned <font color='green'>on</font> by [key_name(user)] at [get_area(src)]","singulo")
update_icon()
else
to_chat(user, "<span class='warning'>The controls are locked!</span>")
else
to_chat(user, "<span class='warning'>The [src] needs to be firmly secured to the floor first!</span>")
return 1
/obj/machinery/power/emitter/attack_animal(mob/living/simple_animal/M)
if(ismegafauna(M) && anchored)
state = 0
anchored = FALSE
M.visible_message("<span class='warning'>[M] rips [src] free from its moorings!</span>")
else
..()
if(!anchored)
step(src, get_dir(M, src))
/obj/machinery/power/emitter/emp_act(severity)//Emitters are hardened but still might have issues
// add_load(1000)
/* if((severity == 1)&&prob(1)&&prob(1))
if(src.active)
src.active = 0
src.use_power = 1 */
return 1
/obj/machinery/power/emitter/process()
if(stat & (BROKEN))
return
if(src.state != 2 || (!powernet && active_power_usage))
src.active = 0
update_icon()
return
if(src.active == 1)
if(!active_power_usage || avail(active_power_usage))
add_load(active_power_usage)
if(!powered)
powered = 1
update_icon()
investigate_log("regained power and turned <font color='green'>on</font> at [get_area(src)]","singulo")
else
if(powered)
powered = 0
update_icon()
investigate_log("lost power and turned <font color='red'>off</font> at [get_area(src)]","singulo")
log_game("Emitter lost power in ([x],[y],[z])")
return
if(charge <=80)
charge+=5
if(!check_delay() || manual == TRUE)
return FALSE
fire_beam(target)
/obj/machinery/power/emitter/proc/check_delay()
if((src.last_shot + src.fire_delay) <= world.time)
return TRUE
return FALSE
/obj/machinery/power/emitter/proc/fire_beam_pulse()
if(!check_delay())
return FALSE
if(state != 2)
return FALSE
if(avail(active_power_usage))
add_load(active_power_usage)
fire_beam()
/obj/machinery/power/emitter/proc/fire_beam(atom/targeted_atom, mob/user)
var/turf/targets_from = get_turf(src)
if(targeted_atom && (targeted_atom == user || targeted_atom == targets_from || targeted_atom == src))
return
var/obj/item/projectile/P = new projectile_type(targets_from)
playsound(src.loc, projectile_sound, 50, 1)
if(prob(35))
sparks.start()
switch(dir)
if(NORTH)
P.yo = 20
P.xo = 0
if(NORTHEAST)
P.yo = 20
P.xo = 20
if(EAST)
P.yo = 0
P.xo = 20
if(SOUTHEAST)
P.yo = -20
P.xo = 20
if(WEST)
P.yo = 0
P.xo = -20
if(SOUTHWEST)
P.yo = -20
P.xo = -20
if(NORTHWEST)
P.yo = 20
P.xo = -20
else // Any other
P.yo = -20
P.xo = 0
if(target)
P.yo = targeted_atom.y - targets_from.y
P.xo = targeted_atom.x - targets_from.x
P.current = targets_from
P.starting = targets_from
P.firer = src
P.original = targeted_atom
if(!manual)
last_shot = world.time
if(shot_number < 3)
fire_delay = 20
shot_number ++
else
fire_delay = rand(minimum_fire_delay,maximum_fire_delay)
shot_number = 0
if(!target)
P.setDir(src.dir)
P.starting = loc
else
if(QDELETED(target))
target = null
P.fire()
return P
/obj/machinery/power/emitter/can_be_unfasten_wrench(mob/user, silent)
if(state == EM_WELDED)
if(!silent)
to_chat(user, "<span class='warning'>[src] is welded to the floor!</span>")
return FAILED_UNFASTEN
return ..()
/obj/machinery/power/emitter/default_unfasten_wrench(mob/user, obj/item/weapon/wrench/W, time = 20)
. = ..()
if(. == SUCCESSFUL_UNFASTEN)
if(anchored)
state = EM_SECURED
else
state = EM_UNSECURED
/obj/machinery/power/emitter/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weapon/wrench))
if(active)
to_chat(user, "<span class='warning'>Turn \the [src] off first!</span>")
return
default_unfasten_wrench(user, W, 0)
return
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(active)
to_chat(user, "Turn \the [src] off first.")
return
switch(state)
if(EM_UNSECURED)
to_chat(user, "<span class='warning'>The [src.name] needs to be wrenched to the floor!</span>")
if(EM_SECURED)
if(WT.remove_fuel(0,user))
playsound(loc, WT.usesound, 50, 1)
user.visible_message("[user.name] starts to weld the [name] to the floor.", \
"<span class='notice'>You start to weld \the [src] to the floor...</span>", \
"<span class='italics'>You hear welding.</span>")
if(do_after(user,20*W.toolspeed, target = src) && WT.isOn())
state = EM_WELDED
to_chat(user, "<span class='notice'>You weld \the [src] to the floor.</span>")
connect_to_network()
if(EM_WELDED)
if(WT.remove_fuel(0,user))
playsound(loc, WT.usesound, 50, 1)
user.visible_message("[user.name] starts to cut the [name] free from the floor.", \
"<span class='notice'>You start to cut \the [src] free from the floor...</span>", \
"<span class='italics'>You hear welding.</span>")
if(do_after(user,20*W.toolspeed, target = src) && WT.isOn())
state = EM_SECURED
to_chat(user, "<span class='notice'>You cut \the [src] free from the floor.</span>")
disconnect_from_network()
return
if(W.GetID())
if(emagged)
to_chat(user, "<span class='warning'>The lock seems to be broken!</span>")
return
if(allowed(user))
if(active)
locked = !locked
to_chat(user, "<span class='notice'>You [src.locked ? "lock" : "unlock"] the controls.</span>")
else
to_chat(user, "<span class='warning'>The controls can only be locked when \the [src] is online!</span>")
else
to_chat(user, "<span class='danger'>Access denied.</span>")
return
if(is_wire_tool(W) && panel_open)
wires.interact(user)
return
if(default_deconstruction_screwdriver(user, "emitter_open", "emitter", W))
return
if(exchange_parts(user, W))
return
if(default_pry_open(W))
return
if(default_deconstruction_crowbar(W))
return
return ..()
/obj/machinery/power/emitter/emag_act(mob/user)
if(!emagged)
locked = 0
emagged = 1
if(user)
user.visible_message("[user.name] emags the [src.name].","<span class='notice'>You short out the lock.</span>")
/obj/machinery/power/emitter/prototype
name = "Prototype Emitter"
icon = 'icons/obj/turrets.dmi'
icon_state = "protoemitter"
icon_state_on = "protoemitter_+a"
can_buckle = TRUE
buckle_lying = 0
var/view_range = 12
var/datum/action/innate/protoemitter/firing/auto
//BUCKLE HOOKS
/obj/machinery/power/emitter/prototype/unbuckle_mob(mob/living/buckled_mob,force = 0)
playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
manual = FALSE
for(var/obj/item/I in buckled_mob.held_items)
if(istype(I, /obj/item/weapon/turret_control))
qdel(I)
if(istype(buckled_mob))
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = 0
if(buckled_mob.client)
buckled_mob.client.change_view(world.view)
auto.Remove(buckled_mob)
. = ..()
/obj/machinery/power/emitter/prototype/user_buckle_mob(mob/living/M, mob/living/carbon/user)
if(user.incapacitated() || !istype(user))
return
for(var/atom/movable/A in get_turf(src))
if(A.density && (A != src && A != M))
return
M.forceMove(get_turf(src))
..()
playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
M.pixel_y = 14
layer = 4.1
if(M.client)
M.client.change_view(view_range)
if(!auto)
auto = new()
auto.Grant(M, src)
/datum/action/innate/protoemitter
check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUNNED | AB_CHECK_CONSCIOUS
var/obj/machinery/power/emitter/prototype/PE
var/mob/living/carbon/U
/datum/action/innate/protoemitter/Grant(mob/living/carbon/L, obj/machinery/power/emitter/prototype/proto)
PE = proto
U = L
. = ..()
/datum/action/innate/protoemitter/firing
name = "Switch to Manual Firing"
desc = "The emitter will only fire on your command and at your designated target"
button_icon_state = "mech_zoom_on"
/datum/action/innate/protoemitter/firing/Activate()
if(PE.manual)
playsound(PE,'sound/mecha/mechmove01.ogg', 50, 1)
PE.manual = FALSE
name = "Switch to Manual Firing"
desc = "The emitter will only fire on your command and at your designated target"
button_icon_state = "mech_zoom_on"
for(var/obj/item/I in U.held_items)
if(istype(I, /obj/item/weapon/turret_control))
qdel(I)
UpdateButtonIcon()
return
else
playsound(PE,'sound/mecha/mechmove01.ogg', 50, 1)
name = "Switch to Automatic Firing"
desc = "Emitters will switch to periodic firing at your last target"
button_icon_state = "mech_zoom_off"
PE.manual = TRUE
for(var/V in U.held_items)
var/obj/item/I = V
if(istype(I))
if(U.dropItemToGround(I))
var/obj/item/weapon/turret_control/TC = new /obj/item/weapon/turret_control()
U.put_in_hands(TC)
else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
var/obj/item/weapon/turret_control/TC = new /obj/item/weapon/turret_control()
U.put_in_hands(TC)
UpdateButtonIcon()
/obj/item/weapon/turret_control
name = "turret controls"
icon_state = "offhand"
w_class = WEIGHT_CLASS_HUGE
flags = ABSTRACT | NODROP
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF | NOBLUDGEON
var/delay = 0
/obj/item/weapon/turret_control/afterattack(atom/targeted_atom, mob/user)
..()
var/obj/machinery/power/emitter/E = user.buckled
E.setDir(get_dir(E,targeted_atom))
user.setDir(E.dir)
switch(E.dir)
if(NORTH)
E.layer = 3.9
user.pixel_x = 0
user.pixel_y = -14
if(NORTHEAST)
E.layer = 3.9
user.pixel_x = -8
user.pixel_y = -12
if(EAST)
E.layer = 4.1
user.pixel_x = -14
user.pixel_y = 0
if(SOUTHEAST)
E.layer = 3.9
user.pixel_x = -8
user.pixel_y = 12
if(SOUTH)
E.layer = 4.1
user.pixel_x = 0
user.pixel_y = 14
if(SOUTHWEST)
E.layer = 3.9
user.pixel_x = 8
user.pixel_y = 12
if(WEST)
E.layer = 4.1
user.pixel_x = 14
user.pixel_y = 0
if(NORTHWEST)
E.layer = 3.9
user.pixel_x = 8
user.pixel_y = -12
if(E.charge >= 10 && world.time > delay)
E.charge -= 10
E.target = targeted_atom
E.fire_beam(targeted_atom, user)
delay = world.time + 10
else if (E.charge < 10)
playsound(get_turf(user),'sound/machines/buzz-sigh.ogg', 50, 1)
/obj/machinery/power/emitter
name = "Emitter"
desc = "A heavy duty industrial laser.\n<span class='notice'>Alt-click to rotate it clockwise.</span>"
icon = 'icons/obj/singularity.dmi'
icon_state = "emitter"
var/icon_state_on = "emitter_+a"
anchored = 0
density = 1
req_access = list(GLOB.access_engine_equip)
// The following 3 vars are mostly for the prototype
var/manual = FALSE
var/charge = 0
var/atom/target = null
use_power = 0
idle_power_usage = 10
active_power_usage = 300
var/active = 0
var/powered = 0
var/fire_delay = 100
var/maximum_fire_delay = 100
var/minimum_fire_delay = 20
var/last_shot = 0
var/shot_number = 0
var/state = 0
var/locked = 0
var/projectile_type = /obj/item/projectile/beam/emitter
var/projectile_sound = 'sound/weapons/emitter.ogg'
var/datum/effect_system/spark_spread/sparks
/obj/machinery/power/emitter/New()
..()
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/emitter(null)
B.apply_default_parts(src)
RefreshParts()
wires = new /datum/wires/emitter(src)
/obj/item/weapon/circuitboard/machine/emitter
name = "Emitter (Machine Board)"
build_path = /obj/machinery/power/emitter
origin_tech = "programming=3;powerstorage=4;engineering=4"
req_components = list(
/obj/item/weapon/stock_parts/micro_laser = 1,
/obj/item/weapon/stock_parts/manipulator = 1)
/obj/machinery/power/emitter/RefreshParts()
var/max_firedelay = 120
var/firedelay = 120
var/min_firedelay = 24
var/power_usage = 350
for(var/obj/item/weapon/stock_parts/micro_laser/L in component_parts)
max_firedelay -= 20 * L.rating
min_firedelay -= 4 * L.rating
firedelay -= 20 * L.rating
maximum_fire_delay = max_firedelay
minimum_fire_delay = min_firedelay
fire_delay = firedelay
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
power_usage -= 50 * M.rating
active_power_usage = power_usage
/obj/machinery/power/emitter/verb/rotate()
set name = "Rotate"
set category = "Object"
set src in oview(1)
if(usr.stat || !usr.canmove || usr.restrained())
return
if (src.anchored)
to_chat(usr, "<span class='warning'>It is fastened to the floor!</span>")
return 0
src.setDir(turn(src.dir, 270))
return 1
/obj/machinery/power/emitter/AltClick(mob/user)
..()
if(user.incapacitated())
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return
if(!in_range(src, user))
return
else
rotate()
/obj/machinery/power/emitter/Initialize()
. = ..()
if(state == 2 && anchored)
connect_to_network()
sparks = new
sparks.attach(src)
sparks.set_up(5, TRUE, src)
/obj/machinery/power/emitter/Destroy()
if(SSticker && SSticker.IsRoundInProgress())
message_admins("Emitter deleted at ([x],[y],[z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)",0,1)
log_game("Emitter deleted at ([x],[y],[z])")
investigate_log("<font color='red'>deleted</font> at ([x],[y],[z]) at [get_area(src)]","singulo")
QDEL_NULL(sparks)
return ..()
/obj/machinery/power/emitter/update_icon()
if (active && powernet && avail(active_power_usage))
icon_state = icon_state_on
else
icon_state = initial(icon_state)
/obj/machinery/power/emitter/attack_hand(mob/user)
src.add_fingerprint(user)
if(state == 2)
if(!powernet)
to_chat(user, "<span class='warning'>The emitter isn't connected to a wire!</span>")
return 1
if(!src.locked)
if(src.active==1)
src.active = 0
to_chat(user, "<span class='notice'>You turn off \the [src].</span>")
message_admins("Emitter turned off by [ADMIN_LOOKUPFLW(user)] in [ADMIN_COORDJMP(src)]",0,1)
log_game("Emitter turned off by [key_name(user)] in [COORD(src)]")
investigate_log("turned <font color='red'>off</font> by [key_name(user)] at [get_area(src)]","singulo")
else
src.active = 1
to_chat(user, "<span class='notice'>You turn on \the [src].</span>")
src.shot_number = 0
src.fire_delay = maximum_fire_delay
investigate_log("turned <font color='green'>on</font> by [key_name(user)] at [get_area(src)]","singulo")
update_icon()
else
to_chat(user, "<span class='warning'>The controls are locked!</span>")
else
to_chat(user, "<span class='warning'>The [src] needs to be firmly secured to the floor first!</span>")
return 1
/obj/machinery/power/emitter/attack_animal(mob/living/simple_animal/M)
if(ismegafauna(M) && anchored)
state = 0
anchored = FALSE
M.visible_message("<span class='warning'>[M] rips [src] free from its moorings!</span>")
else
..()
if(!anchored)
step(src, get_dir(M, src))
/obj/machinery/power/emitter/emp_act(severity)//Emitters are hardened but still might have issues
// add_load(1000)
/* if((severity == 1)&&prob(1)&&prob(1))
if(src.active)
src.active = 0
src.use_power = 1 */
return 1
/obj/machinery/power/emitter/process()
if(stat & (BROKEN))
return
if(src.state != 2 || (!powernet && active_power_usage))
src.active = 0
update_icon()
return
if(src.active == 1)
if(!active_power_usage || avail(active_power_usage))
add_load(active_power_usage)
if(!powered)
powered = 1
update_icon()
investigate_log("regained power and turned <font color='green'>on</font> at [get_area(src)]","singulo")
else
if(powered)
powered = 0
update_icon()
investigate_log("lost power and turned <font color='red'>off</font> at [get_area(src)]","singulo")
log_game("Emitter lost power in ([x],[y],[z])")
return
if(charge <=80)
charge+=5
if(!check_delay() || manual == TRUE)
return FALSE
fire_beam(target)
/obj/machinery/power/emitter/proc/check_delay()
if((src.last_shot + src.fire_delay) <= world.time)
return TRUE
return FALSE
/obj/machinery/power/emitter/proc/fire_beam_pulse()
if(!check_delay())
return FALSE
if(state != 2)
return FALSE
if(avail(active_power_usage))
add_load(active_power_usage)
fire_beam()
/obj/machinery/power/emitter/proc/fire_beam(atom/targeted_atom, mob/user)
var/turf/targets_from = get_turf(src)
if(targeted_atom && (targeted_atom == user || targeted_atom == targets_from || targeted_atom == src))
return
var/obj/item/projectile/P = new projectile_type(targets_from)
playsound(src.loc, projectile_sound, 50, 1)
if(prob(35))
sparks.start()
switch(dir)
if(NORTH)
P.yo = 20
P.xo = 0
if(NORTHEAST)
P.yo = 20
P.xo = 20
if(EAST)
P.yo = 0
P.xo = 20
if(SOUTHEAST)
P.yo = -20
P.xo = 20
if(WEST)
P.yo = 0
P.xo = -20
if(SOUTHWEST)
P.yo = -20
P.xo = -20
if(NORTHWEST)
P.yo = 20
P.xo = -20
else // Any other
P.yo = -20
P.xo = 0
if(target)
P.yo = targeted_atom.y - targets_from.y
P.xo = targeted_atom.x - targets_from.x
P.current = targets_from
P.starting = targets_from
P.firer = src
P.original = targeted_atom
if(!manual)
last_shot = world.time
if(shot_number < 3)
fire_delay = 20
shot_number ++
else
fire_delay = rand(minimum_fire_delay,maximum_fire_delay)
shot_number = 0
if(!target)
P.setDir(src.dir)
P.starting = loc
else
if(QDELETED(target))
target = null
P.fire()
return P
/obj/machinery/power/emitter/can_be_unfasten_wrench(mob/user, silent)
if(state == EM_WELDED)
if(!silent)
to_chat(user, "<span class='warning'>[src] is welded to the floor!</span>")
return FAILED_UNFASTEN
return ..()
/obj/machinery/power/emitter/default_unfasten_wrench(mob/user, obj/item/weapon/wrench/W, time = 20)
. = ..()
if(. == SUCCESSFUL_UNFASTEN)
if(anchored)
state = EM_SECURED
else
state = EM_UNSECURED
/obj/machinery/power/emitter/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weapon/wrench))
if(active)
to_chat(user, "<span class='warning'>Turn \the [src] off first!</span>")
return
default_unfasten_wrench(user, W, 0)
return
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(active)
to_chat(user, "Turn \the [src] off first.")
return
switch(state)
if(EM_UNSECURED)
to_chat(user, "<span class='warning'>The [src.name] needs to be wrenched to the floor!</span>")
if(EM_SECURED)
if(WT.remove_fuel(0,user))
playsound(loc, WT.usesound, 50, 1)
user.visible_message("[user.name] starts to weld the [name] to the floor.", \
"<span class='notice'>You start to weld \the [src] to the floor...</span>", \
"<span class='italics'>You hear welding.</span>")
if(do_after(user,20*W.toolspeed, target = src) && WT.isOn())
state = EM_WELDED
to_chat(user, "<span class='notice'>You weld \the [src] to the floor.</span>")
connect_to_network()
if(EM_WELDED)
if(WT.remove_fuel(0,user))
playsound(loc, WT.usesound, 50, 1)
user.visible_message("[user.name] starts to cut the [name] free from the floor.", \
"<span class='notice'>You start to cut \the [src] free from the floor...</span>", \
"<span class='italics'>You hear welding.</span>")
if(do_after(user,20*W.toolspeed, target = src) && WT.isOn())
state = EM_SECURED
to_chat(user, "<span class='notice'>You cut \the [src] free from the floor.</span>")
disconnect_from_network()
return
if(W.GetID())
if(emagged)
to_chat(user, "<span class='warning'>The lock seems to be broken!</span>")
return
if(allowed(user))
if(active)
locked = !locked
to_chat(user, "<span class='notice'>You [src.locked ? "lock" : "unlock"] the controls.</span>")
else
to_chat(user, "<span class='warning'>The controls can only be locked when \the [src] is online!</span>")
else
to_chat(user, "<span class='danger'>Access denied.</span>")
return
if(is_wire_tool(W) && panel_open)
wires.interact(user)
return
if(default_deconstruction_screwdriver(user, "emitter_open", "emitter", W))
return
if(exchange_parts(user, W))
return
if(default_pry_open(W))
return
if(default_deconstruction_crowbar(W))
return
return ..()
/obj/machinery/power/emitter/emag_act(mob/user)
if(!emagged)
locked = 0
emagged = 1
if(user)
user.visible_message("[user.name] emags the [src.name].","<span class='notice'>You short out the lock.</span>")
/obj/machinery/power/emitter/prototype
name = "Prototype Emitter"
icon = 'icons/obj/turrets.dmi'
icon_state = "protoemitter"
icon_state_on = "protoemitter_+a"
can_buckle = TRUE
buckle_lying = 0
var/view_range = 12
var/datum/action/innate/protoemitter/firing/auto
//BUCKLE HOOKS
/obj/machinery/power/emitter/prototype/unbuckle_mob(mob/living/buckled_mob,force = 0)
playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
manual = FALSE
for(var/obj/item/I in buckled_mob.held_items)
if(istype(I, /obj/item/weapon/turret_control))
qdel(I)
if(istype(buckled_mob))
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = 0
if(buckled_mob.client)
buckled_mob.client.change_view(world.view)
auto.Remove(buckled_mob)
. = ..()
/obj/machinery/power/emitter/prototype/user_buckle_mob(mob/living/M, mob/living/carbon/user)
if(user.incapacitated() || !istype(user))
return
for(var/atom/movable/A in get_turf(src))
if(A.density && (A != src && A != M))
return
M.forceMove(get_turf(src))
..()
playsound(src,'sound/mecha/mechmove01.ogg', 50, 1)
M.pixel_y = 14
layer = 4.1
if(M.client)
M.client.change_view(view_range)
if(!auto)
auto = new()
auto.Grant(M, src)
/datum/action/innate/protoemitter
check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUNNED | AB_CHECK_CONSCIOUS
var/obj/machinery/power/emitter/prototype/PE
var/mob/living/carbon/U
/datum/action/innate/protoemitter/Grant(mob/living/carbon/L, obj/machinery/power/emitter/prototype/proto)
PE = proto
U = L
. = ..()
/datum/action/innate/protoemitter/firing
name = "Switch to Manual Firing"
desc = "The emitter will only fire on your command and at your designated target"
button_icon_state = "mech_zoom_on"
/datum/action/innate/protoemitter/firing/Activate()
if(PE.manual)
playsound(PE,'sound/mecha/mechmove01.ogg', 50, 1)
PE.manual = FALSE
name = "Switch to Manual Firing"
desc = "The emitter will only fire on your command and at your designated target"
button_icon_state = "mech_zoom_on"
for(var/obj/item/I in U.held_items)
if(istype(I, /obj/item/weapon/turret_control))
qdel(I)
UpdateButtonIcon()
return
else
playsound(PE,'sound/mecha/mechmove01.ogg', 50, 1)
name = "Switch to Automatic Firing"
desc = "Emitters will switch to periodic firing at your last target"
button_icon_state = "mech_zoom_off"
PE.manual = TRUE
for(var/V in U.held_items)
var/obj/item/I = V
if(istype(I))
if(U.dropItemToGround(I))
var/obj/item/weapon/turret_control/TC = new /obj/item/weapon/turret_control()
U.put_in_hands(TC)
else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
var/obj/item/weapon/turret_control/TC = new /obj/item/weapon/turret_control()
U.put_in_hands(TC)
UpdateButtonIcon()
/obj/item/weapon/turret_control
name = "turret controls"
icon_state = "offhand"
w_class = WEIGHT_CLASS_HUGE
flags = ABSTRACT | NODROP
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF | NOBLUDGEON
var/delay = 0
/obj/item/weapon/turret_control/afterattack(atom/targeted_atom, mob/user)
..()
var/obj/machinery/power/emitter/E = user.buckled
E.setDir(get_dir(E,targeted_atom))
user.setDir(E.dir)
switch(E.dir)
if(NORTH)
E.layer = 3.9
user.pixel_x = 0
user.pixel_y = -14
if(NORTHEAST)
E.layer = 3.9
user.pixel_x = -8
user.pixel_y = -12
if(EAST)
E.layer = 4.1
user.pixel_x = -14
user.pixel_y = 0
if(SOUTHEAST)
E.layer = 3.9
user.pixel_x = -8
user.pixel_y = 12
if(SOUTH)
E.layer = 4.1
user.pixel_x = 0
user.pixel_y = 14
if(SOUTHWEST)
E.layer = 3.9
user.pixel_x = 8
user.pixel_y = 12
if(WEST)
E.layer = 4.1
user.pixel_x = 14
user.pixel_y = 0
if(NORTHWEST)
E.layer = 3.9
user.pixel_x = 8
user.pixel_y = -12
if(E.charge >= 10 && world.time > delay)
E.charge -= 10
E.target = targeted_atom
E.fire_beam(targeted_atom, user)
delay = world.time + 10
else if (E.charge < 10)
playsound(get_turf(user),'sound/machines/buzz-sigh.ogg', 50, 1)
@@ -117,8 +117,8 @@
strength++
strength_change()
message_admins("PA Control Computer increased to [strength] by [ADMIN_LOOKUPFLW(usr)] in [ADMIN_COORDJMP(src)]",0,1)
log_game("PA Control Computer increased to [strength] by [key_name(usr)] in [COORD(src)]")
message_admins("PA Control Computer increased to [strength] by [ADMIN_LOOKUPFLW(usr)] in [ADMIN_COORDJMP(src)]",0,1)
log_game("PA Control Computer increased to [strength] by [key_name(usr)] in [COORD(src)]")
investigate_log("increased to <font color='red'>[strength]</font> by [key_name(usr)]","singulo")
@@ -127,8 +127,8 @@
strength--
strength_change()
message_admins("PA Control Computer decreased to [strength] by [ADMIN_LOOKUPFLW(usr)] in [ADMIN_COORDJMP(src)]",0,1)
log_game("PA Control Computer decreased to [strength] by [key_name(usr)] in [COORD(src)]")
message_admins("PA Control Computer decreased to [strength] by [ADMIN_LOOKUPFLW(usr)] in [ADMIN_COORDJMP(src)]",0,1)
log_game("PA Control Computer decreased to [strength] by [key_name(usr)] in [COORD(src)]")
investigate_log("decreased to <font color='green'>[strength]</font> by [key_name(usr)]","singulo")
@@ -191,7 +191,7 @@
fire_sound = 'sound/magic/lightningbolt.ogg'
e_cost = 200
select_name = "stun"
projectile_type = /obj/item/projectile/energy/tesla/revolver
projectile_type = /obj/item/projectile/energy/tesla/revolver
/obj/item/ammo_casing/energy/gravityrepulse
projectile_type = /obj/item/projectile/gravityrepulse
@@ -19,12 +19,12 @@
/obj/item/weapon/gun/energy/pulse/prize/New()
. = ..()
GLOB.poi_list |= src
var/msg = "A pulse rifle prize has been created at [ADMIN_COORDJMP(src)]"
var/msg = "A pulse rifle prize has been created at [ADMIN_COORDJMP(src)]"
message_admins(msg)
log_game(msg)
notify_ghosts("Someone won a pulse rifle as a prize!", source = src, action = NOTIFY_ORBIT)
notify_ghosts("Someone won a pulse rifle as a prize!", source = src, action = NOTIFY_ORBIT)
/obj/item/weapon/gun/energy/pulse/prize/Destroy()
GLOB.poi_list -= src
+14 -14
View File
@@ -179,8 +179,8 @@
return
if(setAngle)
Angle = setAngle
var/old_pixel_x = pixel_x
var/old_pixel_y = pixel_y
var/old_pixel_x = pixel_x
var/old_pixel_y = pixel_y
if(!legacy) //new projectiles
set waitfor = 0
var/next_run = world.time
@@ -203,30 +203,30 @@
var/Pixel_x=round((sin(Angle)+16*sin(Angle)*2), 1) //round() is a floor operation when only one argument is supplied, we don't want that here
var/Pixel_y=round((cos(Angle)+16*cos(Angle)*2), 1)
var/pixel_x_offset = old_pixel_x + Pixel_x
var/pixel_y_offset = old_pixel_y + Pixel_y
var/pixel_x_offset = old_pixel_x + Pixel_x
var/pixel_y_offset = old_pixel_y + Pixel_y
var/new_x = x
var/new_y = y
while(pixel_x_offset > 16)
pixel_x_offset -= 32
old_pixel_x -= 32
old_pixel_x -= 32
new_x++// x++
while(pixel_x_offset < -16)
pixel_x_offset += 32
old_pixel_x += 32
old_pixel_x += 32
new_x--
while(pixel_y_offset > 16)
pixel_y_offset -= 32
old_pixel_y -= 32
old_pixel_y -= 32
new_y++
while(pixel_y_offset < -16)
pixel_y_offset += 32
old_pixel_y += 32
old_pixel_y += 32
new_y--
pixel_x = old_pixel_x
pixel_y = old_pixel_y
pixel_x = old_pixel_x
pixel_y = old_pixel_y
step_towards(src, locate(new_x, new_y, z))
next_run += max(world.tick_lag, speed)
var/delay = next_run - world.time
@@ -235,9 +235,9 @@
pixel_y = pixel_y_offset
else
animate(src, pixel_x = pixel_x_offset, pixel_y = pixel_y_offset, time = max(1, (delay <= 3 ? delay - 1 : delay)), flags = ANIMATION_END_NOW)
old_pixel_x = pixel_x_offset
old_pixel_y = pixel_y_offset
old_pixel_x = pixel_x_offset
old_pixel_y = pixel_y_offset
if(original && (original.layer>=2.75) || ismob(original))
if(loc == get_turf(original))
if(!(original in permutated))
View File
View File
@@ -48,16 +48,16 @@
user.changeNext_move(CLICK_CD_RANGE*2)
user.newtonian_move(get_dir(A, user))
var/turf/T = get_turf(src)
var/area/area = get_area(src)
var/area/area = get_area(src)
if(reagents.has_reagent("sacid"))
message_admins("[ADMIN_LOOKUPFLW(user)] fired sulphuric acid from \a [src] at [area] [ADMIN_COORDJMP(T)].")
log_game("[key_name(user)] fired sulphuric acid from \a [src] at [area] ([T.x], [T.y], [T.z]).")
message_admins("[ADMIN_LOOKUPFLW(user)] fired sulphuric acid from \a [src] at [area] [ADMIN_COORDJMP(T)].")
log_game("[key_name(user)] fired sulphuric acid from \a [src] at [area] ([T.x], [T.y], [T.z]).")
if(reagents.has_reagent("facid"))
message_admins("[ADMIN_LOOKUPFLW(user)] fired Fluacid from \a [src] at [area] [ADMIN_COORDJMP(T)].")
log_game("[key_name(user)] fired Fluacid from \a [src] at [area] [COORD(T)].")
message_admins("[ADMIN_LOOKUPFLW(user)] fired Fluacid from \a [src] at [area] [ADMIN_COORDJMP(T)].")
log_game("[key_name(user)] fired Fluacid from \a [src] at [area] [COORD(T)].")
if(reagents.has_reagent("lube"))
message_admins("[ADMIN_LOOKUPFLW(user)] fired Space lube from \a [src] at [area] [ADMIN_COORDJMP(T)].")
log_game("[key_name(user)] fired Space lube from \a [src] at [area] [COORD(T)].")
message_admins("[ADMIN_LOOKUPFLW(user)] fired Space lube from \a [src] at [area] [ADMIN_COORDJMP(T)].")
log_game("[key_name(user)] fired Space lube from \a [src] at [area] [COORD(T)].")
return
+1 -1
View File
@@ -30,4 +30,4 @@
return
last_request = world.time
to_chat(usr, "<span class='notice'>Your request has been recieved by Centcom.</span>")
to_chat(GLOB.admins, "<b>FERRY: <font color='blue'>[ADMIN_LOOKUPFLW(usr)] (<A HREF='?_src_=holder;secrets=moveferry'>Move Ferry</a>)</b> is requesting to move the transport ferry to Centcom.</font>")
to_chat(GLOB.admins, "<b>FERRY: <font color='blue'>[ADMIN_LOOKUPFLW(usr)] (<A HREF='?_src_=holder;secrets=moveferry'>Move Ferry</a>)</b> is requesting to move the transport ferry to Centcom.</font>")
+18 -18
View File
@@ -69,24 +69,24 @@
action_icon_state = "smoke"
/obj/effect/proc_holder/spell/targeted/smoke/lesser //Chaplain smoke book
name = "Smoke"
desc = "This spell spawns a small cloud of choking smoke at your location."
school = "conjuration"
charge_max = 360
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = -1
include_user = 1
smoke_spread = 1
smoke_amt = 2
action_icon_state = "smoke"
/obj/effect/proc_holder/spell/targeted/smoke/lesser //Chaplain smoke book
name = "Smoke"
desc = "This spell spawns a small cloud of choking smoke at your location."
school = "conjuration"
charge_max = 360
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = -1
include_user = 1
smoke_spread = 1
smoke_amt = 2
action_icon_state = "smoke"
/obj/effect/proc_holder/spell/targeted/emplosion/disable_tech
name = "Disable Tech"
desc = "This spell disables all weapons, cameras and most other technology in range."