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:

+ +

Xantholne updated:

+ + +

17 April 2017

+

KasparoVy updated:

+ +

Krausus updated:

+ + +

16 April 2017

+

FalseIncarnate updated:

+ +

KasparoVy updated:

+ +

Kyep updated:

+ +

Twinmold93 updated:

+ +

Xantholne updated:

+ +

ZomgPonies updated:

+ +

uraniummeltdown updated:

+ +

11 April 2017

FalseIncarnate updated: