diff --git a/code/defines/client.dm b/code/defines/client.dm
index a3f0d25b212..c661927efa0 100644
--- a/code/defines/client.dm
+++ b/code/defines/client.dm
@@ -26,6 +26,7 @@
var/karma_spent = 0
var/ooccolor = "#b82e00" //only used for admins of host level, default is equal to admin default
var/midis = 1 //Check if midis should be played for someone -- Urist
+ var/bubbles = 1 //Check if bubbles should be displayed for someone -- Doohl
var/be_alien = 0 //Check if that guy wants to be an alien -- Urist
authenticate = 0
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 414be9f539b..216a33837be 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -192,6 +192,10 @@
move_result = 1
else
move_result = step(src,direction)
+ if(occupant)
+ for(var/obj/speech_bubble/B in range(1, src))
+ if(B.parent == occupant)
+ B.loc = loc
if(move_result)
can_move = 0
use_power(step_energy_drain)
@@ -201,6 +205,7 @@
src.log_message("Movement control lost. Inertial movement started.")
if(do_after(step_in))
can_move = 1
+
return 1
return 0
diff --git a/code/game/objects/closets.dm b/code/game/objects/closets.dm
index e2ffe3849f3..a2be6c3d275 100644
--- a/code/game/objects/closets.dm
+++ b/code/game/objects/closets.dm
@@ -212,6 +212,14 @@
for (var/mob/M in hearers(src, null))
M << text("BANG, bang!", max(0, 5 - get_dist(src, M)))
+/obj/closet/Move()
+ ..()
+ for(var/mob/M in contents)
+ for(var/obj/speech_bubble/B in range(1, src))
+ if(B.parent == M)
+ B.loc = loc
+
+
/obj/closet/attack_paw(mob/user as mob)
return src.attack_hand(user)
diff --git a/code/modules/chemical/Chemistry-Recipes.dm b/code/modules/chemical/Chemistry-Recipes.dm
index 789100780f6..150c0586d43 100644
--- a/code/modules/chemical/Chemistry-Recipes.dm
+++ b/code/modules/chemical/Chemistry-Recipes.dm
@@ -572,8 +572,7 @@ datum
var/virus = pick(/datum/disease/flu, /datum/disease/cold, \
/datum/disease/pierrot_throat, /datum/disease/fake_gbs, \
- /datum/disease/brainrot, /datum/disease/wizarditis, \
- /datum/disease/magnitis)
+ /datum/disease/brainrot, /datum/disease/magnitis)
var/datum/disease/F = new virus(0)
@@ -607,14 +606,19 @@ datum
result_amount = 2
required_container = /obj/item/metroid_core
required_other = 5
- metroidxeno
- name = "Metroid Xeno"
+ metroidretro
+ name = "Metroid Retro"
id = "m_xeno"
- result = "xenomicrobes"
+ result = null
required_reagents = list("sugar" = 1)
result_amount = 1
required_container = /obj/item/metroid_core
required_other = 5
+ on_reaction(var/datum/reagents/holder, var/created_volume)
+ var/datum/disease/F = new /datum/disease/dna_retrovirus(0)
+ var/list/data = list("viruses"= list(F))
+ holder.add_reagent("blood", 20, data)
+
metroidfoam
name = "Metroid Foam"
id = "m_foam"
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 67db434a613..9b0cc5ae562 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -305,6 +305,47 @@
for (var/mob/M in heard_a)
M.show_message(rendered, 2)
+ if(M.client)
+ spawn()
+ var/isbot = ""
+ if(istype(src, /mob/living/silicon))
+ isbot = "bot"
+
+ var/speechtype = "say"
+ var/ending = copytext(message, length(message))
+ if (ending == "?")
+ speechtype = "question"
+ else if (ending == "!")
+ speechtype = "exclamation"
+
+ if(istype(M, /mob/living))
+ if(M:ear_deaf && speechtype == "question")
+ speechtype = "say"
+
+ var/obj/speech_bubble/B = new/obj/speech_bubble
+ B.icon = 'speechbubble.dmi'
+ B.parent = src
+ B.mouse_opacity = 0
+ B.invisibility = invisibility
+ B.layer = 10
+
+ if(!M.client.bubbles || M == src)
+ var/image/I = image('speechbubble.dmi', B, "override")
+ I.override = 1
+ M << I
+
+ flick("[isbot][speechtype]", B)
+
+ if(istype(loc, /turf))
+ B.loc = loc
+ else
+ B.loc = loc.loc
+
+ sleep(11)
+ del(B)
+
+
+
/*
for(var/obj/O in M) // This is terribly costly for such a unique circumstance, should probably do this a different way in the future -- TLE
if(istype(O, /obj/item/device/aicard))
@@ -329,5 +370,37 @@
for (var/mob/M in heard_b)
M.show_message(rendered, 2)
+ if(M.client)
+ spawn()
+ var/isbot = ""
+ if(istype(src, /mob/living/silicon))
+ isbot = "bot"
- log_say("[name]/[key] : [message]")
\ No newline at end of file
+ var/obj/speech_bubble/B = new/obj/speech_bubble
+ B.icon = 'speechbubble.dmi'
+ B.parent = src
+ B.mouse_opacity = 0
+ B.invisibility = invisibility
+ B.layer = 10
+
+ if(!M.client.bubbles || M == src)
+ var/image/I = image('speechbubble.dmi', B, "override")
+ I.override = 1
+ M << I
+
+ flick("[isbot]say", B)
+
+ if(istype(loc, /turf))
+ B.loc = loc
+ else
+ B.loc = loc.loc
+
+ sleep(11)
+ del(B)
+
+ log_say("[name]/[key] : [message]")
+
+
+
+/obj/speech_bubble
+ var/mob/parent
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm
index ca1b1f66601..6c566918f80 100644
--- a/code/modules/mob/living/silicon/ai/say.dm
+++ b/code/modules/mob/living/silicon/ai/say.dm
@@ -13,6 +13,6 @@
if (ending == "?")
return "queries, \"[text]\"";
else if (ending == "!")
- return "declares, \"[copytext(text, 1, length(text))]\"";
+ return "declares, \"[text]\"";
return "states, \"[text]\"";
diff --git a/code/modules/mob/living/silicon/pai/say.dm b/code/modules/mob/living/silicon/pai/say.dm
index b0d98575573..46ee324792d 100644
--- a/code/modules/mob/living/silicon/pai/say.dm
+++ b/code/modules/mob/living/silicon/pai/say.dm
@@ -19,7 +19,7 @@
if (ending == "?")
return "[src.speakQuery], \"[text]\"";
else if (ending == "!")
- return "[src.speakExclamation], \"[copytext(text, 1, length(text))]\"";
+ return "[src.speakExclamation], \"[text]\"";
return "[src.speakStatement], \"[text]\"";
diff --git a/code/modules/mob/living/silicon/robot/say.dm b/code/modules/mob/living/silicon/robot/say.dm
index c8d42e6b4cc..97172a91391 100644
--- a/code/modules/mob/living/silicon/robot/say.dm
+++ b/code/modules/mob/living/silicon/robot/say.dm
@@ -15,6 +15,6 @@
if (ending == "?")
return "queries, \"[text]\"";
else if (ending == "!")
- return "declares, \"[copytext(text, 1, length(text))]\"";
+ return "declares, \"[text]\"";
return "states, \"[text]\"";
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 35a0178e674..08171f9cc71 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1926,6 +1926,10 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
step(mob, pick(cardinal))
else
. = ..()
+ for(var/obj/speech_bubble/S in range(1, mob))
+ if(S.parent == mob)
+ S.loc = mob.loc
+
moving = null
return .
else
diff --git a/code/modules/mob/new_player/preferences.dm b/code/modules/mob/new_player/preferences.dm
index 6436992a80a..0fdec384dc8 100644
--- a/code/modules/mob/new_player/preferences.dm
+++ b/code/modules/mob/new_player/preferences.dm
@@ -40,6 +40,7 @@ datum/preferences
var/ooccolor = "#b82e00"
var/be_random_name = 0
var/underwear = 1
+ var/bubbles = 0 // 0 if the player doesn't want bubbles to appear
var/occupation[] = list("No Preference", "No Preference", "No Preference")
var/datum/jobs/wanted_jobs = list()
@@ -391,6 +392,7 @@ datum/preferences
dat += "
"
dat += "UI Style: [UI == UI_NEW ? "New" : "Old"]
"
dat += "Play admin midis: [midis == 1 ? "Yes" : "No"]
"
+ dat += "Show chat bubbles: [bubbles == 1 ? "Yes" : "No"]
"
if(user.client.holder)
if(user.client.holder.rank)
@@ -793,6 +795,9 @@ datum/preferences
if (link_tags["midis"])
midis = (midis+1)%2
+ if (link_tags["bubbles"])
+ bubbles = !bubbles
+
if (link_tags["underwear"])
if(!IsGuestKey(user.key))
switch(link_tags["underwear"])
@@ -848,6 +853,7 @@ datum/preferences
b_type = "A+"
UI = UI_OLD
midis = 1
+ bubbles = 1
ShowChoices(user)
@@ -944,6 +950,7 @@ datum/preferences
spawn(10)
if(character&&character.client)
character.client.midis = midis
+ character.client.bubbles = bubbles
character.client.ooccolor = ooccolor
character.client.be_alien = be_special&BE_ALIEN
diff --git a/code/modules/mob/new_player/savefile.dm b/code/modules/mob/new_player/savefile.dm
index 22e3fd957e3..60698afe355 100644
--- a/code/modules/mob/new_player/savefile.dm
+++ b/code/modules/mob/new_player/savefile.dm
@@ -46,6 +46,7 @@ datum/preferences/proc/savefile_save(mob/user)
//world << "DEBUG: saving UI as [UI]"
//F["be_alien"] << src.be_alien // Urist
F["midis"] << src.midis // Urist
+ F["bubbles"] << src.bubbles // Doohl
F["ooccolor"] << src.ooccolor // Urist
F["lastchangelog"] << src.lastchangelog // rastaf0
@@ -101,10 +102,11 @@ datum/preferences/proc/savefile_load(mob/user, var/silent = 1)
F["name_is_always_random"] >> src.be_random_name
//F["be_alien"] >> src.be_alien // Urist
F["midis"] >> src.midis // Urist
+ F["bubbles"] >> src.bubbles // Doohl
F["ooccolor"] >> src.ooccolor // Urist
F["lastchangelog"] >> src.lastchangelog // rastaf0
-
+
if (version<=2) // migration from old preferences file format --rastaf0
src.UI = 0 // swithing from storing an image file to storing boolean value --rastaf0
//world << "DEBUG: loading legacy UI as [UI]"
diff --git a/icons/changelog.html b/icons/changelog.html
index 240adcc6f54..87b178a870d 100644
--- a/icons/changelog.html
+++ b/icons/changelog.html
@@ -45,6 +45,16 @@ Stuff which is in development and not yet visible to players or just code relate
(is. code improvements for expandability, etc.) should not be listed here. They
should be listed in the changelog upon commit tho. Thanks. -->
+2 August 2011.
+
+ - Doohl updated:
+
+ - Speech bubbles: you can toggle them on in the character setup window. Basically, whenever someone around you talks, you see a speech bubble appear above them.
+ - You can no longer create wizarditis and xenomicrobes with metroid cores.
+ - Tweak: Using an exclamation mark as an AI, pAI, or cyborg will not longer get rid of the last exclamation mark.
+
+
+
30 July 2011.