diff --git a/_maps/map_files/vr/blood_and_sand.dmm b/_maps/map_files/vr/blood_and_sand.dmm
new file mode 100644
index 00000000000..af13e70d2f1
--- /dev/null
+++ b/_maps/map_files/vr/blood_and_sand.dmm
@@ -0,0 +1,46 @@
+"a" = (/turf/space,/area/space)
+"b" = (/turf/unsimulated/wall/other,/area/vr/roman)
+"c" = (/turf/unsimulated/beach/sand,/area/vr/roman)
+"d" = (/obj/effect/landmark{name = "avatarspawn"},/turf/unsimulated/beach/sand,/area/vr/roman)
+"e" = (/turf/unsimulated/floor{tag = "icon-warnplate (NORTHWEST)"; icon_state = "warnplate"; dir = 9},/area/vr/roman)
+"f" = (/turf/unsimulated/floor{tag = "icon-warnplate (NORTH)"; icon_state = "warnplate"; dir = 1},/area/vr/roman)
+"g" = (/turf/unsimulated/floor{tag = "icon-warnplate (NORTHEAST)"; icon_state = "warnplate"; dir = 5},/area/vr/roman)
+"h" = (/turf/unsimulated/floor{icon_state = "warnplate"; dir = 8},/area/vr/roman)
+"i" = (/turf/unsimulated/floor/lava/dense,/area/vr/roman)
+"j" = (/turf/unsimulated/floor{icon_state = "panelscorched"},/area/vr/roman)
+"k" = (/turf/unsimulated/floor{tag = "icon-warnplate (SOUTHWEST)"; icon_state = "warnplate"; dir = 10},/area/vr/roman)
+"l" = (/turf/unsimulated/floor{tag = "icon-warnplate"; icon_state = "warnplate"; dir = 2},/area/vr/roman)
+"m" = (/turf/unsimulated/floor{tag = "icon-warnplate (SOUTHEAST)"; icon_state = "warnplate"; dir = 6},/area/vr/roman)
+
+(1,1,1) = {"
+aaaaaaaaaaabbbbbbbbaaaaaaaaaaa
+aaaaaaaabbbbccccccbbbbaaaaaaaa
+aaaaaaabbccccccccccccbbaaaaaaa
+aaaaabbbccccccddccccccbbbaaaaa
+aaaabbdccccccefgcccccccdbbaaaa
+aaabbddcccccchijcccccccddbbaaa
+aaabcccccccccklmccccccccccbaaa
+aabbccccccccccccccccccccccbbaa
+abbccefgcccccccccccccccccccbba
+abccchijccccccddccccccccccccba
+abcccklmcccdccccccdcccccccccba
+bbccccccccdbccccccbdccccccccbb
+bccccccccccccccccccccccccccccb
+bccccccccccccccccccccccccccccb
+bccdccccdccccccccccccdccccdccb
+bccdccccdccccccccccccdccccdccb
+bccccccccccccccccccccccccccccb
+bccccccccccccccccccccccccccccb
+bbccccccccdbccccccbdccccefgcbb
+abcccccccccdccccccdccccchijcba
+abccccccccccccccccccccccklmcba
+abbcccefgcccccddcccccccccccbba
+aabbcchijcccccccccccccccccbbaa
+aaabddklmcccccccccccccccccbaaa
+aaabbdcccccccccccccccccddbbaaa
+aaaabbcccccccccccccccccdbbaaaa
+aaaaabbbccccccddccccccbbbaaaaa
+aaaaaaabbccccccccccccbbaaaaaaa
+aaaaaaaabbbbccccccbbbbaaaaaaaa
+aaaaaaaaaaabbbbbbbbaaaaaaaaaaa
+"}
diff --git a/_maps/map_files/vr/lobby.dmm b/_maps/map_files/vr/lobby.dmm
new file mode 100644
index 00000000000..798228e212e
--- /dev/null
+++ b/_maps/map_files/vr/lobby.dmm
@@ -0,0 +1,46 @@
+"a" = (/turf/space,/area/space)
+"b" = (/turf/unsimulated/wall/metal,/area/vr/lobby)
+"c" = (/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vr/lobby)
+"d" = (/turf/unsimulated/wall/fakeglass{dir = 8; icon_state = "fakewindows3"; tag = "icon-fakewindows (WEST)"},/area/vr/lobby)
+"e" = (/turf/unsimulated/floor{icon_state = "gcircuit"},/area/vr/lobby)
+"f" = (/obj/machinery/telecomms/processor/preset_cent,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vr/lobby)
+"g" = (/turf/unsimulated/floor{icon_state = "light_on"},/area/vr/lobby)
+"h" = (/turf/unsimulated/wall/fakeglass{dir = 1; icon_state = "fakewindows"; tag = "icon-fakewindows (WEST)"},/area/vr/lobby)
+"i" = (/turf/unsimulated/wall/fakeglass{dir = 0; icon_state = "fakewindows"; tag = "icon-fakewindows (EAST)"},/area/vr/lobby)
+"j" = (/obj/machinery/telecomms/server/presets/centcomm,/turf/unsimulated/floor{icon_state = "gcircuit"},/area/vr/lobby)
+"k" = (/obj/machinery/telecomms/relay/preset/centcom,/turf/unsimulated/floor{icon_state = "gcircuit"},/area/vr/lobby)
+"l" = (/obj/machinery/telecomms/hub/preset_cent,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vr/lobby)
+"m" = (/obj/machinery/computer/vr_control,/turf/unsimulated/floor{tag = "icon-dark"; icon_state = "dark"},/area/vr/lobby)
+"n" = (/turf/unsimulated/wall/fakeglass{icon_state = "fakewindows"; dir = 8},/area/vr/lobby)
+"o" = (/turf/unsimulated/wall/fakeglass{tag = "icon-fakewindows (EAST)"; icon_state = "fakewindows"; dir = 4},/area/vr/lobby)
+"p" = (/obj/effect/landmark{name = "avatarspawn"},/turf/unsimulated/floor{icon_state = "gcircuit"},/area/vr/lobby)
+"q" = (/obj/machinery/telecomms/processor/preset_cent,/turf/simulated/floor/bluegrid{icon_state = "dark"; name = "Mainframe Floor"; nitrogen = 100; oxygen = 0; temperature = 80},/area/vr/lobby)
+"r" = (/turf/unsimulated/wall/fakeglass,/area/vr/lobby)
+
+(1,1,1) = {"
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaabbbbaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaabbccbbaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaabbbdeedbbbaaaaaaaaaaaaaaaaaaaa
+aabbbbbbbbbbbbbbbbbbbeefeefeebbbbbbbbbbbbbbbbbbbaa
+aabbcecececececbbbeeeegheehgeeeebbbcecececececbbaa
+aabcgegegegegegcbbegcgcieeicgcgebbcgegegegegegcbaa
+aabeejekejekejeebbeceeeleeleeecebbeejekejekejeebaa
+aabcgegegegegegcbeegecgheehgcegeebcgegegegegegcbaa
+aabbcecececececbbegcegcieeicgecgebbcecececececbbaa
+aaabdmdmdmdmdmdbdfnolnobccbnolnofdbdmdmdmdmdmdbaaa
+aaabeeeeeeeeeeeceeeeeeecppceeeeeeeceeeeeeeeeeebaaa
+aaabeeeeeeeeeeeceeeeeeecppceeeeeeeceeeeeeeeeeebaaa
+aaabbbbbbbbbbbbbdfnolnobccbnolnoqdbbbbbbbbbbbbbaaa
+aaaaaaaaaaaaaaabbegcegcheehcgecgebbaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaabeegecgreeigcegeebaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaabbeceeeleeleeecebbaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaabegcgcheehcgcgebaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaabeeeegreeigeeeebaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaabbbbeefeefeebbbbaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaabbbdeedbbbaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaabbccbbaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaabbbbaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+"}
diff --git a/code/_globalvars/mapping.dm b/code/_globalvars/mapping.dm
index 841fbced3f7..4915b91f3d0 100644
--- a/code/_globalvars/mapping.dm
+++ b/code/_globalvars/mapping.dm
@@ -40,6 +40,7 @@ var/list/prisonwarped = list() //list of players already warped
var/list/blobstart = list()
var/list/ninjastart = list()
var/list/carplist = list() //list of all carp-spawn landmarks
+var/list/avatarspawn = list()
//away missions
var/list/awaydestinations = list() //a list of landmarks that the warpgate can take you to
@@ -51,4 +52,5 @@ var/list/datum/map_template/ruins_templates = list()
var/list/datum/map_template/space_ruins_templates = list()
var/list/datum/map_template/lava_ruins_templates = list()
var/list/datum/map_template/shelter_templates = list()
-var/list/datum/map_template/shuttle_templates = list()
\ No newline at end of file
+var/list/datum/map_template/shuttle_templates = list()
+var/list/datum/map_template/vr_templates = list()
\ No newline at end of file
diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm
index ead199814f3..1ecf89de0fe 100644
--- a/code/datums/helper_datums/map_template.dm
+++ b/code/datums/helper_datums/map_template.dm
@@ -114,6 +114,7 @@
preloadRuinTemplates()
preloadShelterTemplates()
preloadShuttleTemplates()
+ preloadVRTemplates()
/proc/preloadRuinTemplates()
// Still supporting bans by filename
@@ -163,4 +164,15 @@
var/datum/map_template/shuttle/S = new shuttle_type()
shuttle_templates[S.shuttle_id] = S
- map_templates[S.shuttle_id] = S
\ No newline at end of file
+ map_templates[S.shuttle_id] = S
+
+/proc/preloadVRTemplates()
+ for(var/item in subtypesof(/datum/map_template/vr))
+ var/datum/map_template/vr/vr_type = item
+ if(!initial(vr_type.suffix))
+ continue
+
+ var/datum/map_template/vr/V = new vr_type()
+
+ vr_templates[V.id] = V
+ map_templates[V.id] = V
\ No newline at end of file
diff --git a/code/datums/spells/lightning.dm b/code/datums/spells/lightning.dm
index bb2bb133d71..257e98346d2 100644
--- a/code/datums/spells/lightning.dm
+++ b/code/datums/spells/lightning.dm
@@ -15,13 +15,15 @@
var/image/halo = null
action_icon_state = "lightning"
var/sound/Snd // so far only way i can think of to stop a sound, thank MSO for the idea.
+ var/damaging = TRUE
/obj/effect/proc_holder/spell/targeted/lightning/lightnian
clothes_req = 0
invocation_type = "none"
+ damaging = 0
/obj/effect/proc_holder/spell/targeted/lightning/Click()
- if(!ready && start_time==0)
+ if(!ready && start_time == 0)
if(cast_check())
StartChargeup()
else
@@ -32,12 +34,12 @@
/obj/effect/proc_holder/spell/targeted/lightning/proc/StartChargeup(mob/user = usr)
ready = 1
to_chat(user, "You start gathering the power.")
- Snd = new/sound('sound/magic/lightning_chargeup.ogg',channel = 7)
+ Snd = new/sound('sound/magic/lightning_chargeup.ogg', channel = 7)
halo = image("icon"='icons/effects/effects.dmi',"icon_state" ="electricity","layer" = EFFECTS_LAYER)
user.overlays.Add(halo)
playsound(get_turf(user), Snd, 50, 0)
start_time = world.time
- if(do_mob(user,user,100,uninterruptible=1))
+ if(do_mob(user, user, 100, uninterruptible=1))
if(ready)
Discharge()
@@ -61,9 +63,9 @@ obj/effect/proc_holder/spell/targeted/lightning/proc/Reset(mob/user = usr)
/obj/effect/proc_holder/spell/targeted/lightning/cast(list/targets, mob/user = usr)
ready = 0
- var/mob/living/carbon/target = targets[1]
- Snd=sound(null, repeat = 0, wait = 1, channel = Snd.channel) //byond, why you suck?
- playsound(get_turf(user),Snd,50,0)// Sorry MrPerson, but the other ways just didn't do it the way i needed to work, this is the only way.
+ var/mob/living/target = targets[1]
+ Snd = sound(null, repeat = 0, wait = 1, channel = Snd.channel) //byond, why you suck?
+ playsound(get_turf(user), Snd, 50, 0)// Sorry MrPerson, but the other ways just didn't do it the way i needed to work, this is the only way.
if(get_dist(user,target)>range)
to_chat(user, "They are too far away!")
Reset(user)
@@ -73,17 +75,37 @@ obj/effect/proc_holder/spell/targeted/lightning/proc/Reset(mob/user = usr)
user.Beam(target,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5)
var/energy = min(world.time - start_time,100)
- Bolt(user,target,max(15,energy/2),5,user) //5 bounces for energy/2 burn
+ if(damaging)
+ Bolt(user,target,max(15,energy/2),5,user) //5 bounces for energy/2 burn
+ else
+ var/bounces = round(energy/20)
+ Bolt(user,target,0,bounces,user)
Reset(user)
-/obj/effect/proc_holder/spell/targeted/lightning/proc/Bolt(mob/origin, mob/target, bolt_energy, bounces, mob/user = usr)
- origin.Beam(target,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5)
- var/mob/living/carbon/current = target
+/obj/effect/proc_holder/spell/targeted/lightning/proc/Bolt(mob/origin, mob/living/target, bolt_energy, bounces, mob/user = usr)
+ origin.Beam(target,icon_state="lightning[rand(1,12)]", icon='icons/effects/effects.dmi', time=5)
+ var/mob/living/current = target
if(bounces < 1)
- current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
+ if(damaging)
+ current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
+ else
+ current.AdjustJitter(1000) //High numbers for violent convulsions
+ current.do_jitter_animation(current.jitteriness)
+ current.AdjustStuttering(2)
+ current.Slowed(3)
+ spawn(20)
+ current.AdjustJitter(-1000, bound_lower = 10) //Still jittery, but vastly less
playsound(get_turf(current), 'sound/magic/LightningShock.ogg', 50, 1, -1)
else
- current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
+ if(damaging)
+ current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
+ else
+ current.AdjustJitter(1000) //High numbers for violent convulsions
+ current.do_jitter_animation(current.jitteriness)
+ current.AdjustStuttering(2)
+ current.Slowed(3)
+ spawn(20)
+ current.AdjustJitter(-1000, bound_lower = 10) //Still jittery, but vastly less
playsound(get_turf(current), 'sound/magic/LightningShock.ogg', 50, 1, -1)
var/list/possible_targets = new
for(var/mob/living/M in view_or_range(range,target,"view"))
diff --git a/code/datums/spells/magnet.dm b/code/datums/spells/magnet.dm
index 100dd881dde..8a6e9c525c4 100644
--- a/code/datums/spells/magnet.dm
+++ b/code/datums/spells/magnet.dm
@@ -12,34 +12,37 @@
random_target = 1
var/energy = 0
var/ready = 0
+ var/start_time = 0
var/image/halo = null
+ var/sound/Snd // so far only way i can think of to stop a sound, thank MSO for the idea.
action_icon_state = "tech"
/obj/effect/proc_holder/spell/targeted/magnet/Click()
- if(!ready)
+ if(!ready && start_time == 0)
if(cast_check())
StartChargeup()
else
- if(cast_check(skipcharge=1))
+ if(ready && cast_check(skipcharge=1))
choose_targets()
return 1
/obj/effect/proc_holder/spell/targeted/magnet/proc/StartChargeup(mob/user = usr)
ready = 1
to_chat(user, "You start gathering the power.")
+ Snd = new/sound('sound/magic/lightning_chargeup.ogg', channel = 7)
halo = image("icon"='icons/effects/effects.dmi',"icon_state" ="electricity","layer" = EFFECTS_LAYER)
user.overlays.Add(halo)
- spawn(0)
- while(ready)
- sleep(1)
- energy++
- if(energy >= 100 && ready)
- Discharge()
+ playsound(get_turf(user), Snd, 50, 0)
+ start_time = world.time
+ if(do_mob(user, user, 100, uninterruptible=1))
+ if(ready)
+ Discharge()
obj/effect/proc_holder/spell/targeted/magnet/proc/Reset(mob/user = usr)
ready = 0
energy = 0
+ start_time = 0
if(halo)
user.overlays.Remove(halo)
@@ -50,16 +53,16 @@ obj/effect/proc_holder/spell/targeted/magnet/proc/Reset(mob/user = usr)
/obj/effect/proc_holder/spell/targeted/magnet/proc/Discharge(mob/user = usr)
var/mob/living/M = user
- //M.electrocute_act(25,"magnet Bolt")
to_chat(M, "You lose control over the power.")
Reset(user)
start_recharge()
/obj/effect/proc_holder/spell/targeted/magnet/cast(list/targets, mob/user = usr)
-
- var/mob/living/carbon/target = targets[1]
-
+ ready = 0
+ var/mob/living/target = targets[1]
+ Snd = sound(null, repeat = 0, wait = 1, channel = Snd.channel) //byond, why you suck?
+ playsound(get_turf(user), Snd, 50, 0)// Sorry MrPerson, but the other ways just didn't do it the way i needed to work, this is the only way.
if(get_dist(user,target)>range)
to_chat(user, "They are too far away!")
Reset(user)
@@ -88,13 +91,13 @@ obj/effect/proc_holder/spell/targeted/magnet/proc/Reset(mob/user = usr)
playsound(get_turf(target), 'sound/machines/defib_zap.ogg', 50, 1, -1)
if(75 to 100)
//CHAIN magnet
- Bolt(user,target,energy,user)
+ Bolt(user,target,energy,5,user)
Reset(user)
-/obj/effect/proc_holder/spell/targeted/magnet/proc/Bolt(mob/origin,mob/target,bolt_energy,mob/user = usr)
- origin.Beam(target,icon_state="lightning",icon='icons/effects/effects.dmi',time=5)
+/obj/effect/proc_holder/spell/targeted/magnet/proc/Bolt(mob/origin,mob/target,bolt_energy,bounces, mob/user = usr)
+ origin.Beam(target, icon_state="lightning", icon='icons/effects/effects.dmi', time=5)
var/mob/living/carbon/current = target
- if(bolt_energy < 75)
+ if(bounces < 1)
for(var/obj/item/I in target.l_hand)
if(I.flags & CONDUCT)
I.throw_at(user, I.throw_range, 4, target)
@@ -119,4 +122,4 @@ obj/effect/proc_holder/spell/targeted/magnet/proc/Reset(mob/user = usr)
return
var/mob/living/next = pick(possible_targets)
if(next)
- Bolt(current,next,bolt_energy-6,user) // 5 max bounces
\ No newline at end of file
+ Bolt(current,next,bolt_energy,bounces-1,user) // 5 max bounces
\ No newline at end of file
diff --git a/code/datums/vr.dm b/code/datums/vr.dm
new file mode 100644
index 00000000000..4d31b6a2072
--- /dev/null
+++ b/code/datums/vr.dm
@@ -0,0 +1,15 @@
+/datum/map_template/vr
+ name = null
+ var/id = null // For blacklisting purposes, all vr levels need an id
+ var/description = "This is a placeholder. Please contact your virtual adminsitrator if you see this."
+ var/outfit = null
+
+ var/prefix = null
+ var/suffix = null
+
+/datum/map_template/vr/New()
+ if(!name && id)
+ name = id
+
+ mappath = prefix + suffix
+ ..(path = mappath)
\ No newline at end of file
diff --git a/code/datums/vr/level.dm b/code/datums/vr/level.dm
new file mode 100644
index 00000000000..d3feca26ad9
--- /dev/null
+++ b/code/datums/vr/level.dm
@@ -0,0 +1,16 @@
+/datum/map_template/vr/level
+ prefix = "_maps/map_files/vr/"
+
+/datum/map_template/vr/level/lobby
+ id = "lobby"
+ suffix = "lobby.dmm"
+ name = "Virtual Hub Facility"
+ description = "This is the lobby. The hub for all things VR."
+ outfit = /datum/outfit/vr/vr_basic
+
+/datum/map_template/vr/level/roman
+ id = "roman"
+ suffix = "blood_and_sand.dmm"
+ name = "Blood and Sand Arena"
+ description = "To the Death!"
+ outfit = /datum/outfit/vr/roman
\ No newline at end of file
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index c572023fc3f..e814bc9081f 100644
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -2582,6 +2582,22 @@ area/security/podbay
/area/awaycontent/a30
icon_state = "awaycontent30"
+////////////////////////VR AREAS///////////////////////////////////
+
+/area/vr
+ name = "VR"
+ requires_power = 0
+ dynamic_lighting = 0
+ no_teleportlocs = 1
+
+
+/area/vr/lobby
+ name = "VR Lobby"
+
+/area/vr/roman
+ name = "Roman Arena"
+
+
/////////////////////////////////////////////////////////////////////
/*
Lists of areas to be used with is_type_in_list.
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index 86e85da4fb0..a9e0c49a122 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -20,37 +20,43 @@
#define DNA_UI_HAIR_R 1
#define DNA_UI_HAIR_G 2
#define DNA_UI_HAIR_B 3
-#define DNA_UI_BEARD_R 4
-#define DNA_UI_BEARD_G 5
-#define DNA_UI_BEARD_B 6
-#define DNA_UI_SKIN_TONE 7
-#define DNA_UI_SKIN_R 8
-#define DNA_UI_SKIN_G 9
-#define DNA_UI_SKIN_B 10
-#define DNA_UI_HACC_R 11
-#define DNA_UI_HACC_G 12
-#define DNA_UI_HACC_B 13
-#define DNA_UI_HEAD_MARK_R 14
-#define DNA_UI_HEAD_MARK_G 15
-#define DNA_UI_HEAD_MARK_B 16
-#define DNA_UI_BODY_MARK_R 17
-#define DNA_UI_BODY_MARK_G 18
-#define DNA_UI_BODY_MARK_B 19
-#define DNA_UI_TAIL_MARK_R 20
-#define DNA_UI_TAIL_MARK_G 21
-#define DNA_UI_TAIL_MARK_B 22
-#define DNA_UI_EYES_R 23
-#define DNA_UI_EYES_G 24
-#define DNA_UI_EYES_B 25
-#define DNA_UI_GENDER 26
-#define DNA_UI_BEARD_STYLE 27
-#define DNA_UI_HAIR_STYLE 28
+#define DNA_UI_HAIR2_R 4
+#define DNA_UI_HAIR2_G 5
+#define DNA_UI_HAIR2_B 6
+#define DNA_UI_BEARD_R 7
+#define DNA_UI_BEARD_G 8
+#define DNA_UI_BEARD_B 9
+#define DNA_UI_BEARD2_R 10
+#define DNA_UI_BEARD2_G 11
+#define DNA_UI_BEARD2_B 12
+#define DNA_UI_SKIN_TONE 13
+#define DNA_UI_SKIN_R 14
+#define DNA_UI_SKIN_G 15
+#define DNA_UI_SKIN_B 16
+#define DNA_UI_HACC_R 17
+#define DNA_UI_HACC_G 18
+#define DNA_UI_HACC_B 19
+#define DNA_UI_HEAD_MARK_R 20
+#define DNA_UI_HEAD_MARK_G 21
+#define DNA_UI_HEAD_MARK_B 22
+#define DNA_UI_BODY_MARK_R 23
+#define DNA_UI_BODY_MARK_G 24
+#define DNA_UI_BODY_MARK_B 25
+#define DNA_UI_TAIL_MARK_R 26
+#define DNA_UI_TAIL_MARK_G 27
+#define DNA_UI_TAIL_MARK_B 28
+#define DNA_UI_EYES_R 29
+#define DNA_UI_EYES_G 30
+#define DNA_UI_EYES_B 31
+#define DNA_UI_GENDER 32
+#define DNA_UI_BEARD_STYLE 33
+#define DNA_UI_HAIR_STYLE 34
/*#define DNA_UI_BACC_STYLE 23*/
-#define DNA_UI_HACC_STYLE 29
-#define DNA_UI_HEAD_MARK_STYLE 30
-#define DNA_UI_BODY_MARK_STYLE 31
-#define DNA_UI_TAIL_MARK_STYLE 32
-#define DNA_UI_LENGTH 32 // Update this when you add something, or you WILL break shit.
+#define DNA_UI_HACC_STYLE 35
+#define DNA_UI_HEAD_MARK_STYLE 36
+#define DNA_UI_BODY_MARK_STYLE 37
+#define DNA_UI_TAIL_MARK_STYLE 38
+#define DNA_UI_LENGTH 38 // Update this when you add something, or you WILL break shit.
#define DNA_SE_LENGTH 55 // Was STRUCDNASIZE, size 27. 15 new blocks added = 42, plus room to grow.
diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm
index 743a8ebbe5c..c5f9ce2b7fe 100644
--- a/code/game/dna/dna2_helpers.dm
+++ b/code/game/dna/dna2_helpers.dm
@@ -132,8 +132,11 @@
dna.check_integrity()
var/mob/living/carbon/human/H = src
var/obj/item/organ/external/head/head_organ = H.get_organ("head")
+ var/obj/item/organ/internal/eyes/eye_organ = H.get_int_organ(/obj/item/organ/internal/eyes)
var/datum/species/S = H.species
dna.write_head_attributes(head_organ)
+ dna.write_eyes_attributes(eye_organ)
+ H.update_eyes()
H.r_skin = dna.GetUIValueRange(DNA_UI_SKIN_R, 255)
H.g_skin = dna.GetUIValueRange(DNA_UI_SKIN_G, 255)
@@ -190,6 +193,10 @@
head_organ.g_hair = GetUIValueRange(DNA_UI_HAIR_G, 255)
head_organ.b_hair = GetUIValueRange(DNA_UI_HAIR_B, 255)
+ head_organ.r_hair_sec = GetUIValueRange(DNA_UI_HAIR2_R, 255)
+ head_organ.g_hair_sec = GetUIValueRange(DNA_UI_HAIR2_G, 255)
+ head_organ.b_hair_sec = GetUIValueRange(DNA_UI_HAIR2_B, 255)
+
//Facial Hair
var/beard = GetUIValueRange(DNA_UI_BEARD_STYLE,facial_hair_styles_list.len)
if((beard > 0) && (beard <= facial_hair_styles_list.len))
@@ -199,6 +206,10 @@
head_organ.g_facial = GetUIValueRange(DNA_UI_BEARD_G, 255)
head_organ.b_facial = GetUIValueRange(DNA_UI_BEARD_B, 255)
+ head_organ.r_facial_sec = GetUIValueRange(DNA_UI_BEARD2_R, 255)
+ head_organ.g_facial_sec = GetUIValueRange(DNA_UI_BEARD2_G, 255)
+ head_organ.b_facial_sec = GetUIValueRange(DNA_UI_BEARD2_B, 255)
+
//Head Accessories
var/headacc = GetUIValueRange(DNA_UI_HACC_STYLE,head_accessory_styles_list.len)
if((headacc > 0) && (headacc <= head_accessory_styles_list.len))
@@ -256,10 +267,18 @@
SetUIValueRange(DNA_UI_HAIR_G, H.g_hair, 255, 1)
SetUIValueRange(DNA_UI_HAIR_B, H.b_hair, 255, 1)
+ SetUIValueRange(DNA_UI_HAIR2_R, H.r_hair_sec, 255, 1)
+ SetUIValueRange(DNA_UI_HAIR2_G, H.g_hair_sec, 255, 1)
+ SetUIValueRange(DNA_UI_HAIR2_B, H.b_hair_sec, 255, 1)
+
SetUIValueRange(DNA_UI_BEARD_R, H.r_facial, 255, 1)
SetUIValueRange(DNA_UI_BEARD_G, H.g_facial, 255, 1)
SetUIValueRange(DNA_UI_BEARD_B, H.b_facial, 255, 1)
+ SetUIValueRange(DNA_UI_BEARD2_R, H.r_facial_sec, 255, 1)
+ SetUIValueRange(DNA_UI_BEARD2_G, H.g_facial_sec, 255, 1)
+ SetUIValueRange(DNA_UI_BEARD2_B, H.b_facial_sec, 255, 1)
+
SetUIValueRange(DNA_UI_HACC_R, H.r_headacc, 255, 1)
SetUIValueRange(DNA_UI_HACC_G, H.g_headacc, 255, 1)
SetUIValueRange(DNA_UI_HACC_B, H.b_headacc, 255, 1)
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index 112b13c6a4f..fc2ad7d62f9 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -37,8 +37,9 @@
var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
var/list/player_draft_log = list()
var/list/datum/mind/xenos = list()
-
+
var/list/datum/station_goal/station_goals = list() // A list of all station goals for this game mode
+ var/list/chumps = list()
/datum/game_mode/proc/announce() //to be calles when round starts
to_chat(world, "Notice: [src] did not define announce()")
@@ -71,6 +72,8 @@
///post_setup()
///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things
/datum/game_mode/proc/post_setup()
+ setup_chumps()
+
spawn (ROUNDSTART_LOGOUT_REPORT_TIME)
display_roundstart_logout_report()
@@ -85,6 +88,40 @@
start_state.count()
return 1
+//setup_chumps()
+//Prepares fake potential collaborators to cut down on metagaming the round type as being a traitor subtype. Overriden in traitor game modes since they have real collaborators
+/datum/game_mode/proc/setup_chumps()
+ var/max_chumps = 1
+ if(config.traitor_scaling)
+ max_chumps = max(1, round((num_players())/(5)))
+ else
+ max_chumps = max(1, min(num_players(), 5))
+ var/tries_left = 5 //limits the number of tries so we don't get stuck looping indefinitely. resets on successfully finding a new chump
+ while(chumps.len < max_chumps)
+ if(!tries_left) //ran out of unique chumps (or just bad luck with the pick() in get_nt_opposed()) so there may end up being fewer chumps in some rounds.
+ break
+ var/mob/living/carbon/human/chump = get_nt_opposed()
+ if(isnull(chump)) //no possible chumps so just end it here.
+ break
+ if(chump in chumps)
+ tries_left-- //this chump already was picked, try again!
+ else
+ chumps += chump
+ tries_left = 5 //reset our tries since we found a new chump
+ //make sure we have chumps before we try misinforming them. if we don't make a note of it.
+ if(!chumps.len)
+ message_admins("Game mode failed to find ANY chumps. Possible causes: no one is opposed/skeptical, or FalseIncarnate can't code.")
+ log_admin("Game mode failed to find ANY chumps. Possible causes: no one is opposed/skeptical, or FalseIncarnate can't code.")
+ return 0
+ //we've got chumps! misinform them!
+ for(var/mob/living/carbon/human/chump in chumps)
+ if(prob(33))
+ spawn(rand(3000, 18000)) //5-30 minute delay to throw off would-be autotraitor metagamers
+ inform_collab(chump)
+ else
+ spawn(rand(10, 100)) //same delay as if the mode were traitor
+ inform_collab(chump)
+ return 1
///process()
///Called by the gameticker
@@ -225,7 +262,7 @@
/datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere.
return 0
-
+
/datum/game_mode/proc/get_players_for_role(var/role, override_jobbans=0)
var/list/players = list()
var/list/candidates = list()
@@ -400,15 +437,20 @@ proc/display_roundstart_logout_report()
to_chat(M, msg)
-proc/get_nt_opposed()
+/proc/get_nt_opposed()
var/list/dudes = list()
for(var/mob/living/carbon/human/man in player_list)
if(man.client)
+ //don't try picking someone like the captain or a security officer for potential collaborators, even if they ARE opposed to Nanotrasen for some reason
+ if(man.mind && man.mind.assigned_role)
+ if((man.mind.assigned_role in ticker.mode.protected_jobs) || (man.mind.assigned_role in ticker.mode.restricted_jobs))
+ continue
if(man.client.prefs.nanotrasen_relation == "Opposed")
dudes += man
else if(man.client.prefs.nanotrasen_relation == "Skeptical" && prob(50))
dudes += man
- if(dudes.len == 0) return null
+ if(dudes.len == 0)
+ return null
return pick(dudes)
//Announces objectives/generic antag text.
@@ -491,10 +533,10 @@ proc/get_nt_opposed()
var/datum/station_goal/picked = pick_n_take(possible)
goal_weights += initial(picked.weight)
station_goals += new picked
-
- if(station_goals.len)
+
+ if(station_goals.len)
send_station_goals_message()
-
+
/datum/game_mode/proc/send_station_goals_message()
var/message_text = "

"
message_text += "
[command_name()] Orders
"
@@ -504,10 +546,34 @@ proc/get_nt_opposed()
G.on_report()
message_text += G.get_report()
message_text += "
"
-
+
print_command_report(message_text, "[command_name()] Orders")
/datum/game_mode/proc/declare_station_goal_completion()
for(var/V in station_goals)
var/datum/station_goal/G = V
- G.print_result()
\ No newline at end of file
+ G.print_result()
+
+
+/datum/game_mode/proc/inform_collab(mob/living/carbon/human/M)
+ if(!M)
+ return
+ //Mad-libs for their message
+ var/adjective = pick("strange", "mysterious", "sinister", "un-assuming", "unexpected")
+ var/action_words = pick("aid the fight against Nanotrasen", "repay a debt", "partake in some mischief", "help overthrow the system", "stick it to the man")
+ var/organization = pick("Anti-Fascist Movement", "Syndicate", "Spessmen for the Protesting of Nanotrasen", "Greytider's Union", "Illuminati (in space)")
+ //Stuff to give them a single set of code-words
+ var/list/possible_words = splittext(syndicate_code_phrase, ", ")
+ var/list/possible_reply = splittext(syndicate_code_response, ", ")
+ var/index = rand(1, possible_words.len)
+ var/my_word = possible_words[index]
+ var/my_reply
+ if(possible_reply.len < index) //just in case we had a longer code word list than the response list
+ my_reply = pick(possible_reply)
+ else
+ my_reply = possible_reply[index]
+
+ to_chat(M, "You suddenly remember \an [adjective] note you received earlier informing you that a chance to [action_words] may present itself today. An agent of the [organization] may contact you for help.")
+ to_chat(M, "The note had the words \"[my_word]\" and \"[my_reply]\" written at the bottom, which you memorized just in case.")
+ to_chat(M, "You are NOT an antagonist, so self-antagging rules still apply to you. Use your good judgement and ahelp if you are unsure of what you are allowed to do.")
+ M.mind.store_memory("Important Words: \"[my_word]\", \"[my_reply]\"")
diff --git a/code/game/gamemodes/intercept_report.dm b/code/game/gamemodes/intercept_report.dm
index cd6dd80876b..6cb2956d3ee 100644
--- a/code/game/gamemodes/intercept_report.dm
+++ b/code/game/gamemodes/intercept_report.dm
@@ -109,8 +109,16 @@
/datum/intercept_text/proc/get_suspect()
var/list/dudes = list()
- for(var/mob/living/carbon/human/man in player_list) if(man.client && man.client.prefs.nanotrasen_relation == "Opposed")
- dudes += man
+ for(var/mob/living/carbon/human/man in player_list)
+ if(man.client && man.client.prefs.nanotrasen_relation == "Opposed")
+ //don't include suspects who can't possibly be the antag based on their job (no suspecting the captain of being a damned dirty tator)
+ if(man.mind && man.mind.assigned_role)
+ if((man.mind.assigned_role in ticker.mode.protected_jobs) || (man.mind.assigned_role in ticker.mode.restricted_jobs))
+ return
+ //don't include suspects who can't possibly be the antag based on their species (no suspecting the machines of being sneaky changelings)
+ if(man.get_species() in ticker.mode.protected_species)
+ return
+ dudes += man
for(var/i = 0, i < max(player_list.len/10,2), i++)
dudes += pick(player_list)
return pick(dudes)
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index 371aef6c6a0..e60b564f5d0 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -70,6 +70,9 @@
modePlayer += traitors
..()
+/datum/game_mode/traitor/setup_chumps()
+ //since we actually have potential collaborators, we don't prepare any chumps to avoid extra people knowing our codewords.
+ return
/datum/game_mode/proc/forge_traitor_objectives(datum/mind/traitor)
if(istype(traitor.current, /mob/living/silicon))
@@ -345,6 +348,14 @@
if(M && M != traitor_mob)
to_chat(traitor_mob, "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them.")
traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]")
+ //let's also inform their contact that they might be called upon, but leave it vague.
+ inform_collab(M)
+
+/datum/game_mode/traitor/inform_collab(mob/living/carbon/human/M)
+ if(M.mind in traitors) //if you are already a traitor, you already know the codewords and your role, so skip this message.
+ return
+ ..(M)
+
/datum/game_mode/proc/remove_traitor(datum/mind/traitor_mind)
if(traitor_mind in traitors)
@@ -355,8 +366,8 @@
to_chat(traitor_mind.current, "You have been turned into a robot! You are no longer a traitor.")
else
to_chat(traitor_mind.current, "You have been brainwashed! You are no longer a traitor.")
- ticker.mode.update_traitor_icons_removed(traitor_mind)
-
+ ticker.mode.update_traitor_icons_removed(traitor_mind)
+
/datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind)
var/datum/atom_hud/antag/tatorhud = huds[ANTAG_HUD_TRAITOR]
tatorhud.join_hud(traitor_mind.current)
diff --git a/code/game/jobs/job/support_chaplain.dm b/code/game/jobs/job/support_chaplain.dm
index 637524ad3bd..8ff51148b9f 100644
--- a/code/game/jobs/job/support_chaplain.dm
+++ b/code/game/jobs/job/support_chaplain.dm
@@ -34,6 +34,8 @@
var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible(H)
spawn()
+ H.equip_to_slot_or_del(B, slot_l_hand)
+
var/religion_name = "Christianity"
var/new_religion = sanitize(copytext(input(H, "You are the crew services officer. Would you like to change your religion? Default is Christianity, in SPACE.", "Name change", religion_name),1,MAX_NAME_LEN))
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index 390496842ab..b3957234d01 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -122,10 +122,11 @@
//data = "0C80C80C80C80C80C8000000000000161FBDDEF" - Farmer Jeff
buf.dna.real_name="God Emperor of Mankind"
buf.dna.unique_enzymes = md5(buf.dna.real_name)
- buf.dna.UI=list(0x066,0x000,0x033,0x000,0x000,0x000,0xAF0,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x033,0x066,0x0FF,0x4DB,0x002,0x690,0x000,0x000)
+ buf.dna.UI=list(0x066,0x000,0x033,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0xAF0,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x033,0x066,0x0FF,0x4DB,0x002,0x690,0x000,0x000,0x000,0x328,0x045,0x5FC,0x053,0x035,0x035,0x035)
//buf.dna.UI=list(0x0C8,0x0C8,0x0C8,0x0C8,0x0C8,0x0C8,0x000,0x000,0x000,0x000,0x161,0xFBD,0xDEF) // Farmer Jeff
- for(var/i in buf.dna.UI.len to DNA_UI_LENGTH)
- buf.dna.UI += 0x000
+ if(buf.dna.UI.len != DNA_UI_LENGTH) //If there's a disparity b/w the dna UI string lengths, 0-fill the extra blocks in this UI.
+ for(var/i in buf.dna.UI.len to DNA_UI_LENGTH)
+ buf.dna.UI += 0x000
buf.dna.ResetSE()
buf.dna.UpdateUI()
diff --git a/code/game/machinery/computer/vr_control.dm b/code/game/machinery/computer/vr_control.dm
new file mode 100644
index 00000000000..b1fded03b99
--- /dev/null
+++ b/code/game/machinery/computer/vr_control.dm
@@ -0,0 +1,37 @@
+/obj/machinery/computer/vr_control
+ name = "VR console"
+ desc = "A list and control panel for all virtual servers."
+ icon_screen = "comm_logs"
+
+ light_color = LIGHT_COLOR_DARKGREEN
+
+
+/obj/machinery/computer/vr_control/New()
+ ..()
+
+/obj/machinery/computer/vr_control/Destroy()
+ return ..()
+
+/obj/machinery/computer/vr_control/attack_ai(mob/user)
+ attack_hand(user)
+ ui_interact(user)
+
+
+/obj/machinery/computer/vr_control/attack_hand(mob/user)
+ add_fingerprint(user)
+ if(stat & (BROKEN|NOPOWER))
+ return
+ ui_interact(user)
+
+/obj/machinery/computer/vr_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ switch(alert("What would you like to do?", "VR Control", "Join Room", "Make Room", "Cancel"))
+ if("Join Room")
+ spawn_vr_avatar(user, input(user, "Choose a room to join.","Select Level") as null|anything in vr_rooms)
+ qdel(user)
+ if("Make Room")
+ make_vr_room(input(user, "Name your new Room","Name here.") as null|text, input(user, "Choose a Level to load into your new Room.","Select Level") as null|anything in vr_templates)
+ if("Cancel")
+ return
+
+/obj/machinery/computer/vr_control/interact(mob/user)
+
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index c6dacede143..fe802eb308b 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -189,7 +189,6 @@
opacity = 0
assembly_type = /obj/structure/door_assembly/door_assembly_research
glass = 1
- heat_proof = 1
/obj/machinery/door/airlock/glass_mining
name = "Maintenance Hatch"
@@ -847,6 +846,7 @@ About the new airlock wires panel:
to_chat(user, "You removed the airlock electronics!")
var/obj/structure/door_assembly/da = new assembly_type(loc)
+ da.heat_proof_finished = heat_proof //tracks whether there's rglass in
da.anchored = 1
if(mineral)
da.glass = mineral
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 2a42b71e7f2..d6b295e1811 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -23,7 +23,7 @@
var/normalspeed = 1
var/auto_close_time = 150
var/auto_close_time_dangerous = 5
- var/heat_proof = 0 // For glass airlocks/opacity firedoors
+ var/heat_proof = 0 // For rglass-windowed airlocks and firedoors
var/emergency = 0
var/air_properties_vary_with_direction = 0
var/block_air_zones = 1 //If set, air zones cannot merge across the door even when it is opened.
@@ -310,7 +310,7 @@
if(!glass && cameranet)
cameranet.updateVisibility(src, 0)
-/obj/machinery/door/BlockSuperconductivity()
+/obj/machinery/door/BlockSuperconductivity() // All non-glass airlocks block heat, this is intended.
if(opacity || heat_proof)
return 1
return 0
diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm
index dc156972f6e..1f83484ae70 100644
--- a/code/game/machinery/doors/poddoor.dm
+++ b/code/game/machinery/doors/poddoor.dm
@@ -3,8 +3,9 @@
desc = "That looks like it doesn't open easily."
icon = 'icons/obj/doors/rapid_pdoor.dmi'
icon_state = "pdoor1"
- var/id_tag = 1.0
explosion_block = 3
+ heat_proof = 1
+ var/id_tag = 1.0
var/protected = 1
/obj/machinery/door/poddoor/preopen
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index 7ff80f248da..e5b1098e2d0 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -20,6 +20,9 @@
wizardstart += loc
qdel(src)
+ if("avatarspawn")
+ avatarspawn += loc
+
if("JoinLate")
latejoin += loc
qdel(src)
@@ -251,7 +254,7 @@
new /obj/item/clothing/mask/gas/sexymime(src.loc)
new /obj/item/clothing/under/sexymime(src.loc)
qdel(src)
-
+
/obj/effect/landmark/ruin
var/datum/map_template/ruin/ruin_template
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index c84c6a84de8..76ade089d9b 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -579,7 +579,9 @@
item_state = "zippo"
storage_slots = 10
w_class = 1
+ max_w_class = 1
slot_flags = SLOT_BELT
+ can_hold = list(/obj/item/weapon/match)
New()
..()
diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm
index ec68cd16e3e..b8ab485512a 100644
--- a/code/game/objects/structures/door_assembly.dm
+++ b/code/game/objects/structures/door_assembly.dm
@@ -13,6 +13,7 @@
var/glass_type = "/glass"
var/glass = 0 // 0 = glass can be installed. -1 = glass can't be installed. 1 = glass is already installed. Text = mineral plating is installed instead.
var/created_name = null
+ var/heat_proof_finished = 0 //whether to heat-proof the finished airlock
/obj/structure/door_assembly/New()
update_state()
@@ -176,7 +177,11 @@
if(do_after(user, 40 * WT.toolspeed, target = src))
if(!src || !WT.isOn()) return
to_chat(user, "You welded the glass panel out!")
- new /obj/item/stack/sheet/rglass(src.loc)
+ if(heat_proof_finished)
+ new /obj/item/stack/sheet/rglass(get_turf(src))
+ heat_proof_finished = 0
+ else
+ new /obj/item/stack/sheet/glass(get_turf(src))
glass = 0
else if(!anchored)
user.visible_message("[user] disassembles the airlock assembly.", "You start to disassemble the airlock assembly.")
@@ -257,11 +262,15 @@
var/obj/item/stack/sheet/S = W
if(S)
if(S.amount>=1)
- if(istype(S, /obj/item/stack/sheet/rglass))
+ if(istype(S, /obj/item/stack/sheet/rglass) || istype(S, /obj/item/stack/sheet/glass))
playsound(src.loc, S.usesound, 100, 1)
user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.")
if(do_after(user, 40 * S.toolspeed, target = src))
- to_chat(user, "You installed reinforced glass windows into the airlock assembly!")
+ if(S.type == /obj/item/stack/sheet/rglass)
+ to_chat(user, "You install reinforced glass windows into the airlock assembly.")
+ heat_proof_finished = 1 //reinforced glass makes the airlock heat-proof
+ else
+ to_chat(user, "You install regular glass windows into the airlock assembly.")
S.use(1)
glass = 1
else if(istype(S, /obj/item/stack/sheet/mineral) && S.sheettype)
@@ -292,6 +301,7 @@
door.setDir(dir)
door.assembly_type = type
door.electronics = src.electronics
+ door.heat_proof = heat_proof_finished
if(src.electronics.one_access)
door.req_access = null
door.req_one_access = src.electronics.conf_access
@@ -318,4 +328,4 @@
name = "Wired "
if(2)
name = "Near Finished "
- name += "[glass == 1 ? "Window " : ""][istext(glass) ? "[glass] Airlock" : base_name] Assembly"
\ No newline at end of file
+ name += "[heat_proof_finished ? "Heat-Proofed " : ""][glass == 1 ? "Window " : ""][istext(glass) ? "[glass] Airlock" : base_name] Assembly"
diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
index 54540ab008b..b32f47520e4 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
@@ -1,6 +1,7 @@
/obj/structure/stool/bed/chair/wheelchair
name = "wheelchair"
desc = "You sit in this. Either by will or force."
+ icon = 'icons/obj/objects.dmi'
icon_state = "wheelchair"
anchored = 0
movable = 1
@@ -9,7 +10,7 @@
/obj/structure/stool/bed/chair/wheelchair/handle_rotation()
overlays = null
- var/image/O = image(icon = 'icons/obj/objects.dmi', icon_state = "w_overlay", layer = FLY_LAYER, dir = src.dir)
+ var/image/O = image(icon = icon, icon_state = "[icon_state]_overlay", layer = FLY_LAYER, dir = src.dir)
overlays += O
if(buckled_mob)
buckled_mob.dir = dir
@@ -152,10 +153,3 @@
else
. = 1
-
-/obj/structure/stool/bed/chair/wheelchair/bike/handle_rotation()
- overlays = null
- var/image/O = image(icon = 'icons/vehicles/motorcycle.dmi', icon_state = "motorcycle_overlay_4d", layer = FLY_LAYER, dir = src.dir)
- overlays += O
- if(buckled_mob)
- buckled_mob.dir = dir
\ No newline at end of file
diff --git a/code/modules/VR/vr_avatar.dm b/code/modules/VR/vr_avatar.dm
new file mode 100644
index 00000000000..510871fb40a
--- /dev/null
+++ b/code/modules/VR/vr_avatar.dm
@@ -0,0 +1,87 @@
+
+
+/mob/living/carbon/human/virtual_reality
+ var/mob/living/carbon/human/real_me //The human controlling us, can be any human (including virtual ones... inception...)
+ var/datum/action/quit_vr/quit_action
+ var/datum/action/back_to_lobby/back_to_lobby
+ var/datum/action/detach_from_avatar/detach_from_avatar
+
+/mob/living/carbon/human/virtual_reality/New()
+ quit_action = new()
+ quit_action.Grant(src)
+ back_to_lobby = new()
+ back_to_lobby.Grant(src)
+ detach_from_avatar = new()
+ detach_from_avatar.Grant(src)
+ ..()
+
+/mob/living/carbon/human/virtual_reality/death()
+ return_to_lobby()
+ return ..()
+
+/mob/living/carbon/human/virtual_reality/Destroy()
+ return_to_lobby()
+ return ..()
+
+/mob/living/carbon/human/virtual_reality/ghost()
+ set category = "OOC"
+ set name = "Ghost"
+ set desc = "Relinquish your life and enter the land of the dead."
+ var/mob/living/carbon/human/H = real_me
+ revert_to_reality(FALSE)
+ if(H)
+ H.ghost()
+ qdel(src)
+
+/mob/living/carbon/human/virtual_reality/proc/revert_to_reality(remove = 0)
+ if(real_me && mind)
+ mind.transfer_to(real_me)
+ real_me.EyeBlind(2)
+ real_me.Confused(2)
+ if(remove)
+ qdel(src)
+ else
+ return src
+
+/mob/living/carbon/human/virtual_reality/proc/return_to_lobby()
+ if(real_me && mind)
+ var/mob/living/carbon/human/virtual_reality/new_vr
+ new_vr = spawn_vr_avatar(src, "Lobby")
+ var/obj/item/clothing/glasses/vr_goggles/g = new_vr.real_me.glasses
+ g.vr_human = new_vr
+ qdel(src)
+
+/datum/action/quit_vr
+ name = "Quit Virtual Reality"
+
+/datum/action/quit_vr/Trigger()
+ if(..())
+ if(istype(owner, /mob/living/carbon/human/virtual_reality))
+ var/mob/living/carbon/human/virtual_reality/vr = owner
+ vr.revert_to_reality(1)
+ else
+ Remove(owner)
+
+/datum/action/back_to_lobby
+ name = "Return To Lobby"
+
+/datum/action/back_to_lobby/Trigger()
+ if(..())
+ if(istype(owner, /mob/living/carbon/human/virtual_reality))
+ var/mob/living/carbon/human/virtual_reality/vr = owner
+ vr.return_to_lobby()
+ else
+ Remove(owner)
+
+/datum/action/detach_from_avatar
+ name = "Detach From Avatar"
+
+/datum/action/detach_from_avatar/Trigger()
+ if(..())
+ if(istype(owner, /mob/living/carbon/human/virtual_reality))
+ var/mob/living/carbon/human/virtual_reality/vr = owner
+ var/obj/item/clothing/glasses/vr_goggles/g = vr.real_me.glasses
+ g.vr_human = vr
+ vr.revert_to_reality(0)
+ else
+ Remove(owner)
diff --git a/code/modules/VR/vr_goggles.dm b/code/modules/VR/vr_goggles.dm
new file mode 100644
index 00000000000..c2a185b0ffa
--- /dev/null
+++ b/code/modules/VR/vr_goggles.dm
@@ -0,0 +1,41 @@
+//Glorified teleporter that puts you in a new human body.
+// it's """VR"""
+
+/obj/item/clothing/glasses/vr_goggles
+ desc = "A long time ago, people used these glasses to makes images from screens threedimensional."
+ name = "3D glasses"
+ icon_state = "3d"
+ item_state = "3d"
+ prescription_upgradable = 0
+ species_fit = list("Vox")
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ )
+
+ var/you_die_in_the_game_you_die_for_real = FALSE
+ var/mob/living/carbon/human/virtual_reality/vr_human
+
+
+/obj/item/clothing/glasses/vr_goggles/Destroy()
+ ..()
+ vr_human.revert_to_reality(1)
+ cleanup_vr_avatar()
+
+/obj/item/clothing/glasses/vr_goggles/dropped()
+ ..()
+ if(vr_human)
+ vr_human.revert_to_reality(0)
+
+/obj/item/clothing/glasses/vr_goggles/proc/cleanup_vr_avatar()
+ if(vr_human)
+ vr_human = null
+
+/obj/item/clothing/glasses/vr_goggles/equipped()
+ ..()
+ var/mob/living/carbon/human/H = loc
+ spawn(1)
+ if(H.glasses == src)
+ if(vr_human == null)
+ vr_human = spawn_vr_avatar(H, "Lobby")
+ else
+ control_remote(H, vr_human)
\ No newline at end of file
diff --git a/code/modules/client/preference/loadout/loadout_hat.dm b/code/modules/client/preference/loadout/loadout_hat.dm
index 7e4ca4620d9..2abfd08f8ce 100644
--- a/code/modules/client/preference/loadout/loadout_hat.dm
+++ b/code/modules/client/preference/loadout/loadout_hat.dm
@@ -118,6 +118,11 @@
path = /obj/item/clothing/head/beret/sci
allowed_roles = list("Research Director", "Scientist")
+/datum/gear/hat/med_beret
+ display_name = "medical beret"
+ path = /obj/item/clothing/head/beret/med
+ allowed_roles = list("Chief Medical Officer", "Medical Doctor" , "Virologist", "Brig Physician")
+
/datum/gear/hat/surgicalcap_purple
display_name = "surgical cap, purple"
path = /obj/item/clothing/head/surgery/purple
diff --git a/code/modules/client/preference/loadout/loadout_uniform.dm b/code/modules/client/preference/loadout/loadout_uniform.dm
index b7b768561d9..82ccc357312 100644
--- a/code/modules/client/preference/loadout/loadout_uniform.dm
+++ b/code/modules/client/preference/loadout/loadout_uniform.dm
@@ -50,7 +50,7 @@
/datum/gear/uniform/skirt/job/cmo
display_name = "skirt, cmo"
- path = /obj/item/clothing/under/rank/chief_medical_officer
+ path = /obj/item/clothing/under/rank/chief_medical_officer/skirt
allowed_roles = list("Chief Medical Officer")
/datum/gear/uniform/skirt/job/chem
diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm
index 5d6dde79848..9c76701c2bb 100644
--- a/code/modules/clothing/head/jobs.dm
+++ b/code/modules/clothing/head/jobs.dm
@@ -129,6 +129,11 @@
icon_state = "beret_sci"
//Medical
+/obj/item/clothing/head/beret/med
+ name = "medical beret"
+ desc = "A white beret with a green cross finely threaded into it. It has that sterile smell about it."
+ icon_state = "beret_med"
+
/obj/item/clothing/head/surgery
name = "surgical cap"
desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs."
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 220781a8bfb..319c0fd5fce 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -379,9 +379,6 @@
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
actions_types = list(/datum/action/item_action/caw)
-/obj/item/clothing/head/griffin/super_hero
- flags = BLOCKHAIR|NODROP
-
/obj/item/clothing/head/griffin/attack_self()
caw()
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index 49c3c3d2392..09ec70e6729 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -167,8 +167,6 @@
icon_state = "griffinboots"
item_state = "griffinboots"
-/obj/item/clothing/shoes/griffin/super_hero
- flags = NODROP
/obj/item/clothing/shoes/fluff/noble_boot
name = "noble boots"
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 2c7272f92d0..a835550ed44 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -817,8 +817,6 @@
allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/device/flashlight/seclite)
actions_types = list(/datum/action/item_action/toggle_wings)
-/obj/item/clothing/suit/toggle/owlwings/super_hero
- flags = NODROP
/obj/item/clothing/suit/toggle/owlwings/griffinwings
name = "griffon cloak"
@@ -826,9 +824,6 @@
icon_state = "griffin_wings"
item_state = "griffin_wings"
-/obj/item/clothing/suit/toggle/owlwings/griffinwings/super_hero
- flags = NODROP
-
/obj/item/clothing/suit/toggle/attack_self()
if(icon_state == initial(icon_state))
icon_state = icon_state + "_t"
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 33100a474a0..d388db29b5c 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -729,18 +729,12 @@
icon_state = "owl"
item_color = "owl"
-/obj/item/clothing/under/owl/super_hero
- flags = NODROP
-
/obj/item/clothing/under/griffin
name = "griffon uniform"
desc = "A soft brown jumpsuit with a white feather collar made of synthetic feathers and a lust for mayhem."
icon_state = "griffin"
item_color = "griffin"
-/obj/item/clothing/under/griffin/super_hero
- flags = NODROP
-
/obj/item/clothing/under/noble_clothes
name = "noble clothes"
desc = "They fall just short of majestic."
diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm
index 6cc353d0b17..7a9620a1d1a 100644
--- a/code/modules/customitems/item_defines.dm
+++ b/code/modules/customitems/item_defines.dm
@@ -129,6 +129,12 @@
icon_state = "zeldacrowbar"
item_state = "crowbar"
+/obj/item/clothing/glasses/monocle/fluff/trubus //Trubus: Wolf O'Shaw
+ name = "Gold Thermal Eyepatch"
+ desc = "Wolf's non-functional thermal eyepatch."
+ icon = 'icons/obj/custom_items.dmi'
+ icon_state = "wolf_eyepatch"
+
/obj/item/clothing/glasses/meson/fluff/book_berner_1 // Adrkiller59: Adam Cooper
name = "bespectacled mesonic surveyors"
desc = "One of the older meson scanner models retrofitted to perform like its modern counterparts."
@@ -140,6 +146,28 @@
desc = "A weathered Vox thermonocle, doesn't seem to work anymore."
icon_state = "thermoncle"
+/obj/item/device/fluff/rapid_wheelchair_kit //Rapidvalj: Hakikarahiti
+ name = "wheelchair conversion kit"
+ desc = "An assorted set of exchangable parts for a wheelchair."
+ icon_state = "modkit"
+
+/obj/item/device/fluff/rapid_wheelchair_kit/afterattack(atom/target, mob/user, proximity)
+ if(!proximity || !ishuman(user) || user.incapacitated())
+ return
+
+ if(istype(target, /obj/structure/stool/bed/chair/wheelchair) && !istype(target, /obj/structure/stool/bed/chair/wheelchair/bike))
+ to_chat(user, "You modify the appearance of [target].")
+ var/obj/structure/stool/bed/chair/wheelchair/chair = target
+ chair.icon = 'icons/obj/custom_items.dmi'
+ chair.icon_state = "vox_wheelchair"
+ chair.name = "vox wheelchair"
+ chair.desc = "A luxurious Vox Wheelchair, weathered from use."
+ chair.handle_rotation()
+ qdel(src)
+ return
+
+ to_chat(user, "You can't modify [target]!")
+
/obj/item/weapon/lighter/zippo/fluff/purple // GodOfOreos: Jason Conrad
name = "purple engraved zippo"
desc = "All craftsspacemanship is of the highest quality. It is encrusted with refined plasma sheets. On the item is an image of a dwarf and the words 'Strike the Earth!' etched onto the side."
@@ -248,7 +276,6 @@
if(istype(target, /obj/item/weapon/melee/baton) && !istype(target, /obj/item/weapon/melee/baton/cattleprod))
to_chat(user, "You modify the appearance of [target].")
- //because batons use the initial() proc, we can't just swap the icon state, sadly
var/obj/item/weapon/melee/baton/the_baton = target
the_baton.base_icon = "desolate_baton"
the_baton.item_state = "desolate_baton"
@@ -353,6 +380,7 @@
/obj/item/clothing/glasses/hud/security/sunglasses/fluff/voxxyhud //LP Spartan: Kaskreyarawkta
name = "VoxxyHUD"
desc = "A worn down visor from a vox raider's gear, crudely ripped from its helmet and linked into the security systems of the station. The word 'Kask' is scratched into the side."
+ icon = 'icons/obj/custom_items.dmi'
icon_state = "hud-spartan"
//////////// Hats ////////////
@@ -368,13 +396,12 @@
desc = "Fuzzy, and also stained with blood."
icon = 'icons/obj/custom_items.dmi'
icon_state = "polarbearpelt"
- item_state = "polarbearpelt"
/obj/item/clothing/head/fluff/sparkyninja_beret // Sparkyninja: Neil Wilkinson
name = "royal marines commando beret"
desc = "Dark Green beret with an old insignia on it."
+ icon = 'icons/obj/custom_items.dmi'
icon_state = "sparkyninja_beret"
- item_state = "sparkyninja_beret"
/obj/item/clothing/head/beret/fluff/sigholt //sigholtstarsong: Sigholt Starsong
name = "Lieutenant Starsong's beret"
@@ -405,25 +432,29 @@
/obj/item/clothing/head/beret/fluff/linda //Epic_Charger: Linda Clark
name = "Green beret"
desc = "A beret, an artist's favorite headwear. This one has two holes cut on the edges."
+ icon = 'icons/obj/custom_items.dmi'
icon_state = "linda_beret"
/obj/item/clothing/head/fluff/kaki //Rapidvalj: Kakicharakiti
name = "sleek fancy leader hat"
desc = "A uniquely colored vox leader hat. Has some signs of wear."
+ icon = 'icons/obj/custom_items.dmi'
icon_state = "kakicharakiti"
//////////// Suits ////////////
+/obj/item/clothing/suit/fluff
+ icon = 'icons/obj/custom_items.dmi'
+ actions_types = list()
+ ignore_suitadjust = 1
+ adjust_flavour = null
+ species_fit = null
+ sprite_sheets = null
+
/obj/item/clothing/suit/fluff/dusty_jacket //ComputerlessCitizen: Screech
name = "Dusty Jacket"
desc = "A worn leather jacket. Some burn holes have been patched."
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- icon = 'icons/obj/custom_items.dmi'
icon_state = "dusty_jacket"
- ignore_suitadjust = 1
- actions_types = list()
- adjust_flavour = null
- species_fit = null
- sprite_sheets = null
/obj/item/clothing/suit/storage/labcoat/fluff/aeneas_rinil //Socialsystem: Lynn Fea
name = "Robotics labcoat"
@@ -448,6 +479,7 @@
/obj/item/clothing/suit/fluff/kluys // Kluys: Cripty Pandaen
name = "Nano Fibre Jacket"
desc = "A Black Suit made out of nanofibre. The newest of cyberpunk fashion using hightech liquid to solid materials."
+ icon = 'icons/obj/custom_items.dmi'
icon_state = "Kluysfluff1"
item_state = "Kluysfluff1"
blood_overlay_type = "coat"
@@ -494,15 +526,29 @@
/obj/item/clothing/suit/hooded/hoodie/fluff/linda // Epic_Charger: Linda Clark
name = "Green Nanotrasen Hoodie"
desc = "A green hoodie with the Nanotrasen logo on the back. It looks weathered."
+ icon = 'icons/obj/custom_items.dmi'
icon_state = "linda_hoodie"
hoodtype = /obj/item/clothing/head/hood/fluff/linda
/obj/item/clothing/head/hood/fluff/linda //Epic_Charger: Linda Clark
icon_state = "greenhood"
+/obj/item/clothing/suit/hooded/fluff/bone //Doru7: Jack Bone
+ name = "skeleton suit"
+ desc = "A spooky full-body suit! This one doesn't glow in the dark."
+ body_parts_covered = HEAD|UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
+ icon = 'icons/obj/custom_items.dmi'
+ icon_state = "skeleton_suit"
+ hoodtype = /obj/item/clothing/head/hood/fluff/skeleton
+
+/obj/item/clothing/head/hood/fluff/skeleton
+ icon = 'icons/obj/custom_items.dmi'
+ icon_state = "skeleton_hood"
+
/obj/item/clothing/suit/armor/shodanscoat // RazekPraxis: SHODAN
name = "SHODAN's Captain's Coat"
desc = "A black coat with gold trim and an old US Chevron printed on the back. Edgy."
+ icon = 'icons/obj/custom_items.dmi'
icon_state = "shodancoat"
//////////// Uniforms ////////////
@@ -523,6 +569,15 @@
item_color = "elishirt"
displays_id = 0
+/obj/item/clothing/under/fluff/jay_turtleneck // Jayfeather: Jay Wingler
+ name = "Mar's Pattern Custom Turtleneck"
+ desc = "It seems to be lightly dusted in orange fuzz, and damp with the smell of anti-freeze. It has a strange symbol in the middle."
+ icon = 'icons/obj/custom_items.dmi'
+ icon_state = "jaywingler"
+ item_state = "jaywingler"
+ item_color = "jaywingler"
+ displays_id = 0
+
/obj/item/clothing/under/psysuit/fluff/isaca_sirius_1 // Xilia: Isaca Sirius
name = "Isaca's suit"
desc = "Black, comfortable and nicely fitting suit. Made not to hinder the wearer in any way. Made of some exotic fabric. And some strange glowing jewel at the waist. Name labels says; Property of Isaca Sirius; The Seeder."
@@ -569,6 +624,9 @@
/obj/item/clothing/under/fluff/aegis //PlagueWalker: A.E.G.I.S.
name = "gilded waistcoat"
desc = "This black, gold-trimmed, rather expensive-looking uniform laced with fine materials appears comfortable despite its stiffness."
+ icon = 'icons/obj/custom_items.dmi'
+ lefthand_file = 'icons/mob/inhands/fluff_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/fluff_righthand.dmi'
icon_state = "aegisuniform"
item_state = "aegisuniform"
item_color = "aegisuniform"
@@ -579,9 +637,9 @@
/obj/item/clothing/mask/bandana/fluff/dar //sasanek12: Dar'Konr
name = "camo bandana"
desc = "It's a worn-out bandana in camo paint"
+ icon = 'icons/obj/custom_items.dmi'
icon_state = "bandcamo"
-
/obj/item/clothing/mask/gas/sechailer/fluff/spartan //LP Spartan: Kaskreyarawkta
name = "minimal gasmask"
desc = "Designed to cover as little of face as possible while still being a functional gasmask."
@@ -723,6 +781,7 @@
/obj/item/weapon/storage/backpack/fluff/krich_back //lizardzsi: Krichahka
name = "Voxcaster"
desc = "Battered, Sol-made military radio backpack that had its speakers fried from playing Vox opera. The words 'Swift-Talon' are crudely scratched onto its side."
+ icon = 'icons/obj/custom_items.dmi'
icon_state = "voxcaster_fluff"
/obj/item/clothing/head/wizard/fake/fluff/dreamy //phantasmicdream : Dreamy Rockwall
diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm
index 2d691cbf652..4a340c1bb24 100644
--- a/code/modules/mob/emote.dm
+++ b/code/modules/mob/emote.dm
@@ -13,6 +13,16 @@
return 0 // Proceed with emote
//--FalseIncarnate
+/mob/proc/handle_emote_param(var/target, var/not_self, var/vicinity, var/return_mob) //Only returns not null if the target param is valid.
+ var/view_vicinity = vicinity ? vicinity : null //not_self means we'll only return if target is valid and not us
+ if(target) //vicinity is the distance passed to the view proc.
+ for(var/mob/A in view(view_vicinity, null)) //if set, return_mob will cause this proc to return the mob instead of just its name if the target is valid.
+ if(target == A.name && (!not_self || (not_self && target != name)))
+ if(return_mob)
+ return A
+ else
+ return target
+
// All mobs should have custom emote, really..
/mob/proc/custom_emote(var/m_type=1,var/message = null)
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index b0a7dfd57a0..e88468e2018 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -85,162 +85,73 @@
if("me") //OKAY SO RANT TIME, THIS FUCKING HAS TO BE HERE OR A SHITLOAD OF THINGS BREAK
return custom_emote(m_type, message) //DO YOU KNOW WHY SHIT BREAKS? BECAUSE SO MUCH OLDCODE CALLS mob.emote("me",1,"whatever_the_fuck_it_wants_to_emote")
//WHO THE FUCK THOUGHT THAT WAS A GOOD FUCKING IDEA!?!?
-
if("ping", "pings")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param) //Check to see if the param is valid (mob with the param name is in view).
- if(param)
- message = "[src] pings at [param]."
- else
- message = "[src] pings."
+ message = "[src] pings[M ? " at [M]" : ""]."
playsound(loc, 'sound/machines/ping.ogg', 50, 0)
m_type = 2
if("buzz2")
- message = "[src] emits an irritated buzzing sound."
+ var/M = handle_emote_param(param)
+
+ message = "[src] emits an irritated buzzing sound[M ? " at [M]" : ""]."
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
m_type = 2
if("buzz", "buzzes")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] buzzes at [param]."
- else
- message = "[src] buzzes."
+ message = "[src] buzzes[M ? " at [M]" : ""]."
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
m_type = 2
if("beep", "beeps")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] beeps at [param]."
- else
- message = "[src] beeps."
+ message = "[src] beeps[M ? " at [M]" : ""]."
playsound(loc, 'sound/machines/twobeep.ogg', 50, 0)
m_type = 2
if("drone", "drones", "hum", "hums", "rumble", "rumbles")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] drones at [param]."
- else
- message = "[src] rumbles."
+ message = "[src] [M ? "drones at [M]" : "rumbles"]."
playsound(loc, 'sound/voice/DraskTalk.ogg', 50, 0)
m_type = 2
if("squish", "squishes")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] squishes at [param]."
- else
- message = "[src] squishes."
+ message = "[src] squishes[M ? " at [M]" : ""]."
playsound(loc, 'sound/effects/slime_squish.ogg', 50, 0) //Credit to DrMinky (freesound.org) for the sound.
m_type = 2
if("clack", "clacks")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] clacks their mandibles at [param]."
- else
- message = "[src] clacks their mandibles."
+ message = "[src] clacks their mandibles[M ? " at [M]" : ""]."
playsound(loc, 'sound/effects/Kidanclack.ogg', 50, 0) //Credit to DrMinky (freesound.org) for the sound.
m_type = 2
if("click", "clicks")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] clicks their mandibles at [param]."
- else
- message = "[src] clicks their mandibles."
+ message = "[src] clicks their mandibles[M ? " at [M]" : ""]."
playsound(loc, 'sound/effects/Kidanclack2.ogg', 50, 0) //Credit to DrMinky (freesound.org) for the sound.
m_type = 2
if("yes")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] emits an affirmative blip at [param]."
- else
- message = "[src] emits an affirmative blip."
+ message = "[src] emits an affirmative blip[M ? " at [M]" : ""]."
playsound(loc, 'sound/machines/synth_yes.ogg', 50, 0)
m_type = 2
if("no")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] emits a negative blip at [param]."
- else
- message = "[src] emits a negative blip."
+ message = "[src] emits a negative blip[M ? " at [M]" : ""]."
playsound(loc, 'sound/machines/synth_no.ogg', 50, 0)
m_type = 2
@@ -293,36 +204,16 @@
if("bow", "bows")
if(!buckled)
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] bows to [param]."
- else
- message = "[src] bows."
+ message = "[src] bows[M ? " to [M]" : ""]."
m_type = 1
if("salute", "salutes")
if(!buckled)
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] salutes to [param]."
- else
- message = "[src] salutes."
+ message = "[src] salutes[M ? " to [M]" : ""]."
m_type = 1
if("choke", "chokes")
@@ -461,11 +352,15 @@
m_type = 2
if("frown", "frowns")
- message = "[src] frowns."
+ var/M = handle_emote_param(param)
+
+ message = "[src] frowns[M ? " at [M]" : ""]."
m_type = 1
if("nod", "nods")
- message = "[src] nods."
+ var/M = handle_emote_param(param)
+
+ message = "[src] nods[M ? " at [M]" : ""]."
m_type = 1
if("blush", "blushes")
@@ -473,7 +368,9 @@
m_type = 1
if("wave", "waves")
- message = "[src] waves."
+ var/M = handle_emote_param(param)
+
+ message = "[src] waves[M ? " at [M]" : ""]."
m_type = 1
if("quiver", "quivers")
@@ -509,56 +406,27 @@
m_type = 2
if("glare", "glares")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] glares at [param]."
- else
- message = "[src] glares."
+ message = "[src] glares[M ? " at [M]" : ""]."
m_type = 1
if("stare", "stares")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] stares at [param]."
- else
- message = "[src] stares."
+ message = "[src] stares[M ? " at [M]" : ""]."
m_type = 1
if("look", "looks")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
+ var/M = handle_emote_param(param)
- if(!M)
- param = null
-
- if(param)
- message = "[src] looks at [param]."
- else
- message = "[src] looks."
+ message = "[src] looks[M ? " at [M]" : ""]."
m_type = 1
if("grin", "grins")
- message = "[src] grins."
+ var/M = handle_emote_param(param)
+
+ message = "[src] grins[M ? " at [M]" : ""]."
m_type = 1
if("cry", "cries")
@@ -574,24 +442,26 @@
m_type = 2
if("sigh", "sighs")
+ var/M = handle_emote_param(param)
if(miming)
- message = "[src] sighs."
+ message = "[src] sighs[M ? " at [M]" : ""]."
m_type = 1
else
if(!muzzled)
- message = "[src] sighs."
+ message = "[src] sighs[M ? " at [M]" : ""]."
m_type = 2
else
- message = "[src] makes a weak noise."
+ message = "[src] makes a weak noise"
m_type = 2
if("laugh", "laughs")
+ var/M = handle_emote_param(param)
if(miming)
- message = "[src] acts out a laugh."
+ message = "[src] acts out a laugh[M ? " at [M]" : ""]."
m_type = 1
else
if(!muzzled)
- message = "[src] laughs."
+ message = "[src] laughs[M ? " at [M]" : ""]."
m_type = 2
else
message = "[src] makes a noise."
@@ -604,11 +474,12 @@
m_type = 1
if("grumble", "grumbles")
+ var/M = handle_emote_param(param)
if(miming)
- message = "[src] grumbles!"
+ message = "[src] grumbles[M ? " at [M]" : ""]!"
m_type = 1
if(!muzzled)
- message = "[src] grumbles!"
+ message = "[src] grumbles[M ? " at [M]" : ""]!"
m_type = 2
else
message = "[src] makes a noise."
@@ -669,7 +540,9 @@
m_type = 1
if("shake", "shakes")
- message = "[src] shakes \his head."
+ var/M = handle_emote_param(param, 1) //Check to see if the param is valid (mob with the param name is in view) but exclude ourselves.
+
+ message = "[src] shakes \his head[M ? " at [M]" : ""]."
m_type = 1
if("shrug", "shrugs")
@@ -687,7 +560,9 @@
m_type = 1
if("smile", "smiles")
- message = "[src] smiles."
+ var/M = handle_emote_param(param, 1)
+
+ message = "[src] smiles[M ? " at [M]" : ""]."
m_type = 1
if("shiver", "shivers")
@@ -751,7 +626,9 @@
m_type = 2
if("wink", "winks")
- message = "[src] winks."
+ var/M = handle_emote_param(param, 1)
+
+ message = "[src] winks[M ? " at [M]" : ""]."
m_type = 1
if("yawn", "yawns")
@@ -771,14 +648,7 @@
if("hug", "hugs")
m_type = 1
if(!restrained())
- var/M = null
- if(param)
- for(var/mob/A in view(1, null))
- if(param == A.name)
- M = A
- break
- if(M == src)
- M = null
+ var/M = handle_emote_param(param, 1, 1) //Check to see if the param is valid (mob with the param name is in view) but exclude ourselves and only check mobs in our immediate vicinity (1 tile distance).
if(M)
message = "[src] hugs [M]."
@@ -788,14 +658,7 @@
if("handshake")
m_type = 1
if(!restrained() && !r_hand)
- var/mob/M = null
- if(param)
- for(var/mob/A in view(1, null))
- if(param == A.name)
- M = A
- break
- if(M == src)
- M = null
+ var/mob/M = handle_emote_param(param, 1, 1, 1) //Check to see if the param is valid (mob with the param name is in view) but exclude ourselves, only check mobs in our immediate vicinity (1 tile distance) and return the whole mob instead of just its name.
if(M)
if(M.canmove && !M.r_hand && !M.restrained())
@@ -806,12 +669,8 @@
if("dap", "daps")
m_type = 1
if(!restrained())
- var/M = null
- if(param)
- for(var/mob/A in view(1, null))
- if(param == A.name)
- M = A
- break
+ var/M = handle_emote_param(param, null, 1)
+
if(M)
message = "[src] gives daps to [M]."
else
@@ -820,27 +679,23 @@
if("slap", "slaps")
m_type = 1
if(!restrained())
- var/M = null
- if(param)
- for(var/mob/A in view(1, null))
- if(param == A.name)
- M = A
- break
+ var/M = handle_emote_param(param, null, 1)
+
if(M)
message = "[src] slaps [M] across the face. Ouch!"
- playsound(loc, 'sound/effects/snap.ogg', 50, 1)
else
message = "[src] slaps \himself!"
- playsound(loc, 'sound/effects/snap.ogg', 50, 1)
adjustFireLoss(4)
+ playsound(loc, 'sound/effects/snap.ogg', 50, 1)
if("scream", "screams")
+ var/M = handle_emote_param(param)
if(miming)
- message = "[src] acts out a scream!"
+ message = "[src] acts out a scream[M ? " at [M]" : ""]!"
m_type = 1
else
if(!muzzled)
- message = "[src] [species.scream_verb]!"
+ message = "[src] [species.scream_verb][M ? " at [M]" : ""]!"
m_type = 2
if(gender == FEMALE)
playsound(loc, "[species.female_scream_sound]", 80, 1, 0, pitch = get_age_pitch())
@@ -848,10 +703,9 @@
playsound(loc, "[species.male_scream_sound]", 80, 1, 0, pitch = get_age_pitch()) //default to male screams if no gender is present.
else
- message = "[src] makes a very loud noise."
+ message = "[src] makes a very loud noise[M ? " at [M]" : ""]."
m_type = 2
-
if("snap", "snaps")
if(prob(95))
m_type = 2
@@ -869,13 +723,14 @@
to_chat(usr, "You need at least one hand in good working order to snap your fingers.")
return
- message = "[src] snaps \his fingers."
+ var/M = handle_emote_param(param)
+
+ message = "[src] snaps \his fingers[M ? " at [M]" : ""]."
playsound(loc, 'sound/effects/fingersnap.ogg', 50, 1, -3)
else
message = "[src] snaps \his fingers right off!"
playsound(loc, 'sound/effects/snap.ogg', 50, 1)
-
// Needed for M_TOXIC_FART
if("fart", "farts")
if(reagents.has_reagent("simethicone"))
@@ -926,11 +781,7 @@
else
to_chat(src, "Unusable emote '[act]'. Say *help for a list.")
-
-
-
-
- if(message) //Humans are special fucking snowflakes and have 735 lines of emotes, they get to handle their own emotes, not call the parent
+ if(message) //Humans are special fucking snowflakes and have 800 lines of emotes, they get to handle their own emotes, not call the parent.
log_emote("[name]/[key] : [message]")
//Hearing gasp and such every five seconds is not good emotes were not global for a reason.
diff --git a/code/modules/mob/living/carbon/superheroes.dm b/code/modules/mob/living/carbon/superheroes.dm
index 7a8ab4c0701..ce9fe15ae6e 100644
--- a/code/modules/mob/living/carbon/superheroes.dm
+++ b/code/modules/mob/living/carbon/superheroes.dm
@@ -14,15 +14,19 @@
assign_genes(H)
assign_spells(H)
equip(H)
+ fixflags(H)
assign_id(H)
/datum/superheroes/proc/equip(var/mob/living/carbon/human/H)
H.rename_character(H.real_name, name)
- for(var/obj/item/W in H)
- if(istype(W,/obj/item/organ)) continue
+ for(var/obj/item/W in H.get_all_slots())
H.unEquip(W)
H.equip_to_slot_or_del(new /obj/item/device/radio/headset(H), slot_l_ear)
+/datum/superheroes/proc/fixflags(var/mob/living/carbon/human/H)
+ for(var/obj/item/W in H.get_all_slots())
+ W.flags |= NODROP
+
/datum/superheroes/proc/assign_genes(var/mob/living/carbon/human/H)
if(default_genes.len)
for(var/gene in default_genes)
@@ -42,14 +46,17 @@
W.registered_name = H.real_name
W.access = list(access_maint_tunnels)
if(class == "Superhero")
- W.name = "[H.real_name]'s ID Card (Superhero)"
W.assignment = "Superhero"
+ W.rank = "Superhero"
ticker.mode.superheroes += H.mind
else if(class == "Supervillain")
- W.name = "[H.real_name]'s ID Card (Supervillain)"
W.assignment = "Supervillain"
+ W.rank = "Supervillain"
ticker.mode.supervillains += H.mind
-
+ W.icon_state = "lifetimeid"
+ W.SetOwnerInfo(H)
+ W.UpdateName()
+ W.flags |= NODROP
H.equip_to_slot_or_del(W, slot_wear_id)
H.regenerate_icons()
@@ -66,8 +73,8 @@
..()
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black/greytide(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/owl/super_hero(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/owlwings/super_hero(H), slot_wear_suit)
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/owl(H), slot_w_uniform)
+ H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/owlwings(H), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/owl_mask/super_hero(H), slot_wear_mask)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/bluespace/owlman(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/clothing/glasses/night(H), slot_glasses)
@@ -84,15 +91,13 @@
/datum/superheroes/griffin/equip(var/mob/living/carbon/human/H)
..()
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/griffin/super_hero(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/under/griffin/super_hero(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/owlwings/griffinwings/super_hero(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/clothing/head/griffin/super_hero(H), slot_head)
+ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/griffin(H), slot_shoes)
+ H.equip_to_slot_or_del(new /obj/item/clothing/under/griffin(H), slot_w_uniform)
+ H.equip_to_slot_or_del(new /obj/item/clothing/suit/toggle/owlwings/griffinwings(H), slot_wear_suit)
+ H.equip_to_slot_or_del(new /obj/item/clothing/head/griffin/(H), slot_head)
var/obj/item/weapon/implant/freedom/L = new/obj/item/weapon/implant/freedom(H)
- L.imp_in = H
- L.implanted = 1
- return 1
+ L.implant(H, H)
/datum/superheroes/lightnian
@@ -217,18 +222,20 @@
target.s_tone = 35
// No `update_dna=0` here because the character is being over-written
target.change_eye_color(1,1,1)
- for(var/obj/item/W in target)
- if(istype(W,/obj/item/organ)) continue
+ for(var/obj/item/W in target.get_all_slots())
target.unEquip(W)
target.rename_character(target.real_name, "Generic Henchman ([rand(1, 1000)])")
target.equip_to_slot_or_del(new /obj/item/clothing/under/color/grey/greytide(target), slot_w_uniform)
target.equip_to_slot_or_del(new /obj/item/clothing/shoes/black/greytide(target), slot_shoes)
target.equip_to_slot_or_del(new /obj/item/weapon/storage/toolbox/mechanical/greytide(target), slot_l_hand)
- var/obj/item/weapon/card/id/syndicate/W = new(target)
- W.registered_name = target.real_name
- W.access = list(access_maint_tunnels)
- W.name = "[target.real_name]'s ID Card (Greyshirt)"
- W.assignment = "Greyshirt"
- target.equip_to_slot_or_del(W, slot_wear_id)
target.equip_to_slot_or_del(new /obj/item/device/radio/headset(target), slot_l_ear)
+ var/obj/item/weapon/card/id/syndicate/W = new(target)
+ W.icon_state = "lifetimeid"
+ W.access = list(access_maint_tunnels)
+ W.assignment = "Greyshirt"
+ W.rank = "Greyshirt"
+ W.flags |= NODROP
+ W.SetOwnerInfo(target)
+ W.UpdateName()
+ target.equip_to_slot_or_del(W, slot_wear_id)
target.regenerate_icons()
diff --git a/code/modules/mob/living/silicon/emote.dm b/code/modules/mob/living/silicon/emote.dm
index 9e95b9cefaa..3385c4ce622 100644
--- a/code/modules/mob/living/silicon/emote.dm
+++ b/code/modules/mob/living/silicon/emote.dm
@@ -26,97 +26,51 @@
switch(act)
if("ping","pings")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] pings at [param]."
- else
- message = "[src] pings."
+ message = "[src] pings[M ? " at [M]" : ""]."
playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
m_type = 2
if("buzz","buzzs","buzzes")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] buzzes at [param]."
- else
- message = "[src] buzzes."
+ message = "[src] buzzes[M ? " at [M]" : ""]."
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
m_type = 2
if("beep","beeps")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] beeps at [param]."
- else
- message = "[src] beeps."
+ message = "[src] beeps[M ? " at [M]" : ""]."
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
m_type = 2
if("yes")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] emits an affirmative blip at [param]."
- else
- message = "[src] emits an affirmative blip."
+ message = "[src] emits an affirmative blip[M ? " at [M]" : ""]."
playsound(src.loc, 'sound/machines/synth_yes.ogg', 50, 0)
m_type = 2
if("no")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] emits a negative blip at [param]."
- else
- message = "[src] emits a negative blip."
+ message = "[src] emits a negative blip[M ? " at [M]" : ""]."
playsound(src.loc, 'sound/machines/synth_no.ogg', 50, 0)
m_type = 2
if("scream", "screams")
- message = "[src] screams!"
+ var/M = handle_emote_param(param)
+
+ message = "[src] screams[M ? " at [M]" : ""]!"
playsound(src.loc, 'sound/goonstation/voice/robot_scream.ogg', 80, 0)
m_type = 2
if("buzz2")
- message = "[src] emits an irritated buzzing sound."
+ var/M = handle_emote_param(param)
+
+ message = "[src] emits an irritated buzzing sound[M ? " at [M]" : ""]."
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
m_type = 2
@@ -124,4 +78,4 @@
if("help")
to_chat(src, "yes, no, beep, ping, buzz, scream, buzz2")
- ..(act, m_type, message)
\ No newline at end of file
+ ..(act, m_type, message)
diff --git a/code/modules/mob/living/simple_animal/bot/emote.dm b/code/modules/mob/living/simple_animal/bot/emote.dm
index 1bf29d14178..70e27937745 100644
--- a/code/modules/mob/living/simple_animal/bot/emote.dm
+++ b/code/modules/mob/living/simple_animal/bot/emote.dm
@@ -28,92 +28,44 @@
switch(act)
if("ping")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] pings at [param]."
- else
- message = "[src] pings."
+ message = "[src] pings[M ? " at [M]" : ""]."
playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
m_type = 2
if("buzz")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] buzzes at [param]."
- else
- message = "[src] buzzes."
+ message = "[src] buzzes[M ? " at [M]" : ""]."
playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
m_type = 2
if("beep")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] beeps at [param]."
- else
- message = "[src] beeps."
+ message = "[src] beeps[M ? " at [M]" : ""]."
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
m_type = 2
if("yes")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] emits an affirmative blip at [param]."
- else
- message = "[src] emits an affirmative blip."
+ message = "[src] emits an affirmative blip[M ? " at [M]" : ""]."
playsound(src.loc, 'sound/machines/synth_yes.ogg', 50, 0)
m_type = 2
if("no")
- var/M = null
- if(param)
- for(var/mob/A in view(null, null))
- if(param == A.name)
- M = A
- break
- if(!M)
- param = null
+ var/M = handle_emote_param(param)
- if(param)
- message = "[src] emits a negative blip at [param]."
- else
- message = "[src] emits a negative blip."
+ message = "[src] emits an negative blip[M ? " at [M]" : ""]."
playsound(src.loc, 'sound/machines/synth_no.ogg', 50, 0)
m_type = 2
if("scream", "screams")
- message = "[src] screams!"
+ var/M = handle_emote_param(param)
+
+ message = "[src] screams[M ? " at [M]" : ""]!"
playsound(src.loc, 'sound/goonstation/voice/robot_scream.ogg', 80, 0)
m_type = 2
diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm
index 9fc96c714a8..43e81db402f 100644
--- a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm
+++ b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm
@@ -287,15 +287,6 @@
C.adjustPlasma(20)
..()
-/datum/reagent/plasma_dust/reaction_obj(obj/O, volume)
- if((!O) || (!volume))
- return 0
- O.atmos_spawn_air(SPAWN_TOXINS|SPAWN_20C, volume)
-
-/datum/reagent/plasma_dust/reaction_turf(turf/simulated/T, volume)
- if(istype(T))
- T.atmos_spawn_air(SPAWN_TOXINS|SPAWN_20C, volume)
-
/datum/reagent/plasma_dust/reaction_mob(mob/living/M, method=TOUCH, volume)//Splashing people with plasma dust is stronger than fuel!
if(method == TOUCH)
M.adjust_fire_stacks(volume / 5)
diff --git a/code/modules/space_management/space_chunk.dm b/code/modules/space_management/space_chunk.dm
index 8b6e5b6974e..e139394e963 100644
--- a/code/modules/space_management/space_chunk.dm
+++ b/code/modules/space_management/space_chunk.dm
@@ -96,6 +96,13 @@
/datum/space_chunk/proc/return_turfs()
return
+/datum/space_chunk/proc/search_chunk(object_list)
+ var/list/located = list()
+ for(var/atom/object in object_list)
+ if(((object.x >= x) && (object.x <= (x + width))) && ((object.y >= y) && (object.y <= (y + height))) && (object.z == zpos))
+ located.Add(object)
+ return located
+
#undef BOTTOM_LEFT_CHUNK
#undef BOTTOM_RIGHT_CHUNK
#undef TOP_LEFT_CHUNK
diff --git a/code/modules/vr/vr_controller.dm b/code/modules/vr/vr_controller.dm
new file mode 100644
index 00000000000..45bf2a6cc74
--- /dev/null
+++ b/code/modules/vr/vr_controller.dm
@@ -0,0 +1,63 @@
+//Control file with the backbone for the vr rooms and avatars
+
+var/datum/vr_rooms = list()
+var/roomcap = 20
+
+/datum/vr_room
+ var/name = null
+ var/datum/map_template/vr/template = null
+ var/datum/space_chunk/chunk = null
+ var/list/spawn_points = list()
+ var/expires = 1
+
+proc/make_vr_room(name, template, expires)
+ var/datum/vr_room/R = new
+ R.name = name
+ R.template = template
+ R.template = vr_templates[R.template]
+ R.chunk = space_manager.allocate_space(R.template.width, R.template.height)
+ R.expires = expires
+ vr_rooms[R.name] = R
+ R.template.load(locate(R.chunk.x,R.chunk.y,R.chunk.zpos), centered = FALSE)
+
+ for(var/atom/landmark in R.chunk.search_chunk(landmarks_list))
+ if(landmark.name == "avatarspawn")
+ R.spawn_points.Add(landmark)
+
+//Control code for the avatars
+proc/build_virtual_avatar(mob/living/carbon/human/H, location, datum/map_template/vr/level/template)
+ if(!location)
+ return
+ var/mob/living/carbon/human/virtual_reality/vr_avatar
+ location = get_turf(location)
+ vr_avatar = new /mob/living/carbon/human/virtual_reality(location)
+ vr_avatar.set_species(H.species.name)
+ if(istype(H, /mob/living/carbon/human/virtual_reality))
+ var/mob/living/carbon/human/virtual_reality/V = H
+ vr_avatar.real_me = V.real_me
+ else
+ vr_avatar.real_me = H
+ vr_avatar.dna = H.dna.Clone()
+ vr_avatar.name = H.name
+ vr_avatar.real_name = H.real_name
+ vr_avatar.undershirt = H.undershirt
+ vr_avatar.underwear = H.underwear
+ vr_avatar.UpdateAppearance()
+ vr_avatar.equipOutfit(template.outfit)
+ return vr_avatar
+
+proc/control_remote(mob/living/carbon/human/H, mob/living/carbon/human/virtual_reality/vr_avatar)
+ if(H.mind)
+ H.mind.transfer_to(vr_avatar)
+
+proc/spawn_vr_avatar(mob/living/carbon/human/H, datum/vr_room/room)
+ room = vr_rooms[room]
+ var/mob/living/carbon/human/virtual_reality/vr_human
+ vr_human = build_virtual_avatar(H, pick(room.spawn_points), room.template)
+ control_remote(H, vr_human)
+ return vr_human
+
+//Preloaded rooms
+/hook/roundstart/proc/starting_levels()
+ make_vr_room("Lobby", "lobby", 0)
+ return 1
\ No newline at end of file
diff --git a/code/modules/vr/vr_outfits.dm b/code/modules/vr/vr_outfits.dm
new file mode 100644
index 00000000000..4f673fd4e8c
--- /dev/null
+++ b/code/modules/vr/vr_outfits.dm
@@ -0,0 +1,15 @@
+//place all the outfits for your levels in here.
+
+/datum/outfit/vr/vr_basic
+ name = "basic vr"
+ uniform = /obj/item/clothing/under/psysuit
+ shoes = /obj/item/clothing/shoes/black
+
+/datum/outfit/vr/roman
+ name = "roman"
+ uniform = /obj/item/clothing/under/roman
+ shoes = /obj/item/clothing/shoes/roman
+ l_hand = /obj/item/weapon/shield/riot/roman
+ r_hand = /obj/item/weapon/twohanded/spear
+ head = /obj/item/clothing/head/helmet/roman
+ back = /obj/item/weapon/twohanded/spear
\ No newline at end of file
diff --git a/html/changelog.html b/html/changelog.html
index 2c6921bdff1..13b803a4bc0 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -55,6 +55,62 @@
-->
+
19 April 2017
+
IK3I updated:
+
+ - Chaplain now spawns with his bible
+
+
Xantholne updated:
+
+ - You now correctly spawn with the CMO Skirt if selected in loadout menu
+
+
+
17 April 2017
+
KasparoVy updated:
+
+ - The God-emperor of Mankind diskette's UI works again.
+ - DNA UI injectors will now immediately update a person's eye colour.
+
+
Krausus updated:
+
+ - You can no longer squeeze non-match objects into matchboxes.
+
+
+
16 April 2017
+
FalseIncarnate updated:
+
+ - Potential collaborators for traitors now are informed they are potentially a collaborator for a potential increase in them potentially helping the traitors potentially do potentially bad things. Potentially.
+ - Potential collaborators are given a single code word and response set so they can discretely find out that their best friend is a filthy traitor.
+
+
KasparoVy updated:
+
+ - Adds secondary (facial) hair colours to the genome (UI). There are 6 new blocks.
+ - Characters with secondary (facial) hair colours won't find they've turned black after cloning anymore.
+
+
Kyep updated:
+
+ - Plasma dust no longer creates plasma gas on objects or turfs during reactions.
+
+
Twinmold93 updated:
+
+ - Missing sprite for pod pilot Drask now added.
+
+
Xantholne updated:
+
+ - Adds Medical Beret available via loadout menu
+
+
ZomgPonies updated:
+
+ - Fixes Superhero ID cards
+ - Fixes Griffin missing his Freedom Implant
+ - Fixes ElectroNegmatic's Ability not working at all.
+ - Changes LightnIan's ability into a non-damaging stun lasting 2 ticks, with the amount of people affected depending on how long you hold the power in for.
+
+
uraniummeltdown updated:
+
+ - You can now create heat-proof glass airlocks by using a sheet of reinforced glass on the assembly during construction. Regular glass airlocks just require a sheet of glass.
+
+
11 April 2017
FalseIncarnate updated:
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 54b7742ff91..6fbdf0e40c8 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -4459,3 +4459,42 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
FalseIncarnate:
- tweak: Damage done to the shuttle engines by a shadowling's "Extend Shuttle" ability
now prevent the shuttle from being recalled to CentComm.
+2017-04-16:
+ FalseIncarnate:
+ - tweak: Potential collaborators for traitors now are informed they are potentially
+ a collaborator for a potential increase in them potentially helping the traitors
+ potentially do potentially bad things. Potentially.
+ - rscadd: Potential collaborators are given a single code word and response set
+ so they can discretely find out that their best friend is a filthy traitor.
+ KasparoVy:
+ - rscadd: Adds secondary (facial) hair colours to the genome (UI). There are 6 new
+ blocks.
+ - bugfix: Characters with secondary (facial) hair colours won't find they've turned
+ black after cloning anymore.
+ Kyep:
+ - rscdel: Plasma dust no longer creates plasma gas on objects or turfs during reactions.
+ Twinmold93:
+ - bugfix: Missing sprite for pod pilot Drask now added.
+ Xantholne:
+ - rscadd: Adds Medical Beret available via loadout menu
+ ZomgPonies:
+ - bugfix: Fixes Superhero ID cards
+ - bugfix: Fixes Griffin missing his Freedom Implant
+ - bugfix: Fixes ElectroNegmatic's Ability not working at all.
+ - tweak: Changes LightnIan's ability into a non-damaging stun lasting 2 ticks, with
+ the amount of people affected depending on how long you hold the power in for.
+ uraniummeltdown:
+ - rscadd: You can now create heat-proof glass airlocks by using a sheet of reinforced
+ glass on the assembly during construction. Regular glass airlocks just require
+ a sheet of glass.
+2017-04-17:
+ KasparoVy:
+ - bugfix: The God-emperor of Mankind diskette's UI works again.
+ - bugfix: DNA UI injectors will now immediately update a person's eye colour.
+ Krausus:
+ - bugfix: You can no longer squeeze non-match objects into matchboxes.
+2017-04-19:
+ IK3I:
+ - bugfix: Chaplain now spawns with his bible
+ Xantholne:
+ - bugfix: You now correctly spawn with the CMO Skirt if selected in loadout menu
diff --git a/icons/mob/eyes.dmi b/icons/mob/eyes.dmi
index 97966c61dac..fdf13394f20 100644
Binary files a/icons/mob/eyes.dmi and b/icons/mob/eyes.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index a3233b8bac5..acfaf83a92c 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/inhands/clothing_lefthand.dmi b/icons/mob/inhands/clothing_lefthand.dmi
index 6028f386552..29ebf19be94 100644
Binary files a/icons/mob/inhands/clothing_lefthand.dmi and b/icons/mob/inhands/clothing_lefthand.dmi differ
diff --git a/icons/mob/inhands/clothing_righthand.dmi b/icons/mob/inhands/clothing_righthand.dmi
index 488f0b342ee..0d43b6216f7 100644
Binary files a/icons/mob/inhands/clothing_righthand.dmi and b/icons/mob/inhands/clothing_righthand.dmi differ
diff --git a/icons/mob/inhands/fluff_lefthand.dmi b/icons/mob/inhands/fluff_lefthand.dmi
index 8e3ccdbfbff..84380f038ed 100644
Binary files a/icons/mob/inhands/fluff_lefthand.dmi and b/icons/mob/inhands/fluff_lefthand.dmi differ
diff --git a/icons/mob/inhands/fluff_righthand.dmi b/icons/mob/inhands/fluff_righthand.dmi
index 21dc49c50ea..d93ab0ffc68 100644
Binary files a/icons/mob/inhands/fluff_righthand.dmi and b/icons/mob/inhands/fluff_righthand.dmi differ
diff --git a/icons/mob/species/drask/uniform.dmi b/icons/mob/species/drask/uniform.dmi
index 6610948f641..9dd5a22618c 100644
Binary files a/icons/mob/species/drask/uniform.dmi and b/icons/mob/species/drask/uniform.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index 7c532ab179f..03c1180b1dc 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi
index ce9cab87794..7742bdcc755 100644
Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ
diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi
index fd2947d7d69..227ec28b742 100644
Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index 06089134abf..0aece3ac8ac 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/masks.dmi b/icons/obj/clothing/masks.dmi
index 8faec500e7b..974efa8a088 100644
Binary files a/icons/obj/clothing/masks.dmi and b/icons/obj/clothing/masks.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index a131fc14f04..669e8dff821 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi
index 21b101e88dd..1db72be54fa 100644
Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ
diff --git a/icons/obj/custom_items.dmi b/icons/obj/custom_items.dmi
index e52c0e5b9f4..9623f991e2f 100644
Binary files a/icons/obj/custom_items.dmi and b/icons/obj/custom_items.dmi differ
diff --git a/icons/obj/objects.dmi b/icons/obj/objects.dmi
index e2b617812a8..e95b9ce041f 100644
Binary files a/icons/obj/objects.dmi and b/icons/obj/objects.dmi differ
diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi
index d021f5d02b1..ba4485bdbf8 100644
Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ
diff --git a/icons/vehicles/motorcycle.dmi b/icons/vehicles/motorcycle.dmi
index 2f3c2d5517f..5b1a910b7b0 100644
Binary files a/icons/vehicles/motorcycle.dmi and b/icons/vehicles/motorcycle.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 431b0f954ed..1fc98107ca4 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -219,6 +219,7 @@
#include "code\datums\supplypacks.dm"
#include "code\datums\uplink_item.dm"
#include "code\datums\vision_override.dm"
+#include "code\datums\vr.dm"
#include "code\datums\cache\air_alarm.dm"
#include "code\datums\cache\apc.dm"
#include "code\datums\cache\cache.dm"
@@ -317,6 +318,7 @@
#include "code\datums\spells\trigger.dm"
#include "code\datums\spells\turf_teleport.dm"
#include "code\datums\spells\wizard.dm"
+#include "code\datums\vr\level.dm"
#include "code\datums\weather\weather.dm"
#include "code\datums\weather\weather_types.dm"
#include "code\datums\wires\airlock.dm"
@@ -601,6 +603,7 @@
#include "code\game\machinery\computer\store.dm"
#include "code\game\machinery\computer\syndicate_specops_shuttle.dm"
#include "code\game\machinery\computer\telecrystalconsoles.dm"
+#include "code\game\machinery\computer\vr_control.dm"
#include "code\game\machinery\doors\airlock.dm"
#include "code\game\machinery\doors\airlock_control.dm"
#include "code\game\machinery\doors\airlock_electronics.dm"
@@ -2210,6 +2213,10 @@
#include "code\modules\vehicle\speedbike.dm"
#include "code\modules\vehicle\sportscar.dm"
#include "code\modules\vehicle\vehicle.dm"
+#include "code\modules\vr\vr_avatar.dm"
+#include "code\modules\vr\vr_controller.dm"
+#include "code\modules\vr\vr_goggles.dm"
+#include "code\modules\vr\vr_outfits.dm"
#include "goon\code\datums\browserOutput.dm"
#include "interface\interface.dm"
#include "interface\skin.dmf"