Possibly the finishing touches to the telecomms prototype. They will be included in the game soon-ish.

Some work on critters. Added a new critter type: the VISCERATORS. (http://dl.dropbox.com/u/10657252/SS13/Manhacks.PNG) Includes a small new audio file. They'll probably be created with a traitor item or a box-o-hacks in the armory.



git-svn-id: http://tgstation13.googlecode.com/svn/trunk@2932 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
vageyenaman@gmail.com
2012-01-09 01:48:38 +00:00
parent 5c1508994c
commit 2f92ba494e
13 changed files with 282 additions and 54 deletions
+38 -11
View File
@@ -21,14 +21,6 @@
if(signal.data["message"])
/* ###### Broadcast a message using signal.data ###### */
Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"])
signal.data["done"] = 1 // mark the signal as being broadcasted
// Search for the original signal and mark it as done as well
@@ -36,6 +28,16 @@
if(original)
original.data["done"] = 1
if(signal.data["slow"] > 0)
sleep(signal.data["slow"]) // simulate the network lag if necessary
/* ###### Broadcast a message using signal.data ###### */
Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"],, signal.data["compression"])
/* --- Do a snazzy animation! --- */
flick("broadcaster_send", src)
@@ -82,12 +84,16 @@
1 -- Will only broadcast to intercoms
2 -- Will only broadcast to intercoms and station-bounced radios
@param compression:
If 0, the signal is audible
If nonzero, the signal may be partially inaudible or just complete gibberish.
**/
/proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M,
var/vmask, var/vmessage, var/obj/item/device/radio/radio,
var/message, var/name, var/job, var/realname, var/vname,
var/filtertype)
var/filtertype, var/compression)
/* ###### Prepare the radio connection ###### */
@@ -133,6 +139,7 @@
// Did not understand the message:
var/list/heard_voice = list() // voice message (ie "chimpers")
var/list/heard_garbled = list() // garbled message (ie "f*c* **u, **i*er!")
var/list/heard_gibberish= list() // completely screwed over message (ie "F%! (O*# *#!<>&**%!")
for (var/mob/R in receive)
@@ -141,6 +148,12 @@
if (R.client && R.client.STFU_radio) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
continue
// --- Check for compression ---
if(compression > 0)
heard_gibberish += R
continue
// --- Can understand the speech ---
if (R.say_understands(M))
@@ -166,7 +179,7 @@
/* ###### Begin formatting and sending the message ###### */
if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled))
if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled) || length(heard_gibberish))
/* --- Some miscellaneous variables to format the string output --- */
var/part_a = "<span class='radio'><span class='name'>" // goes in the actual output
@@ -294,11 +307,25 @@
quotedmsg = M.say_quote(stars(message))
var/rendered = "[part_a][vname][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_voice)
for (var/mob/R in heard_garbled)
if(istype(R, /mob/living/silicon/ai))
R.show_message("[part_a]<a href='byond://?src=\ref[radio];track2=\ref[R];track=\ref[M]'>[vname]</a>[part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
/* --- Complete gibberish. Usually happens when there's a compressed message --- */
if (length(heard_gibberish))
quotedmsg = M.say_quote(Gibberish(message, compression + 50))
world << "Gibberish: [quotedmsg]"
var/rendered = "[part_a][Gibberish(M.real_name, compression + 50)][part_b][quotedmsg][part_c]"
for (var/mob/R in heard_gibberish)
if(istype(R, /mob/living/silicon/ai))
R.show_message("[part_a]<a href='byond://?src=\ref[radio];track2=\ref[R];track=\ref[M]'>[Gibberish(realname, compression + 50)] ([Gibberish(job, compression + 50)]) </a>[part_b][quotedmsg][part_c]", 2)
else
R.show_message(rendered, 2)
+2 -2
View File
@@ -93,8 +93,8 @@
if(language == "Human" || universal_translate || C.parameters["uspeech"])
dat += "<u><font color = #18743E>Data type</font color></u>: [C.input_type]<br>"
dat += "<u><font color = #18743E>Orator</font color></u>: [C.parameters["name"]] (Job: [C.parameters["job"]])<br>"
dat += "<u><font color = #18743E>Race</font color></u>: [race]<br>"
dat += "<u><font color = #18743E>Source</font color></u>: [C.parameters["name"]] (Job: [C.parameters["job"]])<br>"
dat += "<u><font color = #18743E>Class</font color></u>: [race]<br>"
dat += "<u><font color = #18743E>Contents</font color></u>: \"[C.parameters["message"]]\"<br>"
@@ -130,20 +130,26 @@
if(href_list["link"])
if(P.buffer)
if( (!(src in P.buffer.links)) && (!(P.buffer in src.links)))
if(!(src in P.buffer.links))
P.buffer.links.Add(src)
if(!(P.buffer in src.links))
src.links.Add(P.buffer)
temp = "<font color = #666633>-% Successfully linked with \ref[P.buffer] [P.buffer.name] %-</font color>"
else
temp = "<font color = #666633>-% Unable to acquire buffer %-</font color>"
if(href_list["buffer"])
temp = "<font color = #666633>-% Successfully stored \ref[P.buffer] [P.buffer.name] in buffer %-</font color>"
P.buffer = src
if(href_list["flush"])
temp = "<font color = #666633>-% Buffer successfully flushed. %-</font color>"
P.buffer = null
@@ -24,21 +24,62 @@
machinetype = 0 // just a hacky way of preventing alike machines from pairing
proc/relay_information(datum/signal/signal, filter, amount)
proc/relay_information(datum/signal/signal, filter, copysig, amount)
// relay signal to all linked machinery that are of type [filter]. If signal has been sent [amount] times, stop sending
var/send_count = 0
// Loop through all linked machines and send the signal or copy.
for(var/obj/machinery/telecomms/machine in links)
if(filter && !istype( machine, text2path(filter) ))
continue
if(amount && send_count >= amount)
break
// If we're sending a copy, be sure to create the copy for EACH machine and paste the data
var/datum/signal/copy = new
if(copysig)
copy.transmission_method = 2
copy.frequency = signal.frequency
// Copy the main data contents! Workaround for some nasty bug where the actual array memory is copied and not its contents.
copy.data = list(
"mob" = signal.data["mob"],
"mobtype" = signal.data["mobtype"],
"realname" = signal.data["realname"],
"name" = signal.data["name"],
"job" = signal.data["job"],
"key" = signal.data["key"],
"vmessage" = signal.data["vmessage"],
"vname" = signal.data["vname"],
"vmask" = signal.data["vmask"],
"compression" = signal.data["compression"],
"message" = signal.data["message"],
"connection" = signal.data["connection"],
"radio" = signal.data["radio"],
"slow" = signal.data["slow"]
)
// Keep the "original" signal constant
if(!copy.data["original"])
copy.data["original"] = signal
else
copy.data["original"] = signal.data["original"]
else
del(copy)
send_count++
spawn()
machine.receive_information(signal, src)
if(copysig && copy)
machine.receive_information(copy, src)
else
machine.receive_information(signal, src)
return send_count
@@ -74,6 +115,8 @@
The receiver idles and receives messages from subspace-compatible radio equipment;
primarily headsets. They then just relay this information to all linked devices,
which can would probably be network buses.
Link to Processor Units in case receiver can't send to bus units.
*/
/obj/machinery/telecomms/receiver
@@ -93,12 +136,13 @@
if(is_freq_listening(signal)) // detect subspace signals
var/datum/signal/copy = new
copy.copy_from(signal) // copy information to new signal
copy.data["original"] = signal
relay_information(copy) // ideally relay the information to bus units
var/sendbus = relay_information(signal, "/obj/machinery/telecomms/bus", 1) // ideally relay the copied information to bus units
/* We can't send the signal to a bus, so we send it to a processor */
if(!sendbus)
signal.data["slow"] += rand(5, 10) // slow the signal down
relay_information(signal, "/obj/machinery/telecomms/processor", 1) // send copy to processors
/*
@@ -107,6 +151,8 @@
They transfer uncompressed subspace packets to processor units, and then take
the processed packet to a server for logging.
Link to a subspace broadcaster if it can't send to a server.
*/
/obj/machinery/telecomms/bus
@@ -126,15 +172,21 @@
if(signal.data["compression"]) // if signal is still compressed from subspace transmission
// send to one linked processor unit
var/send_to_processor = relay_information(signal, "/obj/machinery/telecomms/processor", 1)
var/send_to_processor = relay_information(signal, "/obj/machinery/telecomms/processor")
if(!send_to_processor) // failed to send to a processor, relay information anyway
relay_information(signal, "/obj/machinery/telecomms/server")
signal.data["slow"] += rand(1, 5) // slow the signal down only slightly
relay_information(signal, "/obj/machinery/telecomms/server", 1)
else // the signal has been decompressed by a processor unit
// send to all linked server units
relay_information(signal, "/obj/machinery/telecomms/server")
var/sendserver = relay_information(signal, "/obj/machinery/telecomms/server", 1)
// Can't send to a single server, send to a broadcaster instead! But it needs a processor to do this
if(!sendserver)
signal.data["slow"] += rand(0, 1) // slow the signal down only slightly
relay_information(signal, "/obj/machinery/telecomms/broadcaster")
@@ -142,6 +194,8 @@
The processor is a very simple machine that decompresses subspace signals and
transfers them back to the original bus. It is essential in producing audible
data.
Link to servers if bus is not present
*/
/obj/machinery/telecomms/processor
@@ -159,7 +213,12 @@
if(is_freq_listening(signal))
signal.data["compression"] = 0 // uncompress subspace signal
relay_direct_information(signal, machine_from) // send the signal back to the machine
if(istype(machine_from, /obj/machinery/telecomms/bus))
relay_direct_information(signal, machine_from) // send the signal back to the machine
else // no bus detected - send the signal to servers instead
relay_information(signal, "/obj/machinery/telecomms/server", 1)
@@ -186,11 +245,11 @@
receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
if(signal.data["message"] && !signal.data["compression"])
if(signal.data["message"])
if(is_freq_listening(signal))
// if signal contains discernable data
// If signal has a message and appropriate frequency
update_logs()
@@ -208,6 +267,15 @@
log.parameters["realname"] = signal.data["realname"]
log.parameters["uspeech"] = M.universal_speak
// If the signal is still compressed, make the log entry gibberish
if(signal.data["compression"] > 0)
log.parameters["message"] = Gibberish(signal.data["message"], signal.data["compression"] + 50)
log.parameters["job"] = Gibberish(signal.data["job"], signal.data["compression"] + 50)
log.parameters["name"] = Gibberish(signal.data["name"], signal.data["compression"] + 50)
log.parameters["realname"] = Gibberish(signal.data["realname"], signal.data["compression"] + 50)
log.parameters["vname"] = Gibberish(signal.data["vname"], signal.data["compression"] + 50)
log.input_type = "Corrupt File"
log_entries.Add(log)
var/identifier = num2text( rand(-1000,1000) + world.time )
+21 -1
View File
@@ -427,7 +427,27 @@
src.occupant_message("\blue The [user]'s claws are stopped by the armor.")
for (var/mob/V in viewers(src))
if(V.client && !(V.blinded))
V.show_message("\blue The [user] rebounds off the [src.name] armor!", 1)
V.show_message("\blue The [user] rebounds off [src.name]'s armor!", 1)
return
/obj/mecha/proc/attack_critter(obj/effect/critter/C)
src.log_message("Attack by creature. Attacker - [C].",1)
var/damage = max(0, rand(C.melee_damage_lower - 5, C.melee_damage_upper - 5 ))
if(!prob(src.deflect_chance) && damage > 0)
src.take_damage(damage)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
playsound(src.loc, "sparks", 50, 1)
for (var/mob/V in viewers(src))
if(V.client && !(V.blinded))
V.show_message("\red <b>[C]</b> hits [src.name]'s armor!", 1)
else
src.log_append_to_last("Armor saved.")
src.occupant_message("\blue <b>[C]'s</b> attack is stopped by the armor.")
for (var/mob/V in viewers(src))
if(V.client && !(V.blinded))
V.show_message("\blue <b>[C]</b> rebounds off [src.name]'s armor!", 1)
return
+7 -5
View File
@@ -286,10 +286,11 @@ var/GLOBAL_RADIO_TYPE = 0 // radio type to use
// so that they can be logged even AFTER the mob is deleted or something
// Other tags:
"compression" = 1, // compressed radio signal
"compression" = rand(45,50), // compressed radio signal
"message" = message, // the actual sent message
"connection" = connection, // the radio connection to use
"radio" = src // stores the radio used for transmission
"radio" = src, // stores the radio used for transmission
"slow" = 0 // how much to sleep() before broadcasting - simulates net lag
)
signal.frequency = connection.frequency // Quick frequency set
@@ -328,10 +329,11 @@ var/GLOBAL_RADIO_TYPE = 0 // radio type to use
"vname" = M.voice_name, // the name to display if the voice wasn't understood
"vmask" = voicemask, // 1 if the mob is using a voice gas mas
"compression" = 1, // compressed radio signal
"compression" = 0, // uncompressed radio signal
"message" = message, // the actual sent message
"connection" = connection, // the radio connection to use
"radio" = src // stores the radio used for transmission
"radio" = src, // stores the radio used for transmission
"slow" = 0
)
signal.frequency = connection.frequency // Quick frequency set
@@ -350,7 +352,7 @@ var/GLOBAL_RADIO_TYPE = 0 // radio type to use
Broadcast_Message(connection, M, voicemask, M.voice_message,
src, message, displayname, jobname, real_name, M.voice_name,
filter_type)
filter_type, signal.data["compression"])
+14
View File
@@ -21,6 +21,8 @@
wanderer = 1
//Will open doors it bumps ignoring access
opensdoors = 0
//Will randomly travel through vents
ventcrawl = 0
//Internal tracking ignore
frustration = 0
@@ -32,6 +34,10 @@
target = null
oldtarget_name = null
target_lastloc = null
thinkspeed = 15
chasespeed = 4
wanderspeed = 10
//The last guy who attacked it
attacker = null
//Will not attack this thing
@@ -47,6 +53,11 @@
atksame = 0
atkmech = 0
//Attacks syndies/traitors (distinguishes via mind)
atksynd = 1
//Attacks things NOT in its obj/req_access list
atkreq = 0
//Damage multipliers
brutevuln = 1
firevuln = 1
@@ -59,7 +70,10 @@
//Basic attack message when they move to attack and attack
angertext = "charges at"
attacktext = "attacks"
deathtext = "dies!"
chasestate = null // the icon state to use when attacking or chasing a target
attackflick = null // the icon state to flick when it attacks
attack_sound = null // the sound it makes when it attacks!
attack_speed = 25 // delay of attack
+56 -17
View File
@@ -13,7 +13,7 @@
if("thinking")
src.attack = 0
src.target = null
sleep(15)
sleep(thinkspeed)
walk_to(src,0)
if (src.aggressive) seek_target()
if (src.wanderer && !src.target) src.task = "wandering"
@@ -29,11 +29,13 @@
var/mob/living/carbon/M = src.target
ChaseAttack()
src.task = "attacking"
if(chasestate)
icon_state = chasestate
src.anchored = 1
src.target_lastloc = M.loc
else
var/turf/olddist = get_dist(src, src.target)
walk_to(src, src.target,1,4)
walk_to(src, src.target,1,chasespeed)
if ((get_dist(src, src.target)) >= (olddist))
src.frustration++
else
@@ -45,6 +47,8 @@
if ((get_dist(src, src.target) > 1) || ((src.target:loc != src.target_lastloc)))
src.anchored = 0
src.task = "chasing"
if(chasestate)
icon_state = chasestate
else
if (get_dist(src, src.target) <= 1)
var/mob/living/carbon/M = src.target
@@ -58,20 +62,25 @@
src.attacking = 0
else
if(M!=null)
if(M.health < 0)
src.task = "thinking"
src.target = null
src.anchored = 0
src.last_found = world.time
src.frustration = 0
src.attacking = 0
if(ismob(src.target))
if(M.health < 0)
src.task = "thinking"
src.target = null
src.anchored = 0
src.last_found = world.time
src.frustration = 0
src.attacking = 0
else
src.anchored = 0
src.attacking = 0
src.task = "chasing"
if(chasestate)
icon_state = chasestate
if("wandering")
if(chasestate)
icon_state = initial(icon_state)
patrol_step()
sleep(10)
sleep(wanderspeed)
spawn(8)
process()
return
@@ -112,29 +121,57 @@
if (src.target)
src.task = "chasing"
break
// Ignore syndicates and traitors if specified
if(!atksynd && C.mind)
var/datum/mind/synd_mind = C.mind
if( synd_mind.special_role == "Syndicate" || synd_mind.special_role == "traitor" )
continue
if((C.name == src.oldtarget_name) && (world.time < src.last_found + 100)) continue
if(istype(C, /mob/living/carbon/) && !src.atkcarbon) continue
if(istype(C, /mob/living/silicon/) && !src.atksilicon) continue
if(atkreq)
if(src.allowed(C)) continue
if(C.health < 0) continue
if(istype(C, /mob/living/carbon/) && src.atkcarbon) src.attack = 1
if(istype(C, /mob/living/silicon/) && src.atksilicon) src.attack = 1
if(atkreq)
if(!src.allowed(C)) src.attack = 1
if(src.attack)
T = C
break
if(!src.attack)
for(var/obj/effect/critter/C in view(src.seekrange,src))
if(istype(C, /obj/effect/critter) && !src.atkcritter) continue
if(istype(C, /obj/mecha) && !src.atkmech) continue
if(!src.atkcritter) continue
if(C.health <= 0) continue
if(istype(C, /obj/effect/critter) && src.atkcritter)
if(src.atkcritter)
if((istype(C, src.type) && !src.atksame) || (C == src)) continue
src.attack = 1
if(istype(C, /obj/mecha) && src.atkmech) src.attack = 1
if(src.attack)
T = C
break
if(!src.attack)
for(var/obj/mecha/C in view(src.seekrange,src))
if(!C.occupant) continue
if(atkreq && C.occupant)
if(src.allowed(C.occupant)) continue
if(!atksynd && C.occupant)
if(C.occupant.mind)
var/datum/mind/synd_mind = C.occupant.mind
if( synd_mind.special_role == "Syndicate" || synd_mind.special_role == "traitor" )
continue
if(!src.atkmech) continue
if(C.health <= 0) continue
if(src.atkmech) src.attack = 1
if(src.attack)
T = C
break
if(src.attack)
src.target = T
src.oldtarget_name = T:name
@@ -150,10 +187,11 @@
RunAttack()
src.attacking = 1
for(var/mob/O in viewers(src, null))
O.show_message("\red <B>[src]</B> [src.attacktext] [src.target]!", 1)
if(ismob(src.target))
for(var/mob/O in viewers(src, null))
O.show_message("\red <B>[src]</B> [src.attacktext] [src.target]!", 1)
var/damage = rand(melee_damage_lower, melee_damage_upper)
if(istype(target, /mob/living/carbon/human))
@@ -172,7 +210,8 @@
if(isobj(src.target))
if(istype(target, /obj/mecha))
src.target:take_damage(rand(melee_damage_lower,melee_damage_upper))
//src.target:take_damage(rand(melee_damage_lower,melee_damage_upper))
src.target:attack_critter(src)
else
src.target:TakeDamage(rand(melee_damage_lower,melee_damage_upper))
spawn(attack_speed)
+6 -5
View File
@@ -13,7 +13,7 @@ Contains the procs that control attacking critters
if("fire") damage = W.force * firevuln
if("brute") damage = W.force * brutevuln
TakeDamage(damage)
if(src.defensive) Target_Attacker(user)
if(src.defensive && alive) Target_Attacker(user)
return
@@ -46,9 +46,10 @@ Contains the procs that control attacking critters
if(!target) return
src.target = target
src.oldtarget_name = target:name
if(task != "chasing" || task != "attacking")
for(var/mob/O in viewers(src, null))
O.show_message("\red <b>[src]</b> [src.angertext] at [target:name]!", 1)
if(task != "chasing" && task != "attacking")
if(angertext && angertext != "")
for(var/mob/O in viewers(src, null))
O.show_message("\red <b>[src]</b> [src.angertext] at [target:name]!", 1)
src.task = "chasing"
return
@@ -70,7 +71,7 @@ Contains the procs that control attacking critters
src.anchored = 0
src.density = 0
walk_to(src,0)
src.visible_message("<b>[src]</b> dies!")
src.visible_message("<b>[src]</b> [deathtext]")
Harvest(var/obj/item/weapon/W, var/mob/living/user)
+33
View File
@@ -242,3 +242,36 @@
atkcarbon = 1
atksilicon = 1
attacktext = "bites"
// We can maybe make these controllable via some console or something
/obj/effect/critter/manhack
name = "viscerator"
desc = "A small, twin-bladed machine capable of inflicting very deadly lacerations."
icon_state = "viscerator"
pass_flags = PASSTABLE
health = 15
max_health = 15
aggressive = 1
opensdoors = 1
defensive = 1
wanderer = 1
atkcarbon = 1
atksilicon = 1
atkmech = 1
firevuln = 0 // immune to fire
brutevuln = 1
ventcrawl = 1
melee_damage_lower = 10
melee_damage_upper = 15
attacktext = "cuts"
attack_sound = 'bladeslice.wav'
chasestate = "viscerator_attack"
deathtext = "is smashed into pieces!"
Die()
..()
for(var/mob/O in viewers(src, null))
O.show_message("\red <b>[src]</b> is smashed into pieces!", 1)
del(src)
+18
View File
@@ -192,6 +192,24 @@ proc/isorgan(A)
return copytext(sanitize(t),1,MAX_MESSAGE_LEN)
proc/Gibberish(t, p)
/* Turn text into complete gibberish! */
var/returntext = ""
for(var/i = 1, i <= length(t), i++)
var/letter = copytext(t, i, i+1)
if(prob(50))
if(p >= 70)
letter = ""
for(var/j = 1, j <= rand(0, 2), j++)
letter += pick("#","@","*","&","%","$","/", "<", ">", ";","*","*","*","*","*","*","*")
returntext += letter
return returntext
/proc/ninjaspeak(n)
/*
The difference with stutter is that this proc can stutter more than 1 letter
Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.