diff --git a/baystation12.dme b/baystation12.dme index 94ebc4d3618..acba0a7b7f9 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -219,6 +219,7 @@ #include "code\game\gamemodes\objective.dm" #include "code\game\gamemodes\scoreboard.dm" #include "code\game\gamemodes\setupgame.dm" +#include "code\game\gamemodes\steal_items.dm" #include "code\game\gamemodes\autotraitor\autotraitor.dm" #include "code\game\gamemodes\blob\blob.dm" #include "code\game\gamemodes\blob\blob_finish.dm" @@ -1115,6 +1116,7 @@ #include "code\modules\mob\living\simple_animal\hostile\hivebot.dm" #include "code\modules\mob\living\simple_animal\hostile\hostile.dm" #include "code\modules\mob\living\simple_animal\hostile\mimic.dm" +#include "code\modules\mob\living\simple_animal\hostile\mining_mobs.dm" #include "code\modules\mob\living\simple_animal\hostile\pirate.dm" #include "code\modules\mob\living\simple_animal\hostile\russian.dm" #include "code\modules\mob\living\simple_animal\hostile\syndicate.dm" diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm index 01438c32d99..2d3e9b67a8e 100644 --- a/code/ATMOSPHERICS/components/unary/heat_source.dm +++ b/code/ATMOSPHERICS/components/unary/heat_source.dm @@ -26,7 +26,7 @@ process() ..() - if(!on) + if(!on || !network) return 0 var/air_heat_capacity = air_contents.heat_capacity() var/combined_heat_capacity = current_heat_capacity + air_heat_capacity diff --git a/code/ZAS/ZAS_Zones.dm b/code/ZAS/ZAS_Zones.dm index d254debf0c2..db1e1b6f466 100644 --- a/code/ZAS/ZAS_Zones.dm +++ b/code/ZAS/ZAS_Zones.dm @@ -27,12 +27,6 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs var/interactions_with_unsim = 0 var/progress = "nothing" - -/datum/gas_mixture/zone - Del() - CRASH("Something tried to delete a zone's air!") - . = ..() - //CREATION AND DELETION /zone/New(turf/start) . = ..() @@ -53,7 +47,7 @@ var/list/CounterDoorDirections = list(SOUTH,EAST) //Which directions doors turfs //Generate the gas_mixture for use in txhis zone by using the average of the gases //defined at startup. //Changed to try and find the source of the error. - air = new /datum/gas_mixture/zone() + air = new air.group_multiplier = contents.len for(var/turf/simulated/T in contents) if(!T.air) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 90446e59589..4c53337a2b7 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1572,3 +1572,38 @@ proc/check_target_facings(mob/living/initator, mob/living/target) return 2 if(initator.dir + 2 == target.dir || initator.dir - 2 == target.dir || initator.dir + 6 == target.dir || initator.dir - 6 == target.dir) //Initating mob is looking at the target, while the target mob is looking in a direction perpendicular to the 1st return 3 + + +/proc/texttospeechstrip(var/t_in) + var/t_out = "" + for(var/i=1, i<=length(t_in), i++) + var/ascii_char = text2ascii(t_in,i) + switch(ascii_char) + // A .. Z + if(65 to 90) //Uppercase Letters + if(lentext(t_out) <= 150) + t_out += ascii2text(ascii_char) + // a .. z + if(97 to 122) //Lowercase Letters + if(lentext(t_out) <= 150) + t_out += ascii2text(ascii_char) + // 0 .. 9 + if(48 to 57) //Numbers + if(lentext(t_out) <= 150) + t_out += ascii2text(ascii_char) + // ` , - . ! ? : ' + if(39,44,45,46,33,63,58,96,60,62) //Common name punctuation + if(lentext(t_out) <= 150) + t_out += ascii2text(ascii_char) + //Space + if(32) + if(lentext(t_out) <= 150) + t_out += ascii2text(ascii_char) + return t_out +/var/lastspeak = "" + + +/mob/proc/texttospeech(var/text, var/speed, var/pitch, var/accent, var/voice, var/echo) + text = texttospeechstrip(text) + lastspeak = text + ext_python("voice.py", "\"[accent]\" \"[voice]\" \"[pitch]\" \"[echo]\" \"[speed]\" \"[text]\" \"[src.ckey]\"") \ No newline at end of file diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index dc3a3b36dbd..c335a6f1fac 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -258,6 +258,9 @@ client body += "" body += "" body += "" + + body += "" + body += "" if(ishuman(D)) body += "" body += "" @@ -808,6 +811,55 @@ client else usr << "Mob doesn't know that language." + else if(href_list["addverb"]) + if(!check_rights(R_DEBUG)) return + + var/mob/living/H = locate(href_list["addverb"]) + + if(!istype(H)) + usr << "This can only be done to instances of type /mob/living" + return + var/list/possibleverbs = list() + possibleverbs += "Cancel" // One for the top... + possibleverbs += typesof(/mob/proc,/mob/verb,/mob/living/proc,/mob/living/verb) + switch(H.type) + if(/mob/living/carbon/human) + possibleverbs += typesof(/mob/living/carbon/proc,/mob/living/carbon/verb,/mob/living/carbon/human/verb,/mob/living/carbon/human/proc) + if(/mob/living/silicon/robot) + possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/robot/proc,/mob/living/silicon/robot/verb) + if(/mob/living/silicon/ai) + possibleverbs += typesof(/mob/living/silicon/proc,/mob/living/silicon/ai/proc,/mob/living/silicon/ai/verb) + possibleverbs -= H.verbs + possibleverbs += "Cancel" // ...And one for the bottom + + var/verb = input("Select a verb!", "Verbs",null) as anything in possibleverbs + if(!H) + usr << "Mob doesn't exist anymore" + return + if(!verb || verb == "Cancel") + return + else + H.verbs += verb + + else if(href_list["remverb"]) + if(!check_rights(R_DEBUG)) return + + var/mob/H = locate(href_list["remverb"]) + + if(!istype(H)) + usr << "This can only be done to instances of type /mob" + return + var/verb = input("Please choose a verb to remove.","Verbs",null) as null|anything in H.verbs + if(!H) + usr << "Mob doesn't exist anymore" + return + if(!verb) + return + else + H.verbs -= verb + + + else if(href_list["regenerateicons"]) if(!check_rights(0)) return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 7f630c9bb26..57701a4ec08 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -52,7 +52,9 @@ datum/mind var/datum/faction/faction //associated faction var/datum/changeling/changeling //changeling holder - var/datum/vampire/vampire //vampire holder + + var/datum/vampire/vampire //vampire holder + var/rev_cooldown = 0 // the world.time since the mob has been brigged, or -1 if not at all diff --git a/code/defines/procs/AStar.dm b/code/defines/procs/AStar.dm index 0af47ba12c6..e28a159c6ad 100644 --- a/code/defines/procs/AStar.dm +++ b/code/defines/procs/AStar.dm @@ -38,148 +38,126 @@ length to avoid portals or something i guess?? Not that they're counted right no PriorityQueue - var/L[] - var/cmp + var/list/queue + var/proc/comparison_function + New(compare) - L = new() - cmp = compare - proc - IsEmpty() - return !L.len - Enqueue(d) - var/i - var/j - L.Add(d) - i = L.len - j = i>>1 - while(i > 1 && call(cmp)(L[j],L[i]) > 0) - L.Swap(i,j) - i = j - j >>= 1 + queue = list() + comparison_function = compare - Dequeue() - if(!L.len) return 0 - . = L[1] - Remove(1) + proc/IsEmpty() + return !queue.len + + proc/Enqueue(var/data) + queue.Add(data) + var/index = queue.len + + //From what I can tell, this automagically sorts the added data into the correct location. + while(index > 2 && call(comparison_function)(queue[index / 2], queue[index]) > 0) + queue.Swap(index, index / 2) + index /= 2 + + proc/Dequeue() + if(!queue.len) + return + return Remove(1) + + proc/Remove(index) + if(index > queue.len) + return + + var/thing = queue[index] + queue.Cut(index, index + 1) + return thing + + proc/List() + return queue.Copy() + + proc/Length() + return queue.len + + proc/RemoveItem(data) + var/index = queue.Find(data) + if(index) + return Remove(index) - Remove(i) - if(i > L.len) return 0 - L.Swap(i,L.len) - L.Cut(L.len) - if(i < L.len) - _Fix(i) - _Fix(i) - var/child = i + i - var/item = L[i] - while(child <= L.len) - if(child + 1 <= L.len && call(cmp)(L[child],L[child + 1]) > 0) - child++ - if(call(cmp)(item,L[child]) > 0) - L[i] = L[child] - i = child - else - break - child = i + i - L[i] = item - List() - var/ret[] = new() - var/copy = L.Copy() - while(!IsEmpty()) - ret.Add(Dequeue()) - L = copy - return ret - RemoveItem(i) - var/ind = L.Find(i) - if(ind) - Remove(ind) PathNode - var/datum/source - var/PathNode/prevNode - var/f - var/g - var/h - var/nt // Nodes traversed - New(s,p,pg,ph,pnt) - source = s - prevNode = p - g = pg - h = ph - f = g + h - source.bestF = f - nt = pnt + var/datum/position + var/PathNode/previous_node -datum - var/bestF -proc - PathWeightCompare(PathNode/a, PathNode/b) - return a.f - b.f + var/best_estimated_cost + var/estimated_cost + var/known_cost + var/cost + var/nodes_traversed - AStar(start,end,adjacent,dist,maxnodes,maxnodedepth = 30,mintargetdist,minnodedist,id=null, var/turf/exclude=null) + New(_position, _previous_node, _known_cost, _cost, _nodes_traversed) + position = _position + previous_node = _previous_node -// world << "A*: [start] [end] [adjacent] [dist] [maxnodes] [maxnodedepth] [mintargetdist], [minnodedist] [id]" - var/PriorityQueue/open = new /PriorityQueue(/proc/PathWeightCompare) - var/closed[] = new() - var/path[] - start = get_turf(start) - if(!start) return 0 + known_cost = _known_cost + cost = _cost + estimated_cost = cost + known_cost - open.Enqueue(new /PathNode(start,null,0,call(start,dist)(end))) + best_estimated_cost = estimated_cost + nodes_traversed = _nodes_traversed - while(!open.IsEmpty() && !path) - { - var/PathNode/cur = open.Dequeue() - closed.Add(cur.source) +proc/PathWeightCompare(PathNode/a, PathNode/b) + return a.estimated_cost - b.estimated_cost - var/closeenough - if(mintargetdist) - closeenough = call(cur.source,dist)(end) <= mintargetdist +proc/AStar(var/start, var/end, var/proc/adjacent, var/proc/dist, var/max_nodes, var/max_node_depth = 30, var/min_target_dist = 0, var/min_node_dist, var/id, var/datum/exclude) + var/PriorityQueue/open = new /PriorityQueue(/proc/PathWeightCompare) + var/list/closed = list() + var/list/path + var/list/path_node_by_position = list() + start = get_turf(start) + if(!start) + return 0 - if(cur.source == end || closeenough) - path = new() - path.Add(cur.source) - while(cur.prevNode) - cur = cur.prevNode - path.Add(cur.source) - break + open.Enqueue(new /PathNode(start, null, 0, call(start, dist)(end), 0)) - var/L[] = call(cur.source,adjacent)(id) - if(minnodedist && maxnodedepth) - if(call(cur.source,minnodedist)(end) + cur.nt >= maxnodedepth) - continue - else if(maxnodedepth) - if(cur.nt >= maxnodedepth) - continue + while(!open.IsEmpty() && !path) + var/PathNode/current = open.Dequeue() + closed.Add(current.position) - for(var/datum/d in L) - if(d == exclude) - continue - var/ng = cur.g + call(cur.source,dist)(d) - if(d.bestF) - if(ng + call(d,dist)(end) < d.bestF) - for(var/i = 1; i <= open.L.len; i++) - var/PathNode/n = open.L[i] - if(n.source == d) - open.Remove(i) - break + if(current.position == end || call(current.position, dist)(end) <= min_target_dist) + path = new /list(current.nodes_traversed + 1) + path[path.len] = current.position + var/index = path.len - 1 + + while(current.previous_node) + current = current.previous_node + path[index--] = current.position + break + + if(min_node_dist && max_node_depth) + if(call(current.position, min_node_dist)(end) + current.nodes_traversed >= max_node_depth) + continue + + if(max_node_depth) + if(current.nodes_traversed >= max_node_depth) + continue + + for(var/datum/datum in call(current.position, adjacent)(id)) + if(datum == exclude) + continue + + var/best_estimated_cost = current.estimated_cost + call(current.position, dist)(datum) + + //handle removal of sub-par positions + if(datum in path_node_by_position) + var/PathNode/target = path_node_by_position[datum] + if(target.best_estimated_cost) + if(best_estimated_cost + call(datum, dist)(end) < target.best_estimated_cost) + open.RemoveItem(target) else continue - open.Enqueue(new /PathNode(d,cur,ng,call(d,dist)(end),cur.nt+1)) - if(maxnodes && open.L.len > maxnodes) - open.L.Cut(open.L.len) - } + var/PathNode/next_node = new (datum, current, best_estimated_cost, call(datum, dist)(end), current.nodes_traversed + 1) + path_node_by_position[datum] = next_node + open.Enqueue(next_node) - var/PathNode/temp - while(!open.IsEmpty()) - temp = open.Dequeue() - temp.source.bestF = 0 - while(closed.len) - temp = closed[closed.len] - temp.bestF = 0 - closed.Cut(closed.len) + if(max_nodes && open.Length() > max_nodes) + open.Remove(open.Length()) - if(path) - for(var/i = 1; i <= path.len/2; i++) - path.Swap(i,path.len-i+1) - - return path + return path diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm index b96da7b214c..b2a2108c201 100644 --- a/code/game/dna/dna2.dm +++ b/code/game/dna/dna2.dm @@ -232,7 +232,7 @@ var/global/list/datum/dna/gene/dna_genes[0] // Set a DNA SE block's raw value. /datum/dna/proc/SetSEValue(var/block,var/value,var/defer=0) - //testing("SetSEBlock([block],[value],[defer]): [value] -> [nval]") + if (block<=0) return ASSERT(value>=0) ASSERT(value<=4095) @@ -240,6 +240,7 @@ var/global/list/datum/dna/gene/dna_genes[0] dirtySE=1 if(!defer) UpdateSE() + //testing("SetSEBlock([block],[value],[defer]): [value] -> [GetSEValue(block)]") // Get a DNA SE block's raw value. /datum/dna/proc/GetSEValue(var/block) diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm index f0205ff9d1b..57eb989ffb7 100644 --- a/code/game/dna/genes/disabilities.dm +++ b/code/game/dna/genes/disabilities.dm @@ -139,4 +139,4 @@ block=LISPBLOCK OnSay(var/mob/M, var/message) - return replacetext(replacetext(message,"S","TH"),"s","th") \ No newline at end of file + return replacetext(message,"s","th") \ No newline at end of file diff --git a/code/game/dna/genes/gene.dm b/code/game/dna/genes/gene.dm index fc6fec4863b..1d46eb54d09 100644 --- a/code/game/dna/genes/gene.dm +++ b/code/game/dna/genes/gene.dm @@ -104,9 +104,6 @@ var/list/deactivation_messages=list() /datum/dna/gene/basic/can_activate(var/mob/M,var/flags) - if(mutation==0) - return 0 - // Probability check if(flags & MUTCHK_FORCED || probinj(activation_prob,(flags&MUTCHK_FORCED))) return 1 diff --git a/code/game/dna/genes/goon_disabilities.dm b/code/game/dna/genes/goon_disabilities.dm index 4491462fc85..acfd8c90fef 100644 --- a/code/game/dna/genes/goon_disabilities.dm +++ b/code/game/dna/genes/goon_disabilities.dm @@ -84,7 +84,7 @@ /datum/dna/gene/disability/speech can_activate(var/mob/M, var/flags) // Can only activate one of these at a time. - if(is_type_in_list(/datum/dna/gene/disability/speech,M.mutations)) + if(is_type_in_list(/datum/dna/gene/disability/speech,M.active_genes)) return 0 return ..(M,flags) @@ -239,7 +239,7 @@ block=STRONGBLOCK // WAS: /datum/bioEffect/horns -/datum/dna/gene/disability/strong +/datum/dna/gene/disability/horns name = "Horns" desc = "Enables the growth of a compacted keratin formation on the subject's head." activation_message = "A pair of horns erupt from your head." diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm index 4ec5853d7de..83b7e681e08 100644 --- a/code/game/dna/genes/goon_powers.dm +++ b/code/game/dna/genes/goon_powers.dm @@ -30,10 +30,15 @@ /datum/dna/gene/basic/stealth can_activate(var/mob/M, var/flags) // Can only activate one of these at a time. - if(is_type_in_list(/datum/dna/gene/basic/stealth,M.mutations)) + if(is_type_in_list(/datum/dna/gene/basic/stealth,M.active_genes)) + testing("Cannot activate [type]: /datum/dna/gene/basic/stealth in M.active_genes.") return 0 return ..(M,flags) + deactivate(var/mob/M) + ..(M) + M.alpha=255 + // WAS: /datum/bioEffect/darkcloak /datum/dna/gene/basic/stealth/darkcloak name = "Cloak of Darkness" @@ -49,9 +54,9 @@ if(!istype(T)) return if(T.lighting_lumcount <= 2) - M.alpha = round((255 * 0.15)) + M.alpha = round(255 * 0.05) else - M.alpha = round((255 * 0.80)) + M.alpha = round(255 * 0.80) //WAS: /datum/bioEffect/chameleon /datum/dna/gene/basic/stealth/chameleon @@ -64,8 +69,7 @@ block=CHAMELEONBLOCK OnMobLife(var/mob/M) - if((world.timeofday - M.last_move_intent) >= 30 && !M.stat && M.canmove && !M.restrained()) - M.alpha = round((255 * 0.15)) + if((world.time - M.last_movement) >= 30 && !M.stat && M.canmove && !M.restrained()) + M.alpha = round(255 * 0.10) else - M.alpha = round((255 * 0.80)) - return \ No newline at end of file + M.alpha = round(255 * 0.80) \ No newline at end of file diff --git a/code/game/gamemodes/blob/blobs/factory.dm b/code/game/gamemodes/blob/blobs/factory.dm index 1ab1b4a347b..0322a33cee8 100644 --- a/code/game/gamemodes/blob/blobs/factory.dm +++ b/code/game/gamemodes/blob/blobs/factory.dm @@ -40,6 +40,7 @@ attacktext = "hits" attack_sound = 'sound/weapons/genhit1.ogg' var/obj/effect/blob/factory/factory = null + var/is_zombie = 0 faction = "blob" min_oxy = 0 max_oxy = 0 @@ -70,10 +71,57 @@ factory.spores += src ..() - Die() - del(src) +/mob/living/simple_animal/hostile/blobspore/Life() - Del() - if(factory) - factory.spores -= src - ..() + if(!is_zombie) + for(var/mob/living/carbon/human/H in ListTargets(0)) //Only for people in the same tile + if(H.stat == DEAD) + Zombify(H) + break + ..() + +/mob/living/simple_animal/hostile/blobspore/proc/Zombify(var/mob/living/carbon/human/H) + if(H.wear_suit) + var/obj/item/clothing/suit/armor/A = H.wear_suit + if(A.armor && A.armor["melee"]) + maxHealth += A.armor["melee"] //That zombie's got armor, I want armor! + maxHealth += 40 + health = maxHealth + name = "blob zombie" + desc = "A shambling corpse animated by the blob." + melee_damage_lower = 10 + melee_damage_upper = 15 + icon = H.icon + icon_state = "husk_s" + H.h_style = null + H.update_hair() + overlays = H.overlays + overlays += image('icons/mob/blob.dmi', icon_state = "blob_head") + H.loc = src + is_zombie = 1 + loc.visible_message(" The corpse of [H.name] suddenly rises!") + +/mob/living/simple_animal/hostile/blobspore/Die() + // On death, create a small smoke of harmful gas (s-Acid) + var/datum/effect/effect/system/chem_smoke_spread/S = new + var/turf/location = get_turf(src) + + // Create the reagents to put into the air, s-acid is yellow and stings a little + create_reagents(25) + reagents.add_reagent("spore", 25) + + // Attach the smoke spreader and setup/start it. + S.attach(location) + S.set_up(reagents, 1, 1, location, 15, 1) // only 1-2 smoke cloud + S.start() + + del(src) + + +/mob/living/simple_animal/hostile/blobspore/Del() + if(factory) + factory.spores -= src + if(contents) + for(var/mob/M in contents) + M.loc = src.loc + ..() diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 99bc4154cd8..82a1c6d17d4 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -44,6 +44,7 @@ /obj/item/clothing/head/culthood/alt icon_state = "cult_hoodalt" item_state = "cult_hoodalt" + loose = 5 // one size fits all /obj/item/clothing/suit/cultrobes/alt icon_state = "cultrobesalt" @@ -70,6 +71,7 @@ flags = FPRINT|TABLEPASS|HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR armor = list(melee = 30, bullet = 30, laser = 30,energy = 20, bomb = 0, bio = 0, rad = 0) siemens_coefficient = 0 + loose = 6 // mostly one size fits all /obj/item/clothing/suit/magusred name = "magus robes" @@ -101,4 +103,4 @@ allowed = list(/obj/item/weapon/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency_oxygen) slowdown = 1 armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30) - siemens_coefficient = 0 + siemens_coefficient = 0 diff --git a/code/game/gamemodes/events/space_ninja.dm b/code/game/gamemodes/events/space_ninja.dm index 7168274bd07..f6661c1f1c9 100644 --- a/code/game/gamemodes/events/space_ninja.dm +++ b/code/game/gamemodes/events/space_ninja.dm @@ -303,8 +303,7 @@ Malf AIs/silicons aren't added. Monkeys aren't added. Messes with objective comp if(2)//Steal var/datum/objective/steal/ninja_objective = new ninja_objective.owner = ninja_mind - var/target_item = pick(ninja_objective.possible_items_special) - ninja_objective.set_target(target_item) + ninja_objective.find_target(1) // Find a special target. ninja_mind.objectives += ninja_objective objective_list -= 2 diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm index 24f2353b8ed..fc7cc1a648e 100644 --- a/code/game/gamemodes/nuclear/pinpointer.dm +++ b/code/game/gamemodes/nuclear/pinpointer.dm @@ -148,12 +148,18 @@ mode = 2 switch(alert("Search for item signature or DNA fragment?" , "Signature Mode Select" , "" , "Item" , "DNA")) if("Item") - var/datum/objective/steal/itemlist - itemlist = itemlist // To supress a 'variable defined but not used' error. - var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in itemlist.possible_items + var/list/item_names[0] + var/list/item_paths[0] + for(var/typepath in potential_theft_objectives) + var/obj/item/tmp_object=new typepath + var/n="[tmp_object]" + item_names+=n + item_paths[n]=typepath + del(tmp_object) + var/targetitem = input("Select item to search for.", "Item Mode Select","") as null|anything in potential_theft_objectives if(!targetitem) return - target=locate(itemlist.possible_items[targetitem]) + target=locate(item_paths[targetitem]) if(!target) usr << "Failed to locate [targetitem]!" return diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 6aaf0dd6cd1..27164b5abc9 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -1,5 +1,11 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 +var/list/potential_theft_objectives=typesof(/datum/theft_objective) \ + - /datum/theft_objective \ + - /datum/theft_objective/special \ + - /datum/theft_objective/number \ + - /datum/theft_objective/number/special + datum/objective var/datum/mind/owner = null //Who owns the objective. var/explanation_text = "Nothing" //What that person is supposed to do. @@ -478,131 +484,51 @@ datum/objective/nuclear datum/objective/steal - var/obj/item/steal_target - var/target_name + var/datum/theft_objective/steal_target - var/global/possible_items[] = list( - "the captain's antique laser gun" = /obj/item/weapon/gun/energy/laser/captain, - "a hand teleporter" = /obj/item/weapon/hand_tele, - "an RCD" = /obj/item/weapon/rcd, - "a jetpack" = /obj/item/weapon/tank/jetpack, - "a captain's jumpsuit" = /obj/item/clothing/under/rank/captain, - "a functional AI" = /obj/item/device/aicard, - "a pair of magboots" = /obj/item/clothing/shoes/magboots, - "the station blueprints" = /obj/item/blueprints, - "a nasa voidsuit" = /obj/item/clothing/suit/space/nasavoid, - "28 moles of plasma (full tank)" = /obj/item/weapon/tank, - "a sample of slime extract" = /obj/item/slime_extract, - "a piece of corgi meat" = /obj/item/weapon/reagent_containers/food/snacks/meat/corgi, - "a research director's jumpsuit" = /obj/item/clothing/under/rank/research_director, - "a chief engineer's jumpsuit" = /obj/item/clothing/under/rank/chief_engineer, - "a chief medical officer's jumpsuit" = /obj/item/clothing/under/rank/chief_medical_officer, - "a head of security's jumpsuit" = /obj/item/clothing/under/rank/head_of_security, - "a head of personnel's jumpsuit" = /obj/item/clothing/under/rank/head_of_personnel, - "the hypospray" = /obj/item/weapon/reagent_containers/hypospray, - "the captain's pinpointer" = /obj/item/weapon/pinpointer, - "an ablative armor vest" = /obj/item/clothing/suit/armor/laserproof, - "a laser pointer" = /obj/item/device/laser_pointer, - ) - - var/global/possible_items_special[] = list( - /*"nuclear authentication disk" = /obj/item/weapon/disk/nuclear,*///Broken with the change to nuke disk making it respawn on z level change. - "nuclear gun" = /obj/item/weapon/gun/energy/gun/nuclear, - "diamond drill" = /obj/item/weapon/pickaxe/diamonddrill, - "bag of holding" = /obj/item/weapon/storage/backpack/holding, - "hyper-capacity cell" = /obj/item/weapon/cell/hyper, - "10 diamonds" = /obj/item/stack/sheet/mineral/diamond, - "50 gold bars" = /obj/item/stack/sheet/mineral/gold, - "25 refined uranium bars" = /obj/item/stack/sheet/mineral/uranium, - ) - - - proc/set_target(item_name) - target_name = item_name - steal_target = possible_items[target_name] - if (!steal_target ) - steal_target = possible_items_special[target_name] - explanation_text = "Steal [target_name]." - return steal_target - - - find_target() - return set_target(pick(possible_items)) + find_target(var/special_only=0) + var/loop=50 + while(!steal_target && loop > 0) + loop-- + var/thefttype = pick(potential_theft_objectives) + var/datum/theft_objective/O = new thefttype + if(owner.assigned_role in O.protected_jobs) + continue + if(special_only) + if(!(O.flags & 1)) // THEFT_FLAG_SPECIAL + continue + else + if(O.flags & 1) // THEFT_FLAG_SPECIAL + continue + steal_target=O + explanation_text = "Steal [O]." + return + explanation_text = "Free Objective." proc/select_target() - var/list/possible_items_all = possible_items+possible_items_special+"custom" - var/new_target = input("Select target:", "Objective target", steal_target) as null|anything in possible_items_all + var/list/possible_items_all = potential_theft_objectives+"custom" + var/new_target = input("Select target:", "Objective target", null) as null|anything in possible_items_all if (!new_target) return if (new_target == "custom") - var/obj/item/custom_target = input("Select type:","Type") as null|anything in typesof(/obj/item) - if (!custom_target) return - var/tmp_obj = new custom_target + var/datum/theft_objective/O=new + O.typepath = input("Select type:","Type") as null|anything in typesof(/obj/item) + if (!O.typepath) return + var/tmp_obj = new O.typepath var/custom_name = tmp_obj:name del(tmp_obj) - custom_name = copytext(sanitize(input("Enter target name:", "Objective target", custom_name) as text|null),1,MAX_MESSAGE_LEN) - if (!custom_name) return - target_name = custom_name - steal_target = custom_target - explanation_text = "Steal [target_name]." + O.name = copytext(sanitize(input("Enter target name:", "Objective target", custom_name) as text|null),1,MAX_MESSAGE_LEN) + if (!O.name) return + steal_target = O + explanation_text = "Steal [O.name]." else - set_target(new_target) + steal_target = new new_target + explanation_text = "Steal [steal_target.name]." return steal_target check_completion() - if(!steal_target || !owner.current) return 0 - if(!isliving(owner.current)) return 0 - var/list/all_items = owner.current.get_contents() - switch (target_name) - if("28 moles of plasma (full tank)","10 diamonds","50 gold bars","25 refined uranium bars") - var/target_amount = text2num(target_name)//Non-numbers are ignored. - var/found_amount = 0.0//Always starts as zero. - - for(var/obj/item/I in all_items) //Check for plasma tanks - if(istype(I, steal_target)) - found_amount += (target_name=="28 moles of plasma (full tank)" ? (I:air_contents:toxins) : (I:amount)) - return found_amount>=target_amount - - if("50 coins (in bag)") - var/obj/item/weapon/moneybag/B = locate() in all_items - - if(B) - var/target = text2num(target_name) - var/found_amount = 0.0 - for(var/obj/item/weapon/coin/C in B) - found_amount++ - return found_amount>=target - - if("a functional AI") - for(var/obj/item/device/aicard/C in all_items) //Check for ai card - for(var/mob/living/silicon/ai/M in C) - if(istype(M, /mob/living/silicon/ai) && M.stat != 2) //See if any AI's are alive inside that card. - return 1 - - for(var/obj/item/clothing/suit/space/space_ninja/S in all_items) //Let an AI downloaded into a space ninja suit count - if(S.AI && S.AI.stat != 2) - return 1 - - for(var/mob/living/silicon/ai/ai in world) - if(istype(ai.loc, /turf)) - var/area/check_area = get_area(ai) - if(istype(check_area, /area/shuttle/escape/centcom)) - return 1 - if(istype(check_area, /area/shuttle/escape_pod1/centcom)) - return 1 - if(istype(check_area, /area/shuttle/escape_pod2/centcom)) - return 1 - if(istype(check_area, /area/shuttle/escape_pod3/centcom)) - return 1 - if(istype(check_area, /area/shuttle/escape_pod5/centcom)) - return 1 - else - - for(var/obj/I in all_items) //Check for items - if(istype(I, steal_target)) - return 1 - return 0 - + if(!steal_target) return 1 // Free Objective + return steal_target.check_completion(owner) datum/objective/download diff --git a/code/game/gamemodes/setupgame.dm b/code/game/gamemodes/setupgame.dm index 9f5741e25d4..dc85d7e9970 100644 --- a/code/game/gamemodes/setupgame.dm +++ b/code/game/gamemodes/setupgame.dm @@ -78,6 +78,13 @@ SHADOWBLOCK = getAssignedBlock("SHADOW", numsToAssign, DNA_HARDER_BOUNDS) CHAMELEONBLOCK = getAssignedBlock("CHAMELEON", numsToAssign, DNA_HARDER_BOUNDS) + // + // Static Blocks + /////////////////////////////////////////////. + + // Monkeyblock is always last. + MONKEYBLOCK = DNA_SE_LENGTH + // And the genes that actually do the work. (domutcheck improvements) var/list/blocks_assigned[DNA_SE_LENGTH] for(var/gene_type in typesof(/datum/dna/gene)) diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm new file mode 100644 index 00000000000..72d59460da5 --- /dev/null +++ b/code/game/gamemodes/steal_items.dm @@ -0,0 +1,227 @@ +// Theft objectives. +// +// Separated into datums so we can prevent roles from getting certain objectives. + +#define THEFT_FLAG_SPECIAL 1 + +/datum/theft_objective + var/name="" + var/typepath=/atom + var/list/protected_jobs=list() + var/flags=0 + +/datum/theft_objective/proc/check_completion(var/datum/mind/owner) + if(!owner.current) + return 0 + if(!isliving(owner.current)) + return 0 + var/list/all_items = owner.current.get_contents() + for(var/obj/I in all_items) //Check for items + if(istype(I, typepath)) + //Stealing the cheap autoinjector doesn't count + if(istype(I, /obj/item/weapon/reagent_containers/hypospray/autoinjector)) + continue + return 1 + return 0 + + +/datum/theft_objective/antique_laser_gun + name = "the captain's antique laser gun" + typepath = /obj/item/weapon/gun/energy/laser/captain + protected_jobs = list("Captain") + +/datum/theft_objective/hand_tele + name = "a hand teleporter" + typepath = /obj/item/weapon/hand_tele + protected_jobs = list("Captain") + +/datum/theft_objective/rcd + name = "an RCD" + typepath = /obj/item/weapon/rcd + protected_jobs = list("Chief Engineer") + +/datum/theft_objective/rpd + name = "an RPD" + typepath = /obj/item/weapon/pipe_dispenser + protected_jobs = list("Chief Engineer") + +/datum/theft_objective/jetpack + name = "a jetpack" + typepath = /obj/item/weapon/tank/jetpack + +/datum/theft_objective/cap_jumpsuit + name = "the captain's jumpsuit" + typepath = /obj/item/clothing/under/rank/captain + protected_jobs = list("Captain") + +/datum/theft_objective/ai + name = "a functional AI" + typepath = /obj/item/device/aicard + +/datum/theft_objective/magboots + name = "a pair of magboots" + typepath = /obj/item/clothing/shoes/magboots + protected_jobs = list("Station Engineer", "Atmospheric Technician", "Chief Engineer") + +/datum/theft_objective/blueprints + name = "the station blueprints" + typepath = /obj/item/blueprints + protected_jobs = list("Chief Engineer") + +/datum/theft_objective/voidsuit + name = "a nasa voidsuit" + typepath = /obj/item/clothing/suit/space/nasavoid + protected_jobs = list("Research Director") + +/datum/theft_objective/slime_extract + name = "a sample of slime extract" + typepath = /obj/item/slime_extract + +/datum/theft_objective/corgi + name = "a piece of corgi meat" + typepath = /obj/item/weapon/reagent_containers/food/snacks/meat/corgi + +/datum/theft_objective/rd_jumpsuit + name = "the research director's jumpsuit" + typepath = /obj/item/clothing/under/rank/research_director + protected_jobs = list("Research Director") + +/datum/theft_objective/ce_jumpsuit + name = "the chief engineer's jumpsuit" + typepath = /obj/item/clothing/under/rank/chief_engineer + protected_jobs = list("Chief Engineer") + +/datum/theft_objective/cmo_jumpsuit + name = "the chief medical officer's jumpsuit" + typepath = /obj/item/clothing/under/rank/chief_medical_officer + protected_jobs = list("Chief Medical Officer") + +/datum/theft_objective/hos_jumpsuit + name = "the head of security's jumpsuit" + typepath = /obj/item/clothing/under/rank/head_of_security + protected_jobs = list("Head of Security") + +/datum/theft_objective/hop_jumpsuit + name = "the head of personnel's jumpsuit" + typepath = /obj/item/clothing/under/rank/head_of_personnel + protected_jobs = list("Head of Personnel") + +/datum/theft_objective/hypospray + name = "a hypospray" + typepath = /obj/item/weapon/reagent_containers/hypospray + protected_jobs = list("Chief Medical Officer") + +/datum/theft_objective + name = "the captain's pinpointer" + typepath = /obj/item/weapon/pinpointer + protected_jobs = list("Captain") + +/datum/theft_objective + name = "an ablative armor vest" + typepath = /obj/item/clothing/suit/armor/laserproof + +/datum/theft_objective/number + var/min=0 + var/max=0 + var/step=1 + + var/required_amount=0 + +/datum/theft_objective/number/New() + if(min==max) + required_amount=min + else + var/lower=min/step + var/upper=min/step + required_amount=rand(lower,upper)*step + name = "[required_amount] [name]" + +/datum/theft_objective/number/check_completion(var/datum/mind/owner) + if(!owner.current) + return 0 + if(!isliving(owner.current)) + return 0 + var/list/all_items = owner.current.get_contents() + var/found_amount=0.0 + for(var/obj/item/I in all_items) + if(istype(I, typepath)) + found_amount += getAmountStolen(I) + return found_amount >= required_amount + +/datum/theft_objective/number/proc/getAmountStolen(var/obj/item/I) + return I:amount + +/datum/theft_objective/number/plasma_gas + name = "moles of plasma (full tank)" + typepath = /obj/item/weapon/tank + min=28 + max=28 + +/datum/theft_objective/number/plasma_gas/getAmountStolen(var/obj/item/I) + return I:air_contents:toxins + +/datum/theft_objective/number/coins + name = "credits of coins (in bag)" + min=1000 + max=5000 + step=500 + +/datum/theft_objective/number/coins/check_completion(var/datum/mind/owner) + if(!owner.current) + return 0 + if(!isliving(owner.current)) + return 0 + var/list/all_items = owner.current.get_contents() + var/found_amount=0.0 + for(var/obj/item/weapon/moneybag/B in all_items) + if(B) + for(var/obj/item/weapon/coin/C in B) + found_amount += C.credits + return found_amount >= required_amount + + +//////////////////////////////// +// SPECIAL OBJECTIVES +//////////////////////////////// +/datum/theft_objective/special + flags = THEFT_FLAG_SPECIAL + +/datum/theft_objective/special/nuke_gun + name = "nuclear gun" + typepath = /obj/item/weapon/gun/energy/gun/nuclear + +/datum/theft_objective/special/diamond_drill + name = "diamond drill" + typepath = /obj/item/weapon/pickaxe/diamonddrill + +/datum/theft_objective/special/boh + name = "bag of holding" + typepath = /obj/item/weapon/storage/backpack/holding + +/datum/theft_objective/special/hyper_cell + name = "hyper-capacity cell" + typepath = /obj/item/weapon/cell/hyper + +/datum/theft_objective/number/special + flags = THEFT_FLAG_SPECIAL + +/datum/theft_objective/number/special/diamonds + name = "diamonds" + typepath = /obj/item/stack/sheet/mineral/diamond + min=5 + max=10 + step=5 + +/datum/theft_objective/number/special/gold + name = "gold bars" + typepath = /obj/item/stack/sheet/mineral/gold + min=10 + max=50 + step=10 + +/datum/theft_objective/number/special/uranium + name = "refined uranium bars" + typepath = /obj/item/stack/sheet/mineral/uranium + min=10 + max=30 + step=5 \ No newline at end of file diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm index 0884e7eff1c..90f97035291 100644 --- a/code/game/gamemodes/vampire/vampire.dm +++ b/code/game/gamemodes/vampire/vampire.dm @@ -217,9 +217,9 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha if(!mind.vampire) mind.vampire = new /datum/vampire(gender) mind.vampire.owner = src - verbs += /client/proc/vampire_rejuvinate - verbs += /client/proc/vampire_hypnotise - verbs += /client/proc/vampire_glare + verbs += /client/vampire/proc/vampire_rejuvinate + verbs += /client/vampire/proc/vampire_hypnotise + verbs += /client/vampire/proc/vampire_glare //testing purposes REMOVE BEFORE PUSH TO MASTER /*for(var/handler in typesof(/client/proc)) if(findtext("[handler]","vampire_")) @@ -232,27 +232,27 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha for(var/n in mind.vampire.powers) switch(n) if(VAMP_SHAPE) - verbs += /client/proc/vampire_shapeshift + verbs += /client/vampire/proc/vampire_shapeshift if(VAMP_VISION) continue if(VAMP_DISEASE) - verbs += /client/proc/vampire_disease + verbs += /client/vampire/proc/vampire_disease if(VAMP_CLOAK) - verbs += /client/proc/vampire_cloak + verbs += /client/vampire/proc/vampire_cloak if(VAMP_BATS) - verbs += /client/proc/vampire_bats + verbs += /client/vampire/proc/vampire_bats if(VAMP_SCREAM) - verbs += /client/proc/vampire_screech + verbs += /client/vampire/proc/vampire_screech if(VAMP_JAUNT) - verbs += /client/proc/vampire_jaunt + verbs += /client/vampire/proc/vampire_jaunt if(VAMP_BLINK) - verbs += /client/proc/vampire_shadowstep + verbs += /client/vampire/proc/vampire_shadowstep if(VAMP_SLAVE) - verbs += /client/proc/vampire_enthrall + verbs += /client/vampire/proc/vampire_enthrall if(VAMP_FULL) continue /mob/proc/remove_vampire_powers() - for(var/handler in typesof(/client/proc)) + for(var/handler in typesof(/client/vampire/proc)) if(findtext("[handler]","vampire_")) verbs -= handler @@ -355,31 +355,31 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha switch(n) if(VAMP_SHAPE) src << "\blue You have gained the shapeshifting ability, at the cost of stored blood you can change your form permanently." - verbs += /client/proc/vampire_shapeshift + verbs += /client/vampire/proc/vampire_shapeshift if(VAMP_VISION) src << "\blue Your vampiric vision has improved." //no verb if(VAMP_DISEASE) src << "\blue You have gained the Diseased Touch ability which causes those you touch to die shortly after unless treated medically." - verbs += /client/proc/vampire_disease + verbs += /client/vampire/proc/vampire_disease if(VAMP_CLOAK) src << "\blue You have gained the Cloak of Darkness ability which when toggled makes you near invisible in the shroud of darkness." - verbs += /client/proc/vampire_cloak + verbs += /client/vampire/proc/vampire_cloak if(VAMP_BATS) src << "\blue You have gained the Summon Bats ability." - verbs += /client/proc/vampire_bats // work in progress + verbs += /client/vampire/proc/vampire_bats // work in progress if(VAMP_SCREAM) src << "\blue You have gained the Chriopteran Screech ability which stuns anything with ears in a large radius and shatters glass in the process." - verbs += /client/proc/vampire_screech + verbs += /client/vampire/proc/vampire_screech if(VAMP_JAUNT) src << "\blue You have gained the Mist Form ability which allows you to take on the form of mist for a short period and pass over any obstacle in your path." - verbs += /client/proc/vampire_jaunt + verbs += /client/vampire/proc/vampire_jaunt if(VAMP_SLAVE) src << "\blue You have gained the Enthrall ability which at a heavy blood cost allows you to enslave a human that is not loyal to any other for a random period of time." - verbs += /client/proc/vampire_enthrall + verbs += /client/vampire/proc/vampire_enthrall if(VAMP_BLINK) src << "\blue You have gained the ability to shadowstep, which makes you disappear into nearby shadows at the cost of blood." - verbs += /client/proc/vampire_shadowstep + verbs += /client/vampire/proc/vampire_shadowstep if(VAMP_FULL) src << "\blue You have reached your full potential and are no longer weak to the effects of anything holy and your vision has been improved greatly." //no verb diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index ab922cc413d..9540dd6880e 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -68,7 +68,7 @@ if(!vampire_power(required_blood, max_stat)) return return T -/client/proc/vampire_rejuvinate() +/client/vampire/proc/vampire_rejuvinate() set category = "Vampire" set name = "Rejuvinate " set desc= "Flush your system with spare blood to remove any incapacitating effects" @@ -88,11 +88,11 @@ M.current.adjustToxLoss(-2) M.current.adjustFireLoss(-2) sleep(35) - M.current.verbs -= /client/proc/vampire_rejuvinate + M.current.verbs -= /client/vampire/proc/vampire_rejuvinate spawn(200) - M.current.verbs += /client/proc/vampire_rejuvinate + M.current.verbs += /client/vampire/proc/vampire_rejuvinate -/client/proc/vampire_hypnotise() +/client/vampire/proc/vampire_hypnotise() set category = "Vampire" set name = "Hypnotise (20)" set desc= "A piercing stare that incapacitates your victim for a good length of time." @@ -104,9 +104,9 @@ if(!C) return M.current.visible_message("[M]'s eyes flash briefly as he stares into [C.name]'s eyes") M.current.remove_vampire_blood(20) - M.current.verbs -= /client/proc/vampire_hypnotise + M.current.verbs -= /client/vampire/proc/vampire_hypnotise spawn(1800) - M.current.verbs += /client/proc/vampire_hypnotise + M.current.verbs += /client/vampire/proc/vampire_hypnotise if(do_mob(M.current, C, 50)) if(C.mind && C.mind.vampire) M.current << "\red Your piercing gaze fails to knock out [C.name]." @@ -122,7 +122,7 @@ M.current << "\red You broke your gaze." return -/client/proc/vampire_disease() +/client/vampire/proc/vampire_disease() set category = "Vampire" set name = "Diseased Touch (100)" set desc = "Touches your victim with infected blood giving them the Shutdown Syndrome which quickly shutsdown their major organs resulting in a quick painful death." @@ -162,10 +162,10 @@ shutdown.clicks = 185 infect_virus2(C,shutdown,0) M.current.remove_vampire_blood(100) - M.current.verbs -= /client/proc/vampire_disease - spawn(1800) M.current.verbs += /client/proc/vampire_disease + M.current.verbs -= /client/vampire/proc/vampire_disease + spawn(1800) M.current.verbs += /client/vampire/proc/vampire_disease -/client/proc/vampire_glare() +/client/vampire/proc/vampire_glare() set category = "Vampire" set name = "Glare" set desc= "A scary glare that incapacitates people for a short while around you." @@ -174,9 +174,9 @@ if(M.current.vampire_power(0, 1)) M.current.visible_message("\red [M.current]'s eyes emit a blinding flash!") //M.vampire.bloodusable -= 10 - M.current.verbs -= /client/proc/vampire_glare + M.current.verbs -= /client/vampire/proc/vampire_glare spawn(300) - M.current.verbs += /client/proc/vampire_glare + M.current.verbs += /client/vampire/proc/vampire_glare if(istype(M.current:glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) M.current << "You're blindfolded!" return @@ -188,7 +188,7 @@ C.stuttering = 20 C << "\red You are blinded by [M.current]'s glare" -/client/proc/vampire_shapeshift() +/client/vampire/proc/vampire_shapeshift() set category = "Vampire" set name = "Shapeshift (50)" set desc = "Changes your name and appearance at the cost of 50 blood and has a cooldown of 3 minutes." @@ -200,10 +200,10 @@ M.current.client.prefs.randomize_appearance_for(M.current) M.current.regenerate_icons() M.current.remove_vampire_blood(50) - M.current.verbs -= /client/proc/vampire_shapeshift - spawn(1800) M.current.verbs += /client/proc/vampire_shapeshift + M.current.verbs -= /client/vampire/proc/vampire_shapeshift + spawn(1800) M.current.verbs += /client/vampire/proc/vampire_shapeshift -/client/proc/vampire_screech() +/client/vampire/proc/vampire_screech() set category = "Vampire" set name = "Chiroptean Screech (30)" set desc = "An extremely loud shriek that stuns nearby humans and breaks windows as well." @@ -227,10 +227,10 @@ del(W) playsound(M.current.loc, 'sound/effects/creepyshriek.ogg', 100, 1) M.current.remove_vampire_blood(30) - M.current.verbs -= /client/proc/vampire_screech - spawn(1800) M.current.verbs += /client/proc/vampire_screech + M.current.verbs -= /client/vampire/proc/vampire_screech + spawn(1800) M.current.verbs += /client/vampire/proc/vampire_screech -/client/proc/vampire_enthrall() +/client/vampire/proc/vampire_enthrall() set category = "Vampire" set name = "Enthrall (300)" set desc = "You use a large portion of your power to sway those loyal to none to be loyal to you only." @@ -248,15 +248,15 @@ if(M.current.can_enthrall(C) && M.current.vampire_power(300, 0)) // recheck M.current.handle_enthrall(C) M.current.remove_vampire_blood(300) - M.current.verbs -= /client/proc/vampire_enthrall - spawn(1800) M.current.verbs += /client/proc/vampire_enthrall + M.current.verbs -= /client/vampire/proc/vampire_enthrall + spawn(1800) M.current.verbs += /client/vampire/proc/vampire_enthrall else M.current << "\red You or your target either moved or you dont have enough usable blood." return -/client/proc/vampire_cloak() +/client/vampire/proc/vampire_cloak() set category = "Vampire" set name = "Cloak of Darkness (toggle)" set desc = "Toggles whether you are currently cloaking yourself in darkness." @@ -319,7 +319,7 @@ ticker.mode.update_vampire_icons_added(src.mind) log_admin("[ckey(src.key)] has mind-slaved [ckey(H.key)].") -/client/proc/vampire_bats() +/client/vampire/proc/vampire_bats() set category = "Vampire" set name = "Summon Bats (75)" set desc = "You summon a pair of space bats who attack nearby targets until they or their target is dead." @@ -344,10 +344,10 @@ new /mob/living/simple_animal/hostile/scarybat(M.current.loc, M.current) new /mob/living/simple_animal/hostile/scarybat(M.current.loc, M.current) M.current.remove_vampire_blood(75) - M.current.verbs -= /client/proc/vampire_bats - spawn(1200) M.current.verbs += /client/proc/vampire_bats + M.current.verbs -= /client/vampire/proc/vampire_bats + spawn(1200) M.current.verbs += /client/vampire/proc/vampire_bats -/client/proc/vampire_jaunt() +/client/vampire/proc/vampire_jaunt() //AHOY COPY PASTE INCOMING set category = "Vampire" set name = "Mist Form (30)" @@ -401,12 +401,12 @@ del(animation) del(holder) M.current.remove_vampire_blood(30) - M.current.verbs -= /client/proc/vampire_jaunt - spawn(600) M.current.verbs += /client/proc/vampire_jaunt + M.current.verbs -= /client/vampire/proc/vampire_jaunt + spawn(600) M.current.verbs += /client/vampire/proc/vampire_jaunt // Blink for vamps // Less smoke spam. -/client/proc/vampire_shadowstep() +/client/vampire/proc/vampire_shadowstep() set category = "Vampire" set name = "Shadowstep (30)" set desc = "Vanish into the shadows." @@ -458,9 +458,9 @@ spawn(10) del(animation) M.current.remove_vampire_blood(30) - M.current.verbs -= /client/proc/vampire_shadowstep + M.current.verbs -= /client/vampire/proc/vampire_shadowstep spawn(20) - M.current.verbs += /client/proc/vampire_shadowstep + M.current.verbs += /client/vampire/proc/vampire_shadowstep /mob/proc/remove_vampire_blood(amount = 0) var/bloodold diff --git a/code/game/machinery/Freezer.dm b/code/game/machinery/Freezer.dm index 319c7a89002..7de58c6f220 100644 --- a/code/game/machinery/Freezer.dm +++ b/code/game/machinery/Freezer.dm @@ -1,5 +1,5 @@ /obj/machinery/atmospherics/unary/cold_sink/freezer - name = "Freezer" + name = "gas cooling system" icon = 'icons/obj/Cryogenic2.dmi' icon_state = "freezer_0" density = 1 @@ -8,84 +8,91 @@ current_heat_capacity = 1000 - New() - ..() - initialize_directions = dir +/obj/machinery/atmospherics/unary/cold_sink/freezer/New() + ..() + initialize_directions = dir - initialize() - if(node) return +/obj/machinery/atmospherics/unary/cold_sink/freezer/initialize() + if(node) return - var/node_connect = dir - - for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) - if(target.initialize_directions & get_dir(target,src)) - node = target - break - - update_icon() + var/node_connect = dir + for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) + if(target.initialize_directions & get_dir(target,src)) + node = target + break update_icon() - if(src.node) - if(src.on) - icon_state = "freezer_1" - else - icon_state = "freezer" + + +/obj/machinery/atmospherics/unary/cold_sink/freezer/update_icon() + if(src.node) + if(src.on) + icon_state = "freezer_1" else - icon_state = "freezer_0" - return + icon_state = "freezer" + else + icon_state = "freezer_0" + return - attack_ai(mob/user as mob) - return src.attack_hand(user) +/obj/machinery/atmospherics/unary/cold_sink/freezer/attack_ai(mob/user as mob) + src.ui_interact(user) - attack_paw(mob/user as mob) - return src.attack_hand(user) +/obj/machinery/atmospherics/unary/cold_sink/freezer/attack_paw(mob/user as mob) + src.ui_interact(user) - attack_hand(mob/user as mob) - user.set_machine(src) - var/temp_text = "" - if(air_contents.temperature > (T0C - 20)) - temp_text = "[air_contents.temperature]" - else if(air_contents.temperature < (T0C - 20) && air_contents.temperature > (T0C - 100)) - temp_text = "[air_contents.temperature]" +/obj/machinery/atmospherics/unary/cold_sink/freezer/attack_hand(mob/user as mob) + src.ui_interact(user) + +/obj/machinery/atmospherics/unary/cold_sink/freezer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + // this is the data which will be sent to the ui + var/data[0] + data["on"] = on ? 1 : 0 + data["gasPressure"] = round(air_contents.return_pressure()) + data["gasTemperature"] = round(air_contents.temperature) + data["minGasTemperature"] = round(T0C - 200) + data["maxGasTemperature"] = round(T20C) + data["targetGasTemperature"] = round(current_temperature) + + var/temp_class = "good" + if (air_contents.temperature > (T0C - 20)) + temp_class = "bad" + else if (air_contents.temperature < (T0C - 20) && air_contents.temperature > (T0C - 100)) + temp_class = "average" + data["gasTemperatureClass"] = temp_class + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "freezer.tmpl", "Gas Cooling System", 440, 300) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + ui.set_auto_update(1) + +/obj/machinery/atmospherics/unary/cold_sink/freezer/Topic(href, href_list) + if (href_list["toggleStatus"]) + src.on = !src.on + update_icon() + if(href_list["temp"]) + var/amount = text2num(href_list["temp"]) + if(amount > 0) + src.current_temperature = min(T20C, src.current_temperature+amount) else - temp_text = "[air_contents.temperature]" - - var/dat = {"Cryo gas cooling system
- Current status: [ on ? "Off On" : "Off On"]
- Current gas temperature: [temp_text]
- Current air pressure: [air_contents.return_pressure()]
- Target gas temperature: - - - [current_temperature] + + +
- "} - - user << browse(dat, "window=freezer;size=400x500") - onclose(user, "freezer") - - Topic(href, href_list) - if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) - usr.set_machine(src) - if (href_list["start"]) - src.on = !src.on - update_icon() - if(href_list["temp"]) - var/amount = text2num(href_list["temp"]) - if(amount > 0) - src.current_temperature = min(T20C, src.current_temperature+amount) - else - src.current_temperature = max((T0C - 200), src.current_temperature+amount) - src.updateUsrDialog() - src.add_fingerprint(usr) - return - - process() - ..() - src.updateUsrDialog() - + src.current_temperature = max((T0C - 200), src.current_temperature+amount) + src.add_fingerprint(usr) + return 1 +/obj/machinery/atmospherics/unary/cold_sink/freezer/process() + ..() /obj/machinery/atmospherics/unary/heat_reservoir/heater - name = "Heater" + name = "gas heating system" icon = 'icons/obj/Cryogenic2.dmi' icon_state = "freezer_0" density = 1 @@ -94,73 +101,83 @@ current_heat_capacity = 1000 - New() - ..() - initialize_directions = dir +/obj/machinery/atmospherics/unary/heat_reservoir/heater/New() + ..() + initialize_directions = dir - initialize() - if(node) return +/obj/machinery/atmospherics/unary/heat_reservoir/heater/initialize() + if(node) return - var/node_connect = dir - - for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) - if(target.initialize_directions & get_dir(target,src)) - node = target - break - - update_icon() + var/node_connect = dir + for(var/obj/machinery/atmospherics/target in get_step(src,node_connect)) + if(target.initialize_directions & get_dir(target,src)) + node = target + break update_icon() - if(src.node) - if(src.on) - icon_state = "heater_1" - else - icon_state = "heater" + + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/update_icon() + if(src.node) + if(src.on) + icon_state = "heater_1" else - icon_state = "heater_0" - return + icon_state = "heater" + else + icon_state = "heater_0" + return - attack_ai(mob/user as mob) - return src.attack_hand(user) +/obj/machinery/atmospherics/unary/heat_reservoir/heater/attack_ai(mob/user as mob) + src.ui_interact(user) - attack_paw(mob/user as mob) - return src.attack_hand(user) +/obj/machinery/atmospherics/unary/heat_reservoir/heater/attack_paw(mob/user as mob) + src.ui_interact(user) - attack_hand(mob/user as mob) - user.set_machine(src) - var/temp_text = "" - if(air_contents.temperature > (T20C+40)) - temp_text = "[air_contents.temperature]" +/obj/machinery/atmospherics/unary/heat_reservoir/heater/attack_hand(mob/user as mob) + src.ui_interact(user) + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null) + // this is the data which will be sent to the ui + var/data[0] + data["on"] = on ? 1 : 0 + data["gasPressure"] = round(air_contents.return_pressure()) + data["gasTemperature"] = round(air_contents.temperature) + data["minGasTemperature"] = round(T20C) + data["maxGasTemperature"] = round(T20C+280) + data["targetGasTemperature"] = round(current_temperature) + + var/temp_class = "normal" + if (air_contents.temperature > (T20C+40)) + temp_class = "bad" + data["gasTemperatureClass"] = temp_class + + // update the ui if it exists, returns null if no ui is passed/found + ui = nanomanager.try_update_ui(user, src, ui_key, ui, data) + if (!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "freezer.tmpl", "Gas Heating System", 440, 300) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every Master Controller tick + ui.set_auto_update(1) + +/obj/machinery/atmospherics/unary/heat_reservoir/heater/Topic(href, href_list) + if (href_list["toggleStatus"]) + src.on = !src.on + update_icon() + if(href_list["temp"]) + var/amount = text2num(href_list["temp"]) + if(amount > 0) + src.current_temperature = min((T20C+280), src.current_temperature+amount) else - temp_text = "[air_contents.temperature]" + src.current_temperature = max(T20C, src.current_temperature+amount) + + src.add_fingerprint(usr) + return 1 - var/dat = {"Heating system
- Current status: [ on ? "Off On" : "Off On"]
- Current gas temperature: [temp_text]
- Current air pressure: [air_contents.return_pressure()]
- Target gas temperature: - - - [current_temperature] + + +
- "} - - user << browse(dat, "window=heater;size=400x500") - onclose(user, "heater") - - Topic(href, href_list) - if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon/ai))) - usr.set_machine(src) - if (href_list["start"]) - src.on = !src.on - update_icon() - if(href_list["temp"]) - var/amount = text2num(href_list["temp"]) - if(amount > 0) - src.current_temperature = min((T20C+280), src.current_temperature+amount) - else - src.current_temperature = max(T20C, src.current_temperature+amount) - src.updateUsrDialog() - src.add_fingerprint(usr) - return - - process() - ..() - src.updateUsrDialog() \ No newline at end of file +/obj/machinery/atmospherics/unary/heat_reservoir/heater/process() + ..() \ No newline at end of file diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 75e7282c4b0..4d7c2328d1f 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -63,7 +63,7 @@ for(var/i=new_SE.len;i<=DNA_SE_LENGTH;i++) new_SE += rand(1,1024) buf.dna.SE=new_SE - buf.dna.SetSEValue(MONKEYBLOCK,0xFFF) + buf.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) //Find a dead mob with a brain and client. diff --git a/code/game/machinery/computer/HolodeckControl.dm b/code/game/machinery/computer/HolodeckControl.dm index 069db8ea340..7a6e1c405e7 100644 --- a/code/game/machinery/computer/HolodeckControl.dm +++ b/code/game/machinery/computer/HolodeckControl.dm @@ -43,9 +43,9 @@ dat += "Please ensure that only holographic weapons are used in the holodeck if a combat simulation has been loaded.
" if(emagged) - dat += "(Begin Atmospheric Burn Simulation)
" +/* dat += "(Begin Atmospheric Burn Simulation)
" dat += "Ensure the holodeck is empty before testing.
" - dat += "
" + dat += "
"*/ dat += "(Begin Wildlife Simulation)
" dat += "Ensure the holodeck is empty before testing.
" dat += "
" @@ -130,13 +130,13 @@ target = locate(/area/holodeck/source_plating) if(target) loadProgram(target) - +/* else if(href_list["burntest"]) if(!emagged) return target = locate(/area/holodeck/source_burntest) if(target) loadProgram(target) - +*/ else if(href_list["wildlifecarp"]) if(!emagged) return target = locate(/area/holodeck/source_wildlife) @@ -339,7 +339,7 @@ spawn(30) for(var/obj/effect/landmark/L in linkedholodeck) - if(L.name=="Atmospheric Test Start") +/* if(L.name=="Atmospheric Test Start") spawn(20) var/turf/T = get_turf(L) var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread @@ -347,9 +347,9 @@ s.start() if(T) T.temperature = 5000 - T.hotspot_expose(50000,50000,1) + T.hotspot_expose(50000,50000,1)*/ if(L.name=="Holocarp Spawn") - new /mob/living/simple_animal/hostile/carp(L.loc) + new /mob/living/simple_animal/hostile/carp/holocarp(L.loc) /obj/machinery/computer/HolodeckControl/proc/emergencyShutdown() diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 7427a7f0f2e..2f2c3a5dbd0 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -224,7 +224,7 @@ return -/obj/item/proc/talk_into(mob/M as mob, text) +/obj/item/proc/talk_into(mob/M as mob, var/text, var/channel=null) return /obj/item/proc/moved(mob/user as mob, old_loc as turf) diff --git a/code/game/objects/items/devices/PDA/radio.dm b/code/game/objects/items/devices/PDA/radio.dm index 9dc462814e4..e3c8a5d23f7 100644 --- a/code/game/objects/items/devices/PDA/radio.dm +++ b/code/game/objects/items/devices/PDA/radio.dm @@ -5,7 +5,7 @@ icon_state = "power_mod" var/obj/item/device/pda/hostpda = null - var/on = 0 //Are we currently active?? + var/on = 0 //Are we currently active? var/menu_message = "" New() diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm index ec8075e85bc..0d12f8262b6 100644 --- a/code/game/objects/items/devices/megaphone.dm +++ b/code/game/objects/items/devices/megaphone.dm @@ -19,7 +19,8 @@ if(!ishuman(user)) user << "\red You don't know how to use this!" return - if(user.silent) + if(user:miming || user.silent) + user << "\red You find yourself unable to speak at all." return if(spamcheck) user << "\red \The [src] needs to recharge!" diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 5f062d62abc..432710a5bea 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -38,6 +38,8 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use var/const/FREQ_LISTENING = 1 //FREQ_BROADCASTING = 2 + var/always_talk=0 // ALWAYS catch signals. Useful for covert listening devices. + /obj/item/device/radio var/datum/radio_frequency/radio_connection var/list/datum/radio_frequency/secure_radio_connections @@ -243,14 +245,21 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use //#### Grab the connection datum ####// var/datum/radio_frequency/connection = null - if(channel && channels && channels.len > 0) - if (channel == "department") - //world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\"" - channel = channels[1] - connection = secure_radio_connections[channel] - if (!channels[channel]) // if the channel is turned off, don't broadcast + testing("[src]: talk_into([M], [message], [channel])") + if(channel == "headset") + channel = null + if(channel) // If a channel is specified, look for it. + if(channels && channels.len > 0) + if (channel == "department") + //world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\"" + channel = channels[1] + connection = secure_radio_connections[channel] + if (!channels[channel]) // if the channel is turned off, don't broadcast + return + else + // If we were to send to a channel we don't have, drop it. return - else + else // If a channel isn't specified, send to common. connection = radio_connection channel = null if (!istype(connection)) diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm index 3a57eae84c2..ecba85ad365 100644 --- a/code/game/objects/items/weapons/extinguisher.dm +++ b/code/game/objects/items/weapons/extinguisher.dm @@ -1,3 +1,4 @@ + /obj/item/weapon/extinguisher name = "fire extinguisher" desc = "A traditional red fire extinguisher." @@ -13,18 +14,18 @@ force = 10 m_amt = 90 attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed") - var/list/reagents_to_log=list( - "fuel"= "welder fuel", - "plasma"= "plasma", - "pacid"= "polytrinic acid", - "sacid"= "sulphuric acid" - ) - var/max_water = 50 var/last_use = 1.0 var/safety = 1 var/sprite_name = "fire_extinguisher" + reagents_to_log=list( + "fuel" = "welder fuel", + "plasma"= "plasma", + "pacid" = "polytrinic acid", + "sacid" = "sulphuric acid" + ) + /obj/item/weapon/extinguisher/mini name = "fire extinguisher" desc = "A light and compact fibreglass-framed model fire extinguisher." diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index d68a7b3c8d3..46b9eefec7c 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -16,6 +16,10 @@ var/damtype = "brute" var/force = 0 + // What reagents should be logged when transferred TO this object? + // Reagent ID => friendly name + var/list/reagents_to_log=list() + /obj/item/proc/is_used_on(obj/O, mob/user) /obj/proc/process() diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 299c7eb27d3..f49433d6afc 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -166,7 +166,7 @@ return /obj/structure/closet/attack_animal(mob/living/simple_animal/user as mob) - if(user.wall_smash) + if(user.environment_smash) visible_message("\red [user] destroys the [src]. ") for(var/atom/movable/A as mob|obj in src) A.loc = src.loc diff --git a/code/game/objects/structures/crates_lockers/closets/statue.dm b/code/game/objects/structures/crates_lockers/closets/statue.dm index 0c642bd9e14..b014a672712 100644 --- a/code/game/objects/structures/crates_lockers/closets/statue.dm +++ b/code/game/objects/structures/crates_lockers/closets/statue.dm @@ -99,7 +99,7 @@ return /obj/structure/closet/statue/attack_animal(mob/living/simple_animal/user as mob) - if(user.wall_smash) + if(user.environment_smash) for(var/mob/M in src) shatter(M) @@ -142,4 +142,4 @@ user.dust() dump_contents() visible_message("\red [src] shatters!. ") - del(src) \ No newline at end of file + del(src) diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index a9a767b84bc..11712a7f4c2 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -1,22 +1,43 @@ /obj/structure/displaycase name = "Display Case" icon = 'icons/obj/stationobjs.dmi' - icon_state = "glassbox1" + icon_state = "glassbox20" desc = "A display case for prized possessions. It taunts you to kick it." density = 1 anchored = 1 unacidable = 1//Dissolving the case would also delete the gun. var/health = 30 - var/occupied = 1 + var/obj/item/occupant = null var/destroyed = 0 + var/locked = 0 + var/ue=null + var/icon/occupant_overlay=null + +/obj/structure/displaycase/captains_laser/New() + occupant=new /obj/item/weapon/gun/energy/laser/captain(src) + locked=1 + req_access=list(access_captain) + update_icon() + +/obj/structure/displaycase/examine() + ..() + usr << "\blue Peering through the glass, you see that it contains:" + if(occupant) + usr << "\icon[occupant] \blue \A [occupant]" + else: + usr << "Nothing." + +/obj/structure/displaycase/proc/dump() + occupant.loc=get_turf(src) + occupant=null + occupant_overlay=null /obj/structure/displaycase/ex_act(severity) switch(severity) if (1) new /obj/item/weapon/shard( src.loc ) - if (occupied) - new /obj/item/weapon/gun/energy/laser/captain( src.loc ) - occupied = 0 + if (occupant) + dump() del(src) if (2) if (prob(50)) @@ -38,15 +59,13 @@ /obj/structure/displaycase/blob_act() if (prob(75)) new /obj/item/weapon/shard( src.loc ) - if (occupied) - new /obj/item/weapon/gun/energy/laser/captain( src.loc ) - occupied = 0 + if(occupant) dump() del(src) /obj/structure/displaycase/meteorhit(obj/O as obj) new /obj/item/weapon/shard( src.loc ) - new /obj/item/weapon/gun/energy/laser/captain( src.loc ) + if(occupant) dump() del(src) @@ -64,36 +83,86 @@ /obj/structure/displaycase/update_icon() if(src.destroyed) - src.icon_state = "glassboxb[src.occupied]" + src.icon_state = "glassbox2b" else - src.icon_state = "glassbox[src.occupied]" + src.icon_state = "glassbox2[locked]" + underlays.Cut() + if(occupant) + if(!occupant_overlay) + occupant_overlay=getFlatIcon(occupant) + occupant_overlay.Scale(16,16) + occupant_overlay.Shift(NORTH, 8) + occupant_overlay.Shift(EAST, 8) + underlays += occupant_overlay return /obj/structure/displaycase/attackby(obj/item/weapon/W as obj, mob/user as mob) - src.health -= W.force - src.healthcheck() - ..() - return + if(istype(W, /obj/item/weapon/card)) + var/obj/item/weapon/card/id/I=W + if(!check_access(I)) + user << "\red Access denied." + return + locked = !locked + if(!locked) + user << "\icon[src] \blue \The [src] clicks as locks release, and it slowly opens for you." + else + user << "\icon[src] \blue You close \the [src] and swipe your card, locking it." + update_icon() + return + if(user.a_intent == "harm") + src.health -= W.force + src.healthcheck() + ..() + else + if(locked) + user << "\red It's locked, you can't put anything into it." + return + if(!occupant) + user << "\blue You insert \the [W] into \the [src], and it floats as the hoverfield activates." + user.drop_item() + W.loc=src + occupant=W + update_icon() /obj/structure/displaycase/attack_paw(mob/user as mob) return src.attack_hand(user) +/obj/structure/displaycase/proc/getPrint(mob/user as mob) + return md5(user:dna:uni_identity) + /obj/structure/displaycase/attack_hand(mob/user as mob) - if (src.destroyed && src.occupied) - new /obj/item/weapon/gun/energy/laser/captain( src.loc ) - user << "\b You deactivate the hover field built into the case." - src.occupied = 0 - src.add_fingerprint(user) - update_icon() - return + if (destroyed) + if(occupant) + dump() + user << "\red You smash your fist into the delicate electronics at the bottom of the case, and deactivate the hover field permanently." + src.add_fingerprint(user) + update_icon() else - usr << text("\blue You kick the display case.") - for(var/mob/O in oviewers()) - if ((O.client && !( O.blinded ))) - O << text("\red [] kicks the display case.", usr) - src.health -= 2 - healthcheck() - return + if(user.a_intent == "harm") + user.visible_message("\red [user.name] kicks \the [src]!", \ + "\red You kick \the [src]!", \ + "You hear glass crack.") + src.health -= 2 + healthcheck() + else if(!locked) + if(ishuman(user)) + if(!ue) + user << "\blue Your press your thumb against the fingerprint scanner, registering your identity with the case." + ue = getPrint(user) + return + if(ue!=getPrint(user)) + user << "\red Access denied." + return + user << "\blue Your press your thumb against the fingerprint scanner, and deactivate the hover field built into the case." + if(occupant) + dump() + update_icon() + else + src << "\icon[src] \red \The [src] is empty!" + else + user.visible_message("[user.name] gently runs his hands over \the [src] in appreciation of its contents.", \ + "You gently run your hands over \the [src] in appreciation of its contents.", \ + "You hear someone streaking glass with their greasy hands.") diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index 7339c88646d..c8ef0afbde5 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -36,9 +36,16 @@ manual_unbuckle(user) return + /obj/structure/stool/bed/MouseDrop(atom/over_object) return +/obj/structure/stool/bed/attack_animal(var/mob/living/simple_animal/M)//No more buckling hostile mobs to chairs to render them immobile forever + if(M.environment_smash) + new /obj/item/stack/sheet/metal(src.loc) + del(src) + + /obj/structure/stool/bed/MouseDrop_T(mob/M as mob, mob/user as mob) if(!istype(M)) return buckle_mob(M, user) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index f8cb733e30f..28f5dbfdf49 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -391,7 +391,7 @@ destroy() /obj/structure/table/attack_animal(mob/living/simple_animal/user) - if(user.wall_smash || istype(user,/mob/living/simple_animal/hostile/carp)) + if(user.environment_smash) visible_message("[user] smashes [src] apart!") destroy() @@ -867,7 +867,7 @@ /obj/structure/rack/attack_animal(mob/living/simple_animal/user) - if(user.wall_smash) + if(user.environment_smash) visible_message("[user] smashes [src] apart!") destroy() diff --git a/code/game/sound.dm b/code/game/sound.dm index 876f65d811c..6eaa6abe651 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -68,6 +68,7 @@ var/const/SURROUND_CAP = 7 if ("explosion") soundin = pick('sound/effects/Explosion1.ogg','sound/effects/Explosion2.ogg') if ("sparks") soundin = pick('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks4.ogg') if ("rustle") soundin = pick('sound/effects/rustle1.ogg','sound/effects/rustle2.ogg','sound/effects/rustle3.ogg','sound/effects/rustle4.ogg','sound/effects/rustle5.ogg') + if ("bodyfall") soundin = pick('sound/effects/bodyfall1.ogg','sound/effects/bodyfall2.ogg','sound/effects/bodyfall3.ogg','sound/effects/bodyfall4.ogg') if ("punch") soundin = pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg') if ("clownstep") soundin = pick('sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg') if ("jackboot") soundin = pick('sound/effects/jackboot1.ogg','sound/effects/jackboot2.ogg') diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 67a74c8acca..24b61d8a5f0 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -103,23 +103,18 @@ return src.attack_hand(user) - -/turf/simulated/wall/attack_animal(mob/living/simple_animal/M as mob) - if(M.wall_smash) - if (istype(src, /turf/simulated/wall/r_wall) && !rotting) - M << text("\blue This wall is far too strong for you to destroy.") - return - else - if (prob(40) || rotting) - M << text("\blue You smash through the wall.") +/turf/simulated/wall/attack_animal(var/mob/living/simple_animal/M) + if(M.environment_smash >= 2) + if(istype(src, /turf/simulated/wall/r_wall)) + if(M.environment_smash == 3) dismantle_wall(1) - return + M << "You smash through the wall." else - M << text("\blue You smash against the wall.") - return - - M << "\blue You push the wall but nothing happens!" - return + M << "This wall is far too strong for you to destroy." + else + M << "You smash through the wall." + dismantle_wall(1) + return /turf/simulated/wall/attack_hand(mob/user as mob) if (M_HULK in user.mutations) @@ -394,4 +389,4 @@ /turf/simulated/wall/ChangeTurf(var/newtype) for(var/obj/effect/E in src) if(E.name == "Wallrot") del E - ..(newtype) \ No newline at end of file + ..(newtype) diff --git a/code/global.dm b/code/global.dm index 21d2c9a7586..038f9ab0bc0 100644 --- a/code/global.dm +++ b/code/global.dm @@ -47,7 +47,7 @@ var/GLASSESBLOCK = 0 var/EPILEPSYBLOCK = 0 var/TWITCHBLOCK = 0 var/NERVOUSBLOCK = 0 -var/MONKEYBLOCK = 27 +var/MONKEYBLOCK = 50 // Monkey block will always be the DNA_SE_LENGTH var/BLOCKADD = 0 var/DIFFMUT = 0 diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm index fe97f8758c8..a58c43bf0ba 100644 --- a/code/modules/admin/verbs/onlyone.dm +++ b/code/modules/admin/verbs/onlyone.dm @@ -10,10 +10,12 @@ ticker.mode.traitors += H.mind H.mind.special_role = "traitor" + /* This never worked. var/datum/objective/steal/steal_objective = new steal_objective.owner = H.mind steal_objective.set_target("nuclear authentication disk") H.mind.objectives += steal_objective + */ var/datum/objective/hijack/hijack_objective = new hijack_objective.owner = H.mind @@ -64,4 +66,4 @@ M.apply_damage(10, HALLOSS) if(prob(5)) M.Weaken(3) - visible_message("\red [M] HAS BEEN ELIMINATED!!", 3) \ No newline at end of file + visible_message("\red [M] HAS BEEN ELIMINATED!!", 3) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 39f56e1825b..b6c26899dd0 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -157,6 +157,7 @@ BLIND // can't see anything icon = 'icons/obj/clothing/hats.dmi' body_parts_covered = HEAD slot_flags = SLOT_HEAD + var/loose = 10 // probability (0..100) of coming off your head when you fall over or lay down //Mask @@ -209,6 +210,7 @@ BLIND // can't see anything min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECITON_TEMPERATURE siemens_coefficient = 0.9 species_restricted = list("exclude","Diona","Vox") + loose = 1 // very rarely falls off /obj/item/clothing/suit/space name = "Space suit" diff --git a/code/modules/clothing/head/collectable.dm b/code/modules/clothing/head/collectable.dm index 50e1215d277..2f839c5cb19 100644 --- a/code/modules/clothing/head/collectable.dm +++ b/code/modules/clothing/head/collectable.dm @@ -9,39 +9,46 @@ name = "ultra rare Pete's hat!" desc = "It smells faintly of plasma" icon_state = "petehat" + loose = 0 /obj/item/clothing/head/collectable/slime name = "collectable slime cap!" desc = "It just latches right in place!" icon_state = "slime" + loose = 0 /obj/item/clothing/head/collectable/xenom name = "collectable xenomorph helmet!" desc = "Hiss hiss hiss!" icon_state = "xenom" + loose = 35 // Zoinks! It was old man McGrief all along! /obj/item/clothing/head/collectable/chef name = "collectable chef's hat" desc = "A rare Chef's Hat meant for hat collectors!" icon_state = "chef" item_state = "chef" + loose = 45 // Mama mia! /obj/item/clothing/head/collectable/paper name = "collectable paper hat" desc = "What looks like an ordinary paper hat, is actually a rare and valuable collector's edition paper hat. Keep away from water, fire and Librarians." icon_state = "paper" + loose = 99 // fucking paper /obj/item/clothing/head/collectable/tophat name = "collectable top hat" desc = "A top hat worn by only the most prestigious hat collectors." icon_state = "tophat" item_state = "that" + loose = 70 // I say! /obj/item/clothing/head/collectable/captain name = "collectable captain's hat" desc = "A Collectable Hat that'll make you look just like a real comdom!" icon_state = "captain" item_state = "caphat" + loose = 55 /obj/item/clothing/head/collectable/police name = "collectable police officer's hat" @@ -58,61 +65,72 @@ desc = "A Collectable Welding Helmet. Now with 80% less lead! Not for actual welding. Any welding done while wearing this Helmet is done so at the owner's own risk!" icon_state = "welding" item_state = "welding" + loose = 0 /obj/item/clothing/head/collectable/slime name = "collectable slime hat" desc = "Just like a real Brain Slug!" icon_state = "headslime" item_state = "headslime" + loose = 5 /obj/item/clothing/head/collectable/flatcap name = "collectable flat cap" desc = "A Collectible farmer's Flat Cap!" icon_state = "flat_cap" item_state = "detective" + loose = 5 /obj/item/clothing/head/collectable/pirate name = "collectable pirate hat" desc = "You'd make a great Dread Syndie Roberts!" icon_state = "pirate" item_state = "pirate" + loose = 55 // yar /obj/item/clothing/head/collectable/kitty name = "collectable kitty ears" desc = "The fur feels.....a bit too realistic." icon_state = "kitty" item_state = "kitty" + loose = 2 // meow /obj/item/clothing/head/collectable/rabbitears name = "collectable rabbit ears" desc = "Not as lucky as the feet!" icon_state = "bunny" item_state = "bunny" + loose = 4 // little bunny foo foo /obj/item/clothing/head/collectable/wizard name = "collectable wizard's hat" desc = "NOTE:Any magical powers gained from wearing this hat are purely coincidental." icon_state = "wizard" + loose = 4 /obj/item/clothing/head/collectable/hardhat name = "collectable hard hat" desc = "WARNING! Offers no real protection, or luminosity, but it is damn fancy!" icon_state = "hardhat0_yellow" item_state = "hardhat0_yellow" + loose = 9 /obj/item/clothing/head/collectable/HoS name = "collectable HoS hat" desc = "Now you can beat prisoners, set silly sentences and arrest for no reason too!" icon_state = "hoscap" + loose = 29 /obj/item/clothing/head/collectable/thunderdome name = "collectable Thunderdome helmet" desc = "Go Red! I mean Green! I mean Red! No Green!" icon_state = "thunderdome" item_state = "thunderdome" + loose = 6 /obj/item/clothing/head/collectable/swat name = "collectable SWAT helmet" desc = "Now you can be in the Deathsquad too!" icon_state = "swat" - item_state = "swat" \ No newline at end of file + item_state = "swat" + loose = 3 diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 4574b905594..bcc5256e84a 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -1,3 +1,4 @@ + /obj/item/clothing/head/hardhat name = "hard hat" desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight." @@ -11,6 +12,7 @@ flags_inv = 0 icon_action_button = "action_hardhat" siemens_coefficient = 0.9 + loose = 4 attack_self(mob/user) if(!isturf(user.loc)) @@ -62,4 +64,3 @@ icon_state = "hardhat0_dblue" item_state = "hardhat0_dblue" _color = "dblue" - diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 7ed648c6bc2..b209b03fcde 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -11,6 +11,22 @@ heat_protection = HEAD max_heat_protection_temperature = HELMET_MAX_HEAT_PROTECITON_TEMPERATURE siemens_coefficient = 0.7 + loose = 4 // generally well seated + +/obj/item/clothing/head/helmet/HoS + name = "head of security hat" + desc = "The hat of the Head of Security. For showing the officers who's in charge." + icon_state = "hoscap" + flags = HEADCOVERSEYES + armor = list(melee = 80, bullet = 60, laser = 50,energy = 10, bomb = 25, bio = 10, rad = 0) + flags_inv = 0 + flags_inv = HIDEEARS + +/obj/item/clothing/head/helmet/HoS/dermal + name = "Dermal Armour Patch" + desc = "You're not quite sure how you manage to take it on and off, but it implants nicely in your head." + icon_state = "dermal" + item_state = "dermal" /obj/item/clothing/head/helmet/roman name = "roman helmet" @@ -30,6 +46,7 @@ desc = "It's a special helmet issued to the Warden of a securiy force. Protects the head from impacts." icon_state = "policehelm" flags_inv = 0 + loose = 12 // no really, you are here beacuse of your exemplary behavior in past jobs. truly. /obj/item/clothing/head/helmet/customs name = "customs officer's hat" @@ -78,4 +95,5 @@ flags = FPRINT|TABLEPASS|HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR item_state = "gladiator" flags_inv = HIDEMASK|HIDEEARS|HIDEEYES - siemens_coefficient = 1 \ No newline at end of file + siemens_coefficient = 1 + loose = 0 // full head, won't fall off diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index e7d15b27f54..3629a1600e2 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -8,6 +8,7 @@ desc = "The commander in chef's head wear." flags = FPRINT | TABLEPASS siemens_coefficient = 0.9 + loose = 35 // why-a do people always push-a me over //Captain: This probably shouldn't be space-worthy /obj/item/clothing/head/caphat @@ -17,6 +18,7 @@ flags = FPRINT|TABLEPASS item_state = "caphat" siemens_coefficient = 0.9 + loose = 43 // not the answer //Captain: This probably shouldn't be space-worthy /obj/item/clothing/head/helmet/cap @@ -28,6 +30,7 @@ cold_protection = HEAD min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECITON_TEMPERATURE siemens_coefficient = 0.9 + loose = 17 //Chaplain /obj/item/clothing/head/chaplain_hood @@ -36,6 +39,7 @@ icon_state = "chaplain_hood" flags = FPRINT|TABLEPASS|HEADCOVERSEYES|BLOCKHAIR siemens_coefficient = 0.9 + loose = 2 //Chaplain /obj/item/clothing/head/nun_hood @@ -44,6 +48,14 @@ icon_state = "nun_hood" flags = FPRINT|TABLEPASS|HEADCOVERSEYES|BLOCKHAIR siemens_coefficient = 0.9 + loose = 2 + +/obj/item/clothing/head/det_hat + name = "hat" + desc = "Someone who wears this will look very smart." + icon_state = "detective" + allowed = list(/obj/item/weapon/reagent_containers/food/snacks/candy_corn, /obj/item/weapon/pen) + armor = list(melee = 50, bullet = 5, laser = 25,energy = 10, bomb = 0, bio = 0, rad = 0) //Mime /obj/item/clothing/head/beret @@ -52,6 +64,7 @@ icon_state = "beret" flags = FPRINT | TABLEPASS siemens_coefficient = 0.9 + loose = 16 //Security /obj/item/clothing/head/beret/sec @@ -59,6 +72,7 @@ desc = "A beret with the security insignia emblazoned on it. For officers that are more inclined towards style than safety." icon_state = "beret_badge" flags = FPRINT | TABLEPASS + /obj/item/clothing/head/beret/eng name = "engineering beret" desc = "A beret with the engineering insignia emblazoned on it. For engineers that are more inclined towards style than safety." @@ -71,6 +85,7 @@ desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs." icon_state = "surgcap_blue" flags = FPRINT | TABLEPASS | BLOCKHEADHAIR + loose = 13 /obj/item/clothing/head/surgery/purple desc = "A cap surgeons wear during operations. Keeps their hair from tickling your internal organs. This one is deep purple." diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 84c78567bf9..cb145f4c55b 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -18,12 +18,15 @@ /obj/item/clothing/head/hairflower/purple icon_state = "hairflowerp" item_state = "hairflowerp" + item_state = "that" + loose = 0 // centcom /obj/item/clothing/head/powdered_wig name = "powdered wig" desc = "A powdered wig." icon_state = "pwig" item_state = "pwig" + loose = 90 // fucking whigs /obj/item/clothing/head/that name = "top-hat" @@ -32,18 +35,21 @@ item_state = "that" flags = FPRINT|TABLEPASS siemens_coefficient = 0.9 + loose = 70 /obj/item/clothing/head/redcoat name = "redcoat's hat" icon_state = "redcoat" desc = "'I guess it's a redhead.'" flags = FPRINT | TABLEPASS + loose = 45 /obj/item/clothing/head/mailman name = "mailman's hat" icon_state = "mailman" desc = "'Right-on-time' mail service head wear." flags = FPRINT | TABLEPASS + loose = 65 /obj/item/clothing/head/plaguedoctorhat name = "plague doctor's hat" @@ -52,12 +58,14 @@ flags = FPRINT | TABLEPASS permeability_coefficient = 0.01 siemens_coefficient = 0.9 + loose = 30 /obj/item/clothing/head/hasturhood name = "hastur's hood" desc = "It's unspeakably stylish" icon_state = "hasturhood" flags = FPRINT|TABLEPASS|HEADCOVERSEYES|BLOCKHAIR + loose = 1 /obj/item/clothing/head/nursehat name = "nurse's hat" @@ -65,6 +73,7 @@ icon_state = "nursehat" flags = FPRINT|TABLEPASS siemens_coefficient = 0.9 + loose = 80 // allowing for awkward come-ons when he/she drops his/her hat and you get it for him/her. /obj/item/clothing/head/syndicatefake name = "red space-helmet replica" @@ -74,6 +83,7 @@ flags = FPRINT | TABLEPASS | BLOCKHAIR flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE siemens_coefficient = 2.0 + loose = 15 // not a very good replica /obj/item/clothing/head/cueball name = "cueball helmet" @@ -82,6 +92,7 @@ flags = FPRINT|TABLEPASS|HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR item_state="cueball" flags_inv = 0 + loose = 0 /obj/item/clothing/head/that name = "sturdy top-hat" @@ -90,6 +101,7 @@ item_state = "that" flags = FPRINT|TABLEPASS flags_inv = 0 + loose = 70 /obj/item/clothing/head/greenbandana @@ -99,6 +111,7 @@ item_state = "greenbandana" flags = FPRINT|TABLEPASS flags_inv = 0 + loose = 1 /obj/item/clothing/head/cardborg name = "cardborg helmet" @@ -107,6 +120,7 @@ item_state = "cardborg_h" flags = FPRINT | TABLEPASS | HEADCOVERSEYES | HEADCOVERSMOUTH flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE + loose = 20 /obj/item/clothing/head/justice name = "justice hat" @@ -114,6 +128,7 @@ icon_state = "justicered" item_state = "justicered" flags = FPRINT|TABLEPASS|HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR + loose = 0 /obj/item/clothing/head/justice/blue icon_state = "justiceblue" @@ -136,6 +151,7 @@ desc = "Wearing these makes you looks useless, and only good for your sex appeal." icon_state = "bunny" flags = FPRINT | TABLEPASS + loose = 4 /obj/item/clothing/head/flatcap name = "flat cap" @@ -143,24 +159,28 @@ icon_state = "flat_cap" item_state = "detective" siemens_coefficient = 0.9 + loose = 1 /obj/item/clothing/head/pirate name = "pirate hat" desc = "Yarr." icon_state = "pirate" item_state = "pirate" + loose = 18 /obj/item/clothing/head/hgpiratecap name = "pirate hat" desc = "Yarr." icon_state = "hgpiratecap" item_state = "hgpiratecap" + loose = 36 /obj/item/clothing/head/bandana name = "pirate bandana" desc = "Yarr." icon_state = "bandana" item_state = "bandana" + loose = 0 /obj/item/clothing/head/bowler name = "bowler-hat" @@ -222,6 +242,7 @@ item_state = "witch" flags = FPRINT | TABLEPASS | BLOCKHAIR siemens_coefficient = 2.0 + loose = 1 /obj/item/clothing/head/chicken name = "chicken suit head" @@ -246,6 +267,7 @@ item_state = "bearpelt" flags = FPRINT | TABLEPASS | BLOCKHAIR siemens_coefficient = 2.0 + loose = 0 // grrrr /obj/item/clothing/head/xenos name = "xenos helmet" @@ -275,4 +297,5 @@ /obj/item/clothing/head/fedora/brownfedora name = "brown fedora" - icon_state = "bfedora" \ No newline at end of file + icon_state = "bfedora" + loose = 35 \ No newline at end of file diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 37e1aed2aa4..1b7ce655771 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -24,6 +24,7 @@ flags_inv = (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE) icon_action_button = "action_welding" siemens_coefficient = 0.9 + loose = 4 /obj/item/clothing/head/welding/attack_self() toggle() @@ -62,6 +63,7 @@ var/status = 0 var/fire_resist = T0C+1300 //this is the max temp it can stand before you start to cook. although it might not burn away, you take damage var/processing = 0 //I dont think this is used anywhere. + loose = 60 /obj/item/clothing/head/cakehat/process() if(!onfire) @@ -101,6 +103,7 @@ icon_state = "ushankadown" item_state = "ushankadown" flags_inv = HIDEEARS + loose = 1 // too warm, your head doesn't want to leave /obj/item/clothing/head/ushanka/attack_self(mob/user as mob) if(src.icon_state == "ushankadown") @@ -127,6 +130,17 @@ action_button_name = "Toggle Pumpkin Light" armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) brightness_on = 2 //luminosity when on + loose = 80 + +/* + * Kitty ears + */ +/obj/item/clothing/head/kitty + name = "kitty ears" + desc = "A pair of kitty ears. Meow!" + icon_state = "kitty" + loose = 4 // meow + /obj/item/clothing/head/hardhat/reindeer name = "novelty reindeer hat" @@ -140,6 +154,7 @@ armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) brightness_on = 1 //luminosity when on + /* * Kitty ears */ @@ -162,4 +177,6 @@ var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner") var/icon/earbit2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner2") mob.Blend(earbit, ICON_OVERLAY) - mob2.Blend(earbit2, ICON_OVERLAY) \ No newline at end of file + mob2.Blend(earbit2, ICON_OVERLAY) + + loose = 33 diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index 436afc72c6b..9a0a753bcd6 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -118,6 +118,22 @@ item_state = "ce_hardsuit" flags = FPRINT | TABLEPASS | STOPSPRESSUREDMAGE | ONESIZEFITSALL + +//Singuloth armor +/obj/item/clothing/head/helmet/space/rig/singuloth + name = "singuloth knight's helmet" + desc = "This is an adamantium helmet from the chapter of the Singuloth Knights. It shines with a holy aura." + icon_state = "rig0-singuloth" + item_state = "singuloth_helm" + _color = "singuloth" + +/obj/item/clothing/suit/space/rig/singuloth + icon_state = "rig-singuloth" + name = "singuloth knight's armor" + desc = "This is a ceremonial armor from the chapter of the Singuloth Knights. It's made of pure forged adamantium." + item_state = "singuloth_hardsuit" + flags = FPRINT | TABLEPASS | STOPSPRESSUREDMAGE + //Mining rig /obj/item/clothing/head/helmet/space/rig/mining name = "mining hardsuit helmet" diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm index 1ff51b4f42d..56513a0e85c 100644 --- a/code/modules/clothing/suits/bio.dm +++ b/code/modules/clothing/suits/bio.dm @@ -8,6 +8,7 @@ armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES siemens_coefficient = 0.9 + loose = 7 /obj/item/clothing/suit/bio_suit name = "bio suit" diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm index 27dbe179464..7c6772eb1e9 100644 --- a/code/modules/clothing/suits/utility.dm +++ b/code/modules/clothing/suits/utility.dm @@ -51,6 +51,7 @@ armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 100, bio = 0, rad = 0) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES siemens_coefficient = 0 + loose = 5 /obj/item/clothing/suit/bomb_suit @@ -90,7 +91,7 @@ desc = "A hood with radiation protective properties. Label: Made with lead, do not eat insulation" flags = FPRINT|TABLEPASS|HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100) - + loose = 8 /obj/item/clothing/suit/radiation name = "Radiation suit" diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index 277b42d364d..ffaa03f92fc 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -2,6 +2,7 @@ name = "wizard hat" desc = "Strange-looking hat-wear that most certainly belongs to a real magic user." icon_state = "wizard" + loose = 0 // magic //Not given any special protective value since the magic robes are full-body protection --NEO siemens_coefficient = 0.8 diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index 49afd01e78b..14afce1baad 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -32,11 +32,12 @@ armor = list(melee = 10, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) // Standard Security jumpsuit stats siemens_coefficient = 0. -/obj/item/clothing/under/fluff/BlackSchoolGirl // Black schoolgirl uniform +/obj/item/clothing/under/fluff/blackschoolGirl // Black schoolgirl uniform name = "Black Schoolgirl Uniform" desc = "A Japanese style school uniform for girls" icon= 'icons/obj/clothing/uniforms.dmi' icon_state = "schoolgirl_black" + _color = "schoolgirl_black" item_state = "schoolgirl_black" has_sensor = 1 // Just to make sure it has a sensor armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) // Standar Jumpsuit stats diff --git a/code/modules/events/tgevents/holiday/xmas.dm b/code/modules/events/tgevents/holiday/xmas.dm index 0ae568be1ea..505efd46793 100644 --- a/code/modules/events/tgevents/holiday/xmas.dm +++ b/code/modules/events/tgevents/holiday/xmas.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD:code/modules/events/tgevents/holiday/xmas.dm /datum/event/treevenge/start() for(var/obj/structure/flora/tree/pine/xmas in world) var/mob/living/simple_animal/hostile/tree/evil_tree = new /mob/living/simple_animal/hostile/tree(xmas.loc) @@ -66,4 +67,87 @@ desc = "A crappy paper hat that you are REQUIRED to wear." flags_inv = 0 flags = FPRINT|TABLEPASS - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) \ No newline at end of file + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) +======= +/datum/round_event_control/treevenge + name = "Treevenge" + holidayID = "Xmas" + typepath = /datum/round_event/treevenge + max_occurrences = 1 + weight = 20 + +/datum/round_event/treevenge/start() + for(var/obj/structure/flora/tree/pine/xmas in world) + var/mob/living/simple_animal/hostile/tree/evil_tree = new /mob/living/simple_animal/hostile/tree(xmas.loc) + evil_tree.icon_state = xmas.icon_state + evil_tree.icon_living = evil_tree.icon_state + evil_tree.icon_dead = evil_tree.icon_state + evil_tree.icon_gib = evil_tree.icon_state + del(xmas) + +//this is an example of a possible round-start event +/datum/round_event_control/presents + name = "Presents under Trees" + holidayID = "Xmas" + typepath = /datum/round_event/presents + weight = -1 //forces it to be called, regardless of weight + max_occurrences = 1 + earliest_start = 0 + +/datum/round_event/presents/start() + for(var/obj/structure/flora/tree/pine/xmas in world) + if(xmas.z != 1) continue + for(var/turf/simulated/floor/T in orange(1,xmas)) + for(var/i=1,i<=rand(1,5),i++) + new /obj/item/weapon/a_gift(T) + for(var/mob/living/simple_animal/corgi/Ian/Ian in mob_list) + Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian)) + for(var/obj/machinery/computer/security/telescreen/entertainment/Monitor in machines) + Monitor.icon_state = "entertainment_xmas" + +/datum/round_event/presents/announce() + command_alert("Ho Ho Ho, Merry Xmas!", "Unknown Transmission") + + +/obj/item/weapon/toy/xmas_cracker + name = "xmas cracker" + icon = 'icons/obj/christmas.dmi' + icon_state = "cracker" + desc = "Directions for use: Requires two people, one to pull each end." + var/cracked = 0 + +/obj/item/weapon/toy/xmas_cracker/attack(mob/target, mob/user) + if( !cracked && istype(target,/mob/living/carbon/human) && (target.stat == CONSCIOUS) && !target.get_active_hand() ) + target.visible_message("[user] and [target] pop \an [src]! *pop*", "You pull \an [src] with [target]! *pop*", "You hear a *pop*.") + var/obj/item/weapon/paper/Joke = new /obj/item/weapon/paper(user.loc) + Joke.name = "[pick("awful","terrible","unfunny")] joke" + Joke.info = pick("What did one snowman say to the other?\n\n'Is it me or can you smell carrots?'", + "Why couldn't the snowman get laid?\n\nHe was frigid!", + "Where are santa's helpers educated?\n\nNowhere, they're ELF-taught.", + "What happened to the man who stole advent calanders?\n\nHe got 25 days.", + "What does Santa get when he gets stuck in a chimney?\n\nClaus-trophobia.", + "Where do you find chili beans?\n\nThe north pole.", + "What do you get from eating tree decorations?\n\nTinsilitis!", + "What do snowmen wear on their heads?\n\nIce caps!", + "Why is Christmas just like life on ss13?\n\nYou do all the work and the fat guy gets all the credit.", + "Why doesn’t Santa have any children?\n\nBecause he only comes down the chimney.") + new /obj/item/clothing/head/festive(target.loc) + user.update_icons() + cracked = 1 + icon_state = "cracker1" + var/obj/item/weapon/toy/xmas_cracker/other_half = new /obj/item/weapon/toy/xmas_cracker(target) + other_half.cracked = 1 + other_half.icon_state = "cracker2" + target.put_in_active_hand(other_half) + playsound(user, 'sound/effects/snap.ogg', 50, 1) + return 1 + return ..() + +/obj/item/clothing/head/festive + name = "festive paper hat" + icon_state = "xmashat" + desc = "A crappy paper hat that you are REQUIRED to wear." + flags_inv = 0 + armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + loose = 100 +>>>>>>> cdc0238... Gives mobs a "fall" proc for the transition between falling and standing. This is not for the rotation code, which occurs on both falling and rising.:code/modules/events/holiday/xmas.dm diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm index bb1db7a86d3..44383b0412d 100644 --- a/code/modules/mining/money_bag.dm +++ b/code/modules/mining/money_bag.dm @@ -54,6 +54,27 @@ dat += text("Bananium coins: [amt_clown] Remove one
") if (amt_adamantine) dat += text("Adamantine coins: [amt_adamantine] Remove one
") +/* + var/credits=0 + var/list/ore=list() + for(var/oredata in typesof(/datum/material) - /datum/material) + var/datum/material/ore_datum = new oredata + ore[ore_datum.id]=ore_datum + + for (var/obj/item/weapon/coin/C in contents) + if (istype(C,/obj/item/weapon/coin)) + var/datum/material/ore_info=ore[C.material] + ore_info.stored++ + ore[C.material]=ore_info + credits += C.credits + + var/dat = "The contents of the moneybag reveal...Total haul: $[credits]" +*/ user << browse("[dat]", "window=moneybag") /obj/item/weapon/moneybag/attackby(obj/item/weapon/W as obj, mob/user as mob) diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index d15a0d16091..22024b54aad 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -81,6 +81,8 @@ throwforce = 0.0 w_class = 1.0 var/string_attached + var/material="iron" // Ore ID, used with coinbags. + var/credits = 0 // How many credits is this coin worth? /obj/item/weapon/coin/New() pixel_x = rand(0,16)-8 @@ -89,30 +91,37 @@ /obj/item/weapon/coin/gold name = "Gold coin" icon_state = "coin_gold" + credits = 10 /obj/item/weapon/coin/silver name = "Silver coin" icon_state = "coin_silver" + credits = 5 /obj/item/weapon/coin/diamond name = "Diamond coin" icon_state = "coin_diamond" + credits = 25 /obj/item/weapon/coin/iron name = "Iron coin" icon_state = "coin_iron" + credits = 1 /obj/item/weapon/coin/plasma name = "Solid plasma coin" icon_state = "coin_plasma" + credits = 5 /obj/item/weapon/coin/uranium name = "Uranium coin" icon_state = "coin_uranium" + credits = 25 /obj/item/weapon/coin/clown name = "Bananaium coin" icon_state = "coin_clown" + credits = 1000 /obj/item/weapon/coin/adamantine name = "Adamantine coin" diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 702d6c89bf2..4dae5dd0b5b 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -196,6 +196,15 @@ log_attack("[M.name] ([M.ckey]) pushed [src.name] ([src.ckey])") return + if(randn <= 45 && !lying) + if(head) + var/obj/item/clothing/head/H = head + if(!istype(H) || prob(H.loose)) + drop_from_inventory(H) + if(prob(60)) + step_away(H,M) + visible_message("[M] has knocked [src]'s [H] off!", + "[M] knocked \the [H] clean off your head!") var/talked = 0 // BubbleWrap diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index d9adfe9aa0e..e887ade027c 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -64,6 +64,7 @@ if(M_HULK in mutations) return ..() + /mob/living/carbon/human/adjustCloneLoss(var/amount) ..() var/heal_prob = max(0, 80 - getCloneLoss()) @@ -92,6 +93,7 @@ if (O.status & ORGAN_MUTATED) O.unmutate() src << "Your [O.display_name] is shaped normally again." + //////////////////////////////////////////// //Returns a list of damaged organs @@ -259,4 +261,21 @@ organ.implants += S visible_message("The projectile sticks in the wound!") S.add_blood(src) - return 1 \ No newline at end of file + return 1 + +// incredibly important stuff follows +/mob/living/carbon/human/fall(var/forced) + ..() + if(forced) + playsound(loc, "bodyfall", 50, 1, -1) + if(head) + var/multiplier = 1 + if(stat || (status_flags & FAKEDEATH)) + multiplier = 2 + var/obj/item/clothing/head/H = head + if(!istype(H) || prob(H.loose * multiplier)) + drop_from_inventory(H) + if(prob(60)) + step_rand(H) + if(!stat) + src << "Your [H] fell off!" diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 5e5f6a06ef3..12aa97f50fb 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -61,6 +61,7 @@ // We're a monkey dna.SetSEState(MONKEYBLOCK, 1) + dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) // Fix gender dna.SetUIState(DNA_UI_GENDER, gender != MALE, 1) diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 0dc6be11b08..927865f65b1 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -1,7 +1,7 @@ #define SAY_MINIMUM_PRESSURE 10 var/list/department_radio_keys = list( - ":r" = "right hand", "#r" = "right hand", ".r" = "right hand", - ":l" = "left hand", "#l" = "left hand", ".l" = "left hand", + ":r" = "right ear", "#r" = "right ear", ".r" = "right ear", "!r" = "fake right ear", + ":l" = "left ear", "#l" = "left ear", ".l" = "left ear", "!l" = "fake left ear", ":i" = "intercom", "#i" = "intercom", ".i" = "intercom", ":h" = "department", "#h" = "department", ".h" = "department", ":c" = "Command", "#c" = "Command", ".c" = "Command", @@ -16,8 +16,9 @@ var/list/department_radio_keys = list( ":u" = "Supply", "#u" = "Supply", ".u" = "Supply", ":g" = "changeling", "#g" = "changeling", ".g" = "changeling", - ":R" = "right hand", "#R" = "right hand", ".R" = "right hand", - ":L" = "left hand", "#L" = "left hand", ".L" = "left hand", + + ":R" = "right ear", "#R" = "right ear", ".R" = "right ear", "!R" = "fake right ear", + ":L" = "left ear", "#L" = "left ear", ".L" = "left ear", "!L" = "fake left ear", ":I" = "intercom", "#I" = "intercom", ".I" = "intercom", ":H" = "department", "#H" = "department", ".H" = "department", ":C" = "Command", "#C" = "Command", ".C" = "Command", @@ -188,116 +189,126 @@ var/list/department_radio_keys = list( if (stuttering) message = stutter(message) + /////////////////////////////////////////////////////////// + // VIDEO KILLED THE RADIO STAR V2.0 + // + // EXPERIMENTAL CODE BY YOUR PALS AT /vg/ + /////////////////////////////////////////////////////////// + var/list/obj/item/used_radios = new + + // Actually speaking on the radio? var/is_speaking_radio = 0 - switch (message_mode) - if ("headset") - if (src:l_ear && istype(src:l_ear,/obj/item/device/radio)) - src:l_ear.talk_into(src, message) - used_radios += src:l_ear - is_speaking_radio = 1 - else if (src:r_ear) - src:r_ear.talk_into(src, message) - used_radios += src:r_ear - is_speaking_radio = 1 + // Devices selected + var/list/devices=list() - message_range = 1 - italics = 1 + // Select all always_talk devices + // Carbon lifeforms + if(istype(src, /mob/living/carbon)) + for(var/obj/item/device/radio/R in contents) + if(R.always_talk) + devices += R - if ("right ear") - if (src:r_ear) - src:r_ear.talk_into(src, message) - used_radios += src:r_ear - is_speaking_radio = 1 - - message_range = 1 - italics = 1 - - if ("left ear") - if (src:l_ear) - src:l_ear.talk_into(src, message) - used_radios += src:l_ear - is_speaking_radio = 1 - - message_range = 1 - italics = 1 - - if ("intercom") - for (var/obj/item/device/radio/intercom/I in view(1, null)) - I.talk_into(src, message) - used_radios += I - is_speaking_radio = 1 - - message_range = 1 - italics = 1 - - //I see no reason to restrict such way of whispering - if ("whisper") - whisper(message) - return - - if ("binary") - if(robot_talk_understand || binarycheck()) - //message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) //seems redundant - robot_talk(message) - return - - if ("alientalk") - if(alien_talk_understand || hivecheck()) - //message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) //seems redundant - alien_talk(message) - return - - if ("department") - if(istype(src, /mob/living/carbon)) - if (src:l_ear && istype(src:l_ear,/obj/item/device/radio)) - src:l_ear.talk_into(src, message, message_mode) - used_radios += src:l_ear - is_speaking_radio = 1 - if (src:r_ear) - src:r_ear.talk_into(src, message, message_mode) - used_radios += src:r_ear - is_speaking_radio = 1 - else if(istype(src, /mob/living/silicon/robot)) - if (src:radio) - src:radio.talk_into(src, message, message_mode) - used_radios += src:radio - message_range = 1 - italics = 1 - - if ("pAI") - if (src:radio) - src:radio.talk_into(src, message) - used_radios += src:radio - message_range = 1 - italics = 1 - - if("changeling") - if(mind && mind.changeling) - for(var/mob/Changeling in mob_list) - if((Changeling.mind && Changeling.mind.changeling) || istype(Changeling, /mob/dead/observer)) - Changeling << "[mind.changeling.changelingID]: [message]" - return -////SPECIAL HEADSETS START - else - //world << "SPECIAL HEADSETS" - if (message_mode in radiochannels) - if(isrobot(src))//Seperates robots to prevent runtimes from the ear stuff - var/mob/living/silicon/robot/R = src - if(R.radio)//Sanityyyy - R.radio.talk_into(src, message, message_mode) - used_radios += R.radio - else - if (src:l_ear && istype(src:l_ear,/obj/item/device/radio)) - src:l_ear.talk_into(src, message, message_mode) - used_radios += src:l_ear - else if (src:r_ear) - src:r_ear.talk_into(src, message, message_mode) - used_radios += src:r_ear + //src << "Speaking on [message_mode]: [message]" + if(message_mode) + switch (message_mode) + if ("right ear") + if(iscarbon(src)) + var/mob/living/carbon/C=src + if(C:r_ear) devices += C:r_ear + message_mode="headset" message_range = 1 italics = 1 -/////SPECIAL HEADSETS END + + if ("left ear") + if(iscarbon(src)) + var/mob/living/carbon/C=src + if(C:l_ear) devices += C:l_ear + message_mode="headset" + message_range = 1 + italics = 1 + + // Select a headset and speak into it without actually sending a message + if ("fake") + if(iscarbon(src)) + var/mob/living/carbon/C=src + if(C:l_ear) used_radios += C:l_ear + if(C:r_ear) used_radios += C:r_ear + message_range = 1 + italics = 1 + if ("fake left ear") + if(iscarbon(src)) + var/mob/living/carbon/C=src + if(C:l_ear) used_radios += C:l_ear + message_range = 1 + italics = 1 + if ("fake right ear") + if(iscarbon(src)) + var/mob/living/carbon/C=src + if(C:r_ear) used_radios += C:r_ear + message_range = 1 + italics = 1 + + if ("intercom") + for (var/obj/item/device/radio/intercom/I in view(1, null)) + devices += I + message_mode=null + message_range = 1 + italics = 1 + + //I see no reason to restrict such way of whispering + if ("whisper") + whisper(message) + return + + if ("binary") + if(robot_talk_understand || binarycheck()) + //message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) //seems redundant + robot_talk(message) + return + + if ("alientalk") + if(alien_talk_understand || hivecheck()) + //message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) //seems redundant + alien_talk(message) + return + + if ("pAI") + message_range = 1 + italics = 1 + + + if("changeling") + if(mind && mind.changeling) + log_say("[key_name(src)] ([mind.changeling.changelingID]): [message]") + for(var/mob/Changeling in mob_list) + if(istype(Changeling, /mob/living/silicon)) continue //WHY IS THIS NEEDED? + if((Changeling.mind && Changeling.mind.changeling) || istype(Changeling, /mob/dead/observer)) + Changeling << "[mind.changeling.changelingID]: [message]" + else if(istype(Changeling,/mob/dead/observer) && (Changeling.client && Changeling.client.prefs.toggles & CHAT_GHOSTEARS)) + Changeling << "[mind.changeling.changelingID] (: (Follow) [message]" + return + else // headset, department channels. + if(iscarbon(src)) + var/mob/living/carbon/C=src + if(C:l_ear) devices += C:l_ear + if(C:r_ear) devices += C:r_ear + if(issilicon(src)) + var/mob/living/silicon/Ro=src + if(Ro:radio) devices += Ro:radio + message_range = 1 + italics = 1 + if(devices.len>0) + for(var/obj/item/device/radio/R in devices) + if(istype(R)) + R.talk_into(src, message, message_mode) + used_radios += R + is_speaking_radio = 1 + + ///////////////////////////////////////////////////////////////// + // + ///////////////////////////////////////////////////////////////// var/datum/gas_mixture/environment = loc.return_air() if(environment) @@ -344,21 +355,6 @@ var/list/department_radio_keys = list( O.hear_talk(src, message) -/* Commented out as replaced by code above from BS12 - for (var/obj/O in ((V | contents)-used_radios)) //radio in pocket could work, radio in backpack wouldn't --rastaf0 - spawn (0) - if (O) - O.hear_talk(src, message) -*/ - -/* if(isbrain(src))//For brains to properly talk if they are in an MMI..or in a brain. Could be extended to other mobs I guess. - for(var/obj/O in loc)//Kinda ugly but whatever. - if(O) - spawn(0) - O.hear_talk(src, message) -*/ - - var/list/heard_a = list() // understood us var/list/heard_b = list() // didn't understand us diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index ef6210c6c79..fe4416c5271 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -305,6 +305,7 @@ icon = 'icons/mob/custom-synthetic.dmi' /mob/living/silicon/robot/verb/Namepick() + set category = "Robot Commands" if(custom_name) return 0 diff --git a/code/modules/mob/living/simple_animal/borer.dm b/code/modules/mob/living/simple_animal/borer.dm index 51dfe1ac108..5411500c15c 100644 --- a/code/modules/mob/living/simple_animal/borer.dm +++ b/code/modules/mob/living/simple_animal/borer.dm @@ -294,9 +294,6 @@ src << "You begin disconnecting from [host]'s synapses and prodding at their internal ear canal." - if(!host.stat) - host << "An odd, uncomfortable pressure begins to build inside your skull, behind your ear..." - spawn(200) if(!host || !src) return @@ -306,8 +303,6 @@ return src << "You wiggle out of [host]'s ear and plop to the ground." - if(!host.stat) - host << "Something slimy wiggles out of your ear and plops to the ground!" detatch() @@ -376,7 +371,7 @@ mob/living/simple_animal/borer/proc/detatch() src << "You cannot get through that host's protective gear." return */ - M << "Something slimy begins probing at the opening of your ear canal..." + src << "You slither up [M] and begin probing at their ear canal..." if(!do_after(src,50)) @@ -395,11 +390,7 @@ mob/living/simple_animal/borer/proc/detatch() if(M in view(1, src)) src << "You wiggle into [M]'s ear." - if(!M.stat) - M << "Something disgusting and slimy wiggles into your ear!" - - src.perform_infestation(M) - + src.perform_infestation(M) return else src << "They are no longer in range!" @@ -511,4 +502,4 @@ mob/living/simple_animal/borer/proc/transfer_personality(var/client/candidate) src << text("\green You have stopped hiding.") for(var/mob/O in oviewers(src, null)) if ((O.client && !( O.blinded ))) - O << text("[] slowly peaks up from the ground...", src) \ No newline at end of file + O << text("[] slowly peaks up from the ground...", src) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index e53e13b6169..4739b872cbf 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -147,7 +147,7 @@ melee_damage_upper = 30 attacktext = "smashes their armoured gauntlet into" speed = 3 - wall_smash = 1 + environment_smash = 2 attack_sound = 'sound/weapons/punch3.ogg' status_flags = 0 construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall) @@ -243,7 +243,7 @@ melee_damage_upper = 5 attacktext = "rams" speed = 0 - wall_smash = 1 + environment_smash = 2 attack_sound = 'sound/weapons/punch2.ogg' construct_spells = list(/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser, /obj/effect/proc_holder/spell/aoe_turf/conjure/wall, @@ -271,7 +271,7 @@ melee_damage_upper = 50 attacktext = "brutally crushes" speed = 5 - wall_smash = 1 + environment_smash = 2 attack_sound = 'sound/weapons/punch4.ogg' var/energy = 0 var/max_energy = 1000 diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index fba59db37c8..564a248e6b8 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -29,7 +29,6 @@ max_n2 = 0 unsuitable_atoms_damage = 15 faction = "alien" - wall_smash = 1 status_flags = CANPUSH minbodytemp = 0 heat_damage_per_tick = 20 @@ -53,6 +52,8 @@ melee_damage_lower = 15 melee_damage_upper = 15 ranged = 1 + retreat_distance = 5 + minimum_distance = 5 projectiletype = /obj/item/projectile/neurotox projectilesound = 'sound/weapons/pierce.ogg' @@ -67,6 +68,8 @@ melee_damage_lower = 15 melee_damage_upper = 15 ranged = 1 + retreat_distance = 5 + minimum_distance = 5 move_to_delay = 3 projectiletype = /obj/item/projectile/neurotox projectilesound = 'sound/weapons/pierce.ogg' diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index 8a6c0ef14c5..e1d3af4d597 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -52,4 +52,13 @@ if(istype(L)) if(prob(15)) L.Weaken(3) - L.visible_message("\the [src] knocks down \the [L]!") \ No newline at end of file + L.visible_message("\the [src] knocks down \the [L]!") + + +/mob/living/simple_animal/hostile/carp/holocarp + icon_state = "holocarp" + icon_living = "holocarp" + +/mob/living/simple_animal/hostile/carp/holocarp/Die() + del(src) + return \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm index c7f0cd845ba..70602dc4b77 100644 --- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm +++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm @@ -32,10 +32,14 @@ name = "Hivebot" desc = "A smallish robot, this one is armed!" ranged = 1 + retreat_distance = 5 + minimum_distance = 5 /mob/living/simple_animal/hostile/hivebot/rapid ranged = 1 rapid = 1 + retreat_distance = 5 + minimum_distance = 5 /mob/living/simple_animal/hostile/hivebot/strong name = "Strong Hivebot" @@ -43,7 +47,6 @@ health = 80 ranged = 1 - /mob/living/simple_animal/hostile/hivebot/Die() ..() visible_message("[src] blows apart!") diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 7fa0463c5b3..d5aeb2dab37 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -1,8 +1,11 @@ /mob/living/simple_animal/hostile faction = "hostile" + mouse_opacity = 2 //This makes it easier to hit hostile mobs, you only need to click on their tile, and is set back to 1 when they die + stop_automated_movement_when_pulled = 0 + environment_smash = 1 //Set to 1 to break closets,tables,racks, etc; 2 for walls; 3 for rwalls var/stance = HOSTILE_STANCE_IDLE //Used to determine behavior - var/target - var/attack_same = 0 + var/atom/target + var/attack_same = 0 //Set us to 1 to allow us to attack our own faction, or 2, to only ever attack our own faction var/ranged = 0 var/rapid = 0 var/projectiletype @@ -10,65 +13,163 @@ var/casingtype var/move_to_delay = 2 //delay for the automated movement. var/list/friends = list() - var/vision_range = 10 - stop_automated_movement_when_pulled = 0 + var/vision_range = 9 //How big of an area to search for targets in, a vision of 9 attempts to find targets as soon as they walk into screen view -/mob/living/simple_animal/hostile/proc/FindTarget() + var/aggro_vision_range = 9 //If a mob is aggro, we search in this radius. Defaults to 9 to keep in line with original simple mob aggro radius + var/idle_vision_range = 9 //If a mob is just idling around, it's vision range is limited to this. Defaults to 9 to keep in line with original simple mob aggro radius + var/ranged_message = "fires" //Fluff text for ranged mobs + var/ranged_cooldown = 0 //What the starting cooldown is on ranged attacks + var/ranged_cooldown_cap = 3 //What ranged attacks, after being used are set to, to go back on cooldown, defaults to 3 life() ticks + var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat. + var/minimum_distance = 1 //Minimum approach distance, so ranged mobs chase targets down, but still keep their distance set in tiles to the target, set higher to make mobs keep distance + var/search_objects = 0 //If we want to consider objects when searching around, set this to 1. If you want to search for objects while also ignoring mobs until hurt, set it to 2. To completely ignore mobs, even when attacked, set it to 3 + var/list/wanted_objects = list() //A list of objects that will be checked against to attack, should we have search_objects enabled + var/stat_attack = 0 //Mobs with stat_attack to 1 will attempt to attack things that are unconscious, Mobs with stat_attack set to 2 will attempt to attack the dead. + var/stat_exclusive = 0 //Mobs with this set to 1 will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses + var/attack_faction = null //Put a faction string here to have a mob only ever attack a specific faction - var/atom/T = null - stop_automated_movement = 0 + +/mob/living/simple_animal/hostile/Life() + + . = ..() + if(!.) + walk(src, 0) + return 0 + if(client) + return 0 + if(!stat) + switch(stance) + if(HOSTILE_STANCE_IDLE) + var/new_target = FindTarget() + GiveTarget(new_target) + + if(HOSTILE_STANCE_ATTACK) + MoveToTarget() + DestroySurroundings() + + if(HOSTILE_STANCE_ATTACKING) + AttackTarget() + DestroySurroundings() + + if(ranged) + ranged_cooldown-- + +//////////////HOSTILE MOB TARGETTING AND AGGRESSION//////////// + + +/mob/living/simple_animal/hostile/proc/ListTargets()//Step 1, find out what we can see + var/list/L = list() + if(search_objects < 2) + var/list/Mobs = hearers(src, vision_range) + for(var/mob/living/G in Mobs) + L.Add(G) + L.Remove(src)//So we don't suicide because we listed ourselves as a target! + if(search_objects) + var/list/Objects = oview(vision_range, src) + for(var/obj/O in Objects) + L.Add(O) + else + for(var/obj/mecha/M in mechas_list) + if(get_dist(M, src) <= vision_range && can_see(src, M, vision_range)) + L += M + return L + +/mob/living/simple_animal/hostile/proc/FindTarget()//Step 2, filter down possible targets to things we actually care about + var/list/Targets = list() + var/Target for(var/atom/A in ListTargets()) - - var/atom/F = Found(A) - if(F) - T = F + if(Found(A))//Just in case people want to override targetting + var/list/FoundTarget = list() + FoundTarget.Add(A) + Targets = FoundTarget break + if(CanAttack(A))//Can we attack it? + Targets.Add(A) + continue + Target = PickTarget(Targets) + return Target //We now have a target - if(isliving(A)) - var/mob/living/L = A - if(istype(src, /mob/living/simple_animal/hostile/scarybat)) - if(src:owner == L) continue - if(L.faction == src.faction && !attack_same) - continue - else if(L in friends) - continue - else - if(!L.stat) - T = L - break +/mob/living/simple_animal/hostile/proc/Found(var/atom/A)//This is here as a potential override to pick a specific target if available + return - else if(istype(A, /obj/mecha)) // Our line of sight stuff was already done in ListTargets(). - var/obj/mecha/M = A - if (M.occupant) - T = M - break +/mob/living/simple_animal/hostile/proc/PickTarget(var/list/Targets)//Step 3, pick amongst the possible, attackable targets + if(target != null)//If we already have a target, but are told to pick again, calculate the lowest distance between all possible, and pick from the lowest distance targets + for(var/atom/A in Targets) + var/target_dist = get_dist(src, target) + var/possible_target_distance = get_dist(src, A) + if(target_dist < possible_target_distance) + Targets -= A + if(!Targets.len)//We didnt find nothin! + return + var/chosen_target = pick(Targets)//Pick the remaining targets (if any) at random + return chosen_target - return T +/mob/living/simple_animal/hostile/CanAttack(var/atom/the_target)//Can we actually attack a possible target? + if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it + return 0 + if(isobj(the_target) && search_objects) + if(the_target.type in wanted_objects) + return 1 + if(isliving(the_target) && search_objects < 2) + var/mob/living/L = the_target + if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive == 1) + return 0 + if(L.faction == src.faction && !attack_same || L.faction != src.faction && attack_same == 2 || L.faction != attack_faction && attack_faction) + return 0 + if(L in friends) + return 0 + return 1 + if(istype(the_target, /obj/mecha)) + var/obj/mecha/M = the_target + if(M.occupant)//Just so we don't attack empty mechs + return 1 + return 0 -/mob/living/simple_animal/hostile/proc/GiveTarget(var/new_target) +/mob/living/simple_animal/hostile/proc/GiveTarget(var/new_target)//Step 4, give us our selected target target = new_target - stance = HOSTILE_STANCE_ATTACK + if(target != null) + Aggro() + stance = HOSTILE_STANCE_ATTACK return -/mob/living/simple_animal/hostile/proc/Goto(var/target, var/delay) - walk_to(src, target, 1, delay) - -/mob/living/simple_animal/hostile/proc/Found(var/atom/A) - return - -/mob/living/simple_animal/hostile/proc/MoveToTarget() +/mob/living/simple_animal/hostile/proc/MoveToTarget()//Step 5, handle movement between us and our target stop_automated_movement = 1 if(!target || SA_attackable(target)) LoseTarget() if(target in ListTargets()) - if(ranged) - if(get_dist(src, target) <= 6) + var/TargetDistance = get_dist(src,target) + if(ranged)//We ranged? Shoot at em + if(TargetDistance >= 2 && ranged_cooldown <= 0)//But make sure they're a tile away at least, and our range attack is off cooldown OpenFire(target) + if(retreat_distance != null)//If we have a retreat distance, check if we need to run from our target + if(TargetDistance <= retreat_distance)//If target's closer than our retreat distance, run + walk_away(src,target,retreat_distance,move_to_delay) else - Goto(target, move_to_delay) + Goto(target,move_to_delay,minimum_distance)//Otherwise, get to our minimum distance so we chase them else - stance = HOSTILE_STANCE_ATTACKING - Goto(target, move_to_delay) + Goto(target,move_to_delay,minimum_distance) + if(isturf(loc) && target.Adjacent(src)) //If they're next to us, attack + AttackingTarget() + return + LostTarget() + +/mob/living/simple_animal/hostile/proc/Goto(var/target, var/delay, var/minimum_distance) + walk_to(src, target, minimum_distance, delay) + +/mob/living/simple_animal/hostile/adjustBruteLoss(var/damage) + ..(damage) + if(!stat && search_objects < 3)//Not unconscious, and we don't ignore mobs + if(search_objects)//Turn off item searching and ignore whatever item we were looking at, we're more concerned with fight or flight + search_objects = 0 + target = null + if(stance == HOSTILE_STANCE_IDLE)//If we took damage while idle, immediately attempt to find the source of it so we find a living target + Aggro() + var/new_target = FindTarget() + GiveTarget(new_target) + if(stance == HOSTILE_STANCE_ATTACK)//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one + if(target != null && prob(25)) + var/new_target = FindTarget() + GiveTarget(new_target) /mob/living/simple_animal/hostile/proc/AttackTarget() @@ -79,73 +180,42 @@ if(!(target in ListTargets())) LostTarget() return 0 - if(get_dist(src, target) <= 1) //Attacking + if(isturf(loc) && target.Adjacent(src)) AttackingTarget() return 1 /mob/living/simple_animal/hostile/proc/AttackingTarget() - if(isliving(target)) - var/mob/living/L = target - L.attack_animal(src) - return L - if(istype(target,/obj/mecha)) - var/obj/mecha/M = target - M.attack_animal(src) - return M + target.attack_animal(src) + +/mob/living/simple_animal/hostile/proc/Aggro() + vision_range = aggro_vision_range + +/mob/living/simple_animal/hostile/proc/LoseAggro() + stop_automated_movement = 0 + vision_range = idle_vision_range /mob/living/simple_animal/hostile/proc/LoseTarget() stance = HOSTILE_STANCE_IDLE target = null walk(src, 0) + LoseAggro() /mob/living/simple_animal/hostile/proc/LostTarget() stance = HOSTILE_STANCE_IDLE walk(src, 0) + LoseAggro() - -/mob/living/simple_animal/hostile/proc/ListTargets(var/override = -1) - - // Allows you to override how much the mob can see. Defaults to vision_range if none is entered. - if(override == -1) - override = vision_range - - var/list/L = hearers(src, override) - for(var/obj/mecha/M in mechas_list) - // Will check the distance before checking the line of sight, if the distance is small enough. - if(get_dist(M, src) <= override && can_see(src, M, override)) - L += M - return L +//////////////END HOSTILE MOB TARGETTING AND AGGRESSION//////////// /mob/living/simple_animal/hostile/Die() + LoseAggro() + mouse_opacity = 1 ..() walk(src, 0) -/mob/living/simple_animal/hostile/Life() - - . = ..() - if(!.) - walk(src, 0) - return 0 - if(client) - return 0 - - if(!stat) - switch(stance) - if(HOSTILE_STANCE_IDLE) - var/new_target = FindTarget() - GiveTarget(new_target) - - if(HOSTILE_STANCE_ATTACK) - DestroySurroundings() - MoveToTarget() - - if(HOSTILE_STANCE_ATTACKING) - DestroySurroundings() - AttackTarget() - /mob/living/simple_animal/hostile/proc/OpenFire(var/the_target) var/target = the_target - visible_message("\red [src] fires at [target]!", 1) + visible_message("\red [src] [ranged_message] at [target]!", 1) var/tturf = get_turf(target) if(rapid) @@ -168,9 +238,9 @@ stance = HOSTILE_STANCE_IDLE target = null + ranged_cooldown = ranged_cooldown_cap return - /mob/living/simple_animal/hostile/proc/Shoot(var/target, var/start, var/user, var/bullet = 0) if(target == start) return @@ -190,7 +260,15 @@ return /mob/living/simple_animal/hostile/proc/DestroySurroundings() - for(var/dir in cardinal) // North, South, East, West - var/obj/structure/obstacle = locate(/obj/structure, get_step(src, dir)) - if(istype(obstacle, /obj/structure/window) || istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table) || istype(obstacle, /obj/structure/grille)) - obstacle.attack_animal(src) + if(environment_smash) + if(buckled)//Beds and chairs are no longer hostile mob kryptonite + buckled.attack_animal(src) + var/list/directions = cardinal.Copy() + for(var/dir in directions) + var/turf/T = get_step(src, dir) + if(istype(T, /turf/simulated/wall)) + T.attack_animal(src) + for(var/atom/A in T) + if(istype(A, /obj/structure/window) || istype(A, /obj/structure/closet) || istype(A, /obj/structure/table) || istype(A, /obj/structure/grille) || istype(A, /obj/structure/rack)) + A.attack_animal(src) + return diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm new file mode 100644 index 00000000000..a885aa47387 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm @@ -0,0 +1,299 @@ +/mob/living/simple_animal/hostile/asteroid/ + vision_range = 2 + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + unsuitable_atoms_damage = 15 + faction = "mining" + environment_smash = 2 + minbodytemp = 0 + heat_damage_per_tick = 20 + response_help = "pokes" + response_disarm = "shoves" + response_harm = "strikes" + status_flags = 0 + a_intent = "harm" + var/throw_message = "bounces off of" + var/icon_aggro = null // for swapping to when we get aggressive + +/mob/living/simple_animal/hostile/asteroid/Aggro() + ..() + icon_state = icon_aggro + +/mob/living/simple_animal/hostile/asteroid/LoseAggro() + ..() + icon_state = icon_living + +/mob/living/simple_animal/hostile/asteroid/bullet_act(var/obj/item/projectile/P)//Limits the weapons available to kill them at range + if(P.damage < 30) + visible_message("The [P.name] had no effect on [src.name]!") + Aggro() + return + ..() + +/mob/living/simple_animal/hostile/asteroid/hitby(atom/movable/AM)//No floor tiling them to death, wiseguy + if(istype(AM, /obj/item)) + var/obj/item/T = AM + if(T.throwforce <= 15) + visible_message("The [T.name] [src.throw_message] [src.name]!") + Aggro() + return + ..() + +/mob/living/simple_animal/hostile/asteroid/basilisk + name = "basilisk" + desc = "A territorial beast, covered in a thick shell that absorbs energy. Its stare causes victims to freeze from the inside." + icon = 'icons/mob/animal.dmi' + icon_state = "Basilisk" + icon_living = "Basilisk" + icon_aggro = "Basilisk_alert" + icon_dead = "Basilisk_dead" + icon_gib = "syndicate_gib" + move_to_delay = 20 + projectiletype = /obj/item/projectile/temp/basilisk + projectilesound = 'sound/weapons/pierce.ogg' + ranged = 1 + ranged_message = "stares" + ranged_cooldown_cap = 8 + throw_message = "does nothing against the hard shell of" + vision_range = 2 + speed = 3 + maxHealth = 200 + health = 200 + harm_intent_damage = 5 + melee_damage_lower = 15 + melee_damage_upper = 15 + attacktext = "bites into" + a_intent = "harm" + attack_sound = 'sound/weapons/bladeslice.ogg' + ranged_cooldown_cap = 4 + +/obj/item/projectile/temp/basilisk + name = "freezing blast" + icon_state = "ice_2" + damage = 0 + damage_type = BURN + nodamage = 1 + flag = "energy" + temperature = 50 + +/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(var/new_target) + target = new_target + if(target != null) + Aggro() + stance = HOSTILE_STANCE_ATTACK + if(isliving(target)) + var/mob/living/L = target + if(L.bodytemperature > 261) + L.bodytemperature = 261 + visible_message("The [src.name]'s stare chills [L.name] to the bone!") + return + +/mob/living/simple_animal/hostile/asteroid/Goldgrub + name = "goldgrub" + desc = "A worm that grows fat from eating everything in its sight. Seems to enjoy precious metals and other shiny things, hence the name." + icon = 'icons/mob/animal.dmi' + icon_state = "Goldgrub" + icon_living = "Goldgrub" + icon_aggro = "Goldgrub_alert" + icon_dead = "Goldgrub_dead" + icon_gib = "syndicate_gib" + vision_range = 6 + move_to_delay = 3 + friendly = "harmlessly rolls into" + maxHealth = 45 + health = 45 + harm_intent_damage = 5 + melee_damage_lower = 0 + melee_damage_upper = 0 + attacktext = "barrels into" + a_intent = "help" + throw_message = "sinks in slowly, before being pushed out of " + status_flags = CANPUSH + search_objects = 2 + wanted_objects = list(/obj/item/weapon/ore/diamond, /obj/item/weapon/ore/gold, /obj/item/weapon/ore/silver, /obj/item/weapon/ore/plasma, + /obj/item/weapon/ore/uranium, /obj/item/weapon/ore/iron, /obj/item/weapon/ore/clown) + var/alerted = 0 + +/mob/living/simple_animal/hostile/asteroid/Goldgrub/GiveTarget(var/new_target) + target = new_target + if(target != null) + if(istype(target, /obj/item/weapon/ore)) + visible_message("The [src.name] looks at [target.name] with hungry eyes.") + stance = HOSTILE_STANCE_ATTACK + if(isliving(target) && !search_objects) + Aggro() + stance = HOSTILE_STANCE_ATTACK + visible_message("The [src.name] tries to flee from [target.name]!") + retreat_distance = 10 + Burrow() + return + +/obj/item/weapon/ore/attack_animal(var/mob/living/L) + if(istype(L, /mob/living/simple_animal/hostile/asteroid/Goldgrub)) + L.visible_message("The [src.name] was swallowed whole!") + del(src) + ..() + +/mob/living/simple_animal/hostile/asteroid/Goldgrub/proc/Burrow()//Begin the chase to kill the goldgrub in time + if(!alerted) + alerted = 1 + spawn(100) + if(alerted) + visible_message("The [src.name] buries into the ground, vanishing from sight!") + del(src) + +/mob/living/simple_animal/hostile/asteroid/Goldgrub/bullet_act(var/obj/item/projectile/P) + visible_message("The [P.name] was repelled by [src.name]'s girth!") + return + +/mob/living/simple_animal/hostile/asteroid/Goldgrub/Die() + alerted = 0 + ..() + +/mob/living/simple_animal/hostile/asteroid/Hivelord + name = "hivelord" + desc = "A truly alien creature, it is a mass of unknown organic material, constantly fluctuating. When attacking, pieces of it split off and attack in tandem with the original." + icon = 'icons/mob/animal.dmi' + icon_state = "Hivelord" + icon_living = "Hivelord" + icon_aggro = "Hivelord_alert" + icon_dead = "Hivelord_dead" + icon_gib = "syndicate_gib" + mouse_opacity = 2 + move_to_delay = 12 + ranged = 1 + vision_range = 4 + speed = 3 + maxHealth = 75 + health = 75 + harm_intent_damage = 5 + melee_damage_lower = 2 + melee_damage_upper = 2 + attacktext = "lashes out at" + throw_message = "falls right through the strange body of the" + ranged_cooldown = 0 + ranged_cooldown_cap = 0 + environment_smash = 0 + retreat_distance = 5 + minimum_distance = 5 + pass_flags = PASSTABLE + +/mob/living/simple_animal/hostile/asteroid/Hivelord/OpenFire(var/the_target) + var/mob/living/simple_animal/hostile/asteroid/Hivelordbrood/A = new /mob/living/simple_animal/hostile/asteroid/Hivelordbrood(src.loc) + A.GiveTarget(target) + return + +/mob/living/simple_animal/hostile/asteroid/Hivelord/AttackingTarget() + OpenFire() + ..() + +/mob/living/simple_animal/hostile/asteroid/Hivelordbrood + name = "hivelord brood" + desc = "A fragment of the original Hivelord, rallying behind its original. One isn't much of a threat, but..." + icon = 'icons/mob/animal.dmi' + icon_state = "Hivelordbrood" + icon_living = "Hivelordbrood" + icon_aggro = "Hivelordbrood" + icon_dead = "Hivelordbrood" + icon_gib = "syndicate_gib" + mouse_opacity = 2 + move_to_delay = 0 + friendly = "buzzes near" + vision_range = 10 + speed = 3 + maxHealth = 1 + health = 1 + harm_intent_damage = 5 + melee_damage_lower = 2 + melee_damage_upper = 2 + attacktext = "slashes" + throw_message = "falls right through the strange body of the" + environment_smash = 0 + pass_flags = PASSTABLE + +/mob/living/simple_animal/hostile/asteroid/Hivelordbrood/New() + ..() + spawn(100) + del(src) + +/mob/living/simple_animal/hostile/asteroid/Hivelordbrood/Die() + del(src) + +/mob/living/simple_animal/hostile/asteroid/Goliath + name = "goliath" + desc = "A massive beast that uses long tentacles to ensare its prey, threatening them is not advised under any conditions." + icon = 'icons/mob/animal.dmi' + icon_state = "Goliath" + icon_living = "Goliath" + icon_aggro = "Goliath_alert" + icon_dead = "Goliath_dead" + icon_gib = "syndicate_gib" + mouse_opacity = 2 + move_to_delay = 40 + ranged = 1 + ranged_cooldown_cap = 8 + friendly = "wails at" + vision_range = 5 + speed = 3 + maxHealth = 300 + health = 300 + harm_intent_damage = 0 + melee_damage_lower = 25 + melee_damage_upper = 25 + attacktext = "pulverizes" + throw_message = "does nothing to the rocky hide of the" + +/mob/living/simple_animal/hostile/asteroid/Goliath/OpenFire() + visible_message("The [src.name] digs its tentacles under [target.name]!") + var/tturf = get_turf(target) + new /obj/effect/goliath_tentacle/original(tturf) + ranged_cooldown = ranged_cooldown_cap + return + +/mob/living/simple_animal/hostile/asteroid/Goliath/adjustBruteLoss(var/damage) + ranged_cooldown-- + ..() + +/obj/effect/goliath_tentacle/ + name = "Goliath tentacle" + icon = 'icons/mob/animal.dmi' + icon_state = "Goliath_tentacle" + +/obj/effect/goliath_tentacle/New() + var/turftype = get_turf(src) + if(istype(turftype, /turf/simulated/mineral)) + var/turf/simulated/mineral/M = turftype + M.GetDrilled() + spawn(20) + Trip() + +/obj/effect/goliath_tentacle/original + +/obj/effect/goliath_tentacle/original/New() + var/list/directions = cardinal.Copy() + var/counter + for(counter = 1, counter <= 3, counter++) + var/spawndir = pick(directions) + directions -= spawndir + var/turf/T = get_step(src,spawndir) + new /obj/effect/goliath_tentacle(T) + ..() + +/obj/effect/goliath_tentacle/proc/Trip() + for(var/mob/living/M in src.loc) + M.Weaken(5) + visible_message("The [src.name] knocks [M.name] down!") + del(src) + +/obj/effect/goliath_tentacle/Crossed(AM as mob|obj) + if(isliving(AM)) + Trip() + return + ..() + diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index 8f1a738ec3c..cd3b4cc2a46 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -42,6 +42,8 @@ projectilesound = 'sound/weapons/laser.ogg' ranged = 1 rapid = 1 + retreat_distance = 5 + minimum_distance = 5 projectiletype = /obj/item/projectile/beam corpse = /obj/effect/landmark/mobcorpse/pirate/ranged weapon1 = /obj/item/weapon/gun/energy/laser diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm index c31082cdc59..be8d63d846e 100644 --- a/code/modules/mob/living/simple_animal/hostile/russian.dm +++ b/code/modules/mob/living/simple_animal/hostile/russian.dm @@ -40,6 +40,8 @@ corpse = /obj/effect/landmark/mobcorpse/russian/ranged weapon1 = /obj/item/weapon/gun/projectile/revolver/mateba ranged = 1 + retreat_distance = 5 + minimum_distance = 5 projectiletype = /obj/item/projectile/bullet projectilesound = 'sound/weapons/Gunshot.ogg' casingtype = /obj/item/ammo_casing/a357 diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index aa62cfa6a30..113e6c529cd 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -31,7 +31,6 @@ min_n2 = 0 max_n2 = 0 unsuitable_atoms_damage = 15 - wall_smash = 1 faction = "syndicate" status_flags = CANPUSH @@ -104,6 +103,8 @@ /mob/living/simple_animal/hostile/syndicate/ranged ranged = 1 rapid = 1 + retreat_distance = 5 + minimum_distance = 5 icon_state = "syndicateranged" icon_living = "syndicateranged" casingtype = /obj/item/ammo_casing/a12mm diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index f28358bb5da..771a9159e14 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -52,7 +52,7 @@ var/attacktext = "attacks" var/attack_sound = null var/friendly = "nuzzles" //If the mob does no damage with it's attack - var/wall_smash = 0 //if they can smash walls + var/environment_smash = 0 //Set to 1 to allow breaking of crates,lockers,racks,tables; 2 for walls; 3 for Rwalls var/speed = 0 //LETS SEE IF I CAN SET SPEEDS FOR SIMPLE MOBS WITHOUT DESTROYING EVERYTHING. Higher speed is slower, negative speed is faster var/can_hide = 0 @@ -506,6 +506,7 @@ if(alone && partner && children < 3) new childtype(loc) + // Harvest an animal's delicious byproducts /mob/living/simple_animal/proc/harvest() new meat_type (get_turf(src)) @@ -515,3 +516,16 @@ gib() return + +/mob/living/simple_animal/proc/CanAttack(var/atom/the_target) + if(see_invisible < the_target.invisibility) + return 0 + if (isliving(the_target)) + var/mob/living/L = the_target + if(L.stat != CONSCIOUS) + return 0 + if (istype(the_target, /obj/mecha)) + var/obj/mecha/M = the_target + if (M.occupant) + return 0 + return 1 diff --git a/code/modules/mob/living/simple_animal/vox.dm b/code/modules/mob/living/simple_animal/vox.dm index f3354ce8561..58491911e79 100644 --- a/code/modules/mob/living/simple_animal/vox.dm +++ b/code/modules/mob/living/simple_animal/vox.dm @@ -14,7 +14,6 @@ melee_damage_upper = 40 attacktext = "slammed its enormous claws into" speed = -1 - wall_smash = 1 attack_sound = 'sound/weapons/bladeslice.ogg' status_flags = 0 universal_speak = 1 diff --git a/code/modules/mob/living/simple_animal/worm.dm b/code/modules/mob/living/simple_animal/worm.dm index 14faaffdd57..1e8b6f97217 100644 --- a/code/modules/mob/living/simple_animal/worm.dm +++ b/code/modules/mob/living/simple_animal/worm.dm @@ -30,8 +30,6 @@ a_intent = "harm" //so they don't get pushed around - wall_smash = 1 - speed = -1 var/mob/living/simple_animal/space_worm/previous //next/previous segments, correspondingly diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 3f22b0d2fa0..0e832bddabe 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -934,6 +934,19 @@ note dizziness decrements automatically in the mob's Life() proc. //Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it. /mob/proc/update_canmove() + var/ko = weakened || paralysis || stat || (status_flags & FAKEDEATH) + if(ko || resting || buckled) + canmove = 0 + if(!lying) + if(resting) //Presuming that you're resting on a bed, which would look goofy lying the wrong way + lying = 90 + else + lying = pick(90, 270) //180 looks like shit since BYOND inverts rather than turns in that case + else if(stunned) + canmove = 0 + else + lying = 0 + canmove = 1 if(buckled) anchored = 1 canmove = 0 @@ -953,15 +966,18 @@ note dizziness decrements automatically in the mob's Life() proc. if(lying) density = 0 - drop_l_hand() - drop_r_hand() else density = 1 //Temporarily moved here from the various life() procs //I'm fixing stuff incrementally so this will likely find a better home. //It just makes sense for now. ~Carn - if( update_icon ) //forces a full overlay update + + if(lying != lying_prev) + if(lying && !lying_prev) + fall(ko) + + if(update_icon) //forces a full overlay update update_icon = 0 regenerate_icons() else if( lying != lying_prev ) @@ -969,6 +985,9 @@ note dizziness decrements automatically in the mob's Life() proc. return canmove +/mob/proc/fall(var/forced) + drop_l_hand() + drop_r_hand() /mob/verb/eastface() set hidden = 1 diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index ff8da9ca1d4..d954f367644 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -226,3 +226,4 @@ var/list/active_genes=list() + var/last_movement = -100 // Last world.time the mob actually moved of its own accord. diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 15cd2a8b55a..68af4e64484 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -280,8 +280,10 @@ else if(mob.confused) step(mob, pick(cardinal)) + mob.last_movement=world.time else . = ..() + mob.last_movement=world.time moving = 0 diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index b59459fbb60..95d87409251 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -31,6 +31,7 @@ O.dna = dna.Clone() O.dna.SetSEState(MONKEYBLOCK,1) + O.dna.SetSEValueRange(MONKEYBLOCK,0xDAC, 0xFFF) O.loc = loc O.viruses = viruses O.a_intent = "harm" diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index f47a718b932..4d3d0f02d38 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -182,7 +182,7 @@ obj/item/weapon/gun/energy/staff/focus zoom = 0 /obj/item/weapon/gun/energy/sniperrifle/verb/zoom() - set category = "Special Verbs" + set category = "Object" set name = "Zoom" set popup_menu = 0 if(usr.stat || !(istype(usr,/mob/living/carbon/human))) @@ -196,4 +196,20 @@ obj/item/weapon/gun/energy/staff/focus usr << sound('sound/mecha/imag_enh.ogg',volume=50) else usr.client.view = world.view//world.view - default mob view size - return \ No newline at end of file + return + + +/obj/item/weapon/gun/energy/kinetic_accelerator + name = "proto-kinetic accelerator" + desc = "According to Nanotrasen accounting, this is mining equipment. It's been modified to the legal limit on power output, and often serves as a miner's first defense against hostile alien life; it's not very powerful unless used in a low pressure environment." + icon_state = "freezegun" + item_state = "shotgun" + projectile_type = "/obj/item/projectile/kinetic" + cell_type = "/obj/item/weapon/cell/crap" + charge_cost = 500 + fire_delay = 20 + +/obj/item/weapon/gun/energy/kinetic_accelerator/attack_self(var/mob/living/user/L) + power_supply.give(500) + playsound(src.loc, 'sound/weapons/shotgunpump.ogg', 60, 1) + return diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 49d1e53ac05..cea43310b8c 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -179,8 +179,10 @@ if(!(original in permutated)) Bump(original) sleep(1) + Range() return + /obj/item/projectile/test //Used to see if you can hit them. invisibility = 101 //Nope! Can't see me! yo = null @@ -221,3 +223,7 @@ M = locate() in get_step(src,target) if(istype(M)) return 1 + +/obj/item/projectile/proc/Range() + return + diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 56f9a3594e8..cb72dec0d4e 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -152,3 +152,47 @@ src.visible_message("\red The [src.name] explodes!","\red You hear a snap!") playsound(src, 'sound/effects/snap.ogg', 50, 1) del(src) + +/obj/item/projectile/kinetic + name = "kinetic force" + icon_state = null + damage = 15 + damage_type = BRUTE + flag = "bomb" + var/range = 2 + +obj/item/projectile/kinetic/New() + var/turf/proj_turf = get_turf(src) + if(!istype(proj_turf, /turf)) + return + var/datum/gas_mixture/environment = proj_turf.return_air() + var/pressure = environment.return_pressure() + if(pressure < 50) + name = "full strength kinetic force" + damage = 30 + ..() + +/obj/item/projectile/kinetic/Range() + range-- + if(range <= 0) + new /obj/item/effect/kinetic_blast(src.loc) + delete() + +/obj/item/projectile/kinetic/on_hit(var/atom/target) + var/turf/target_turf= get_turf(target) + if(istype(target_turf, /turf/simulated/mineral)) + var/turf/simulated/mineral/M = target_turf + M.GetDrilled() + new /obj/item/effect/kinetic_blast(target_turf) + ..() + +/obj/item/effect/kinetic_blast + name = "kinetic explosion" + icon = 'icons/obj/projectiles.dmi' + icon_state = "kinetic_blast" + layer = 4.1 + +/obj/item/effect/kinetic_blast/New() + spawn(4) + del(src) + diff --git a/code/modules/reagents/reagent_containers/dropper.dm b/code/modules/reagents/reagent_containers/dropper.dm index cffc1781181..cc2ca414de6 100644 --- a/code/modules/reagents/reagent_containers/dropper.dm +++ b/code/modules/reagents/reagent_containers/dropper.dm @@ -78,6 +78,18 @@ else M.LAssailant = user + // /vg/: Logging transfers of bad things + if(isobj(target)) + if(target.reagents_to_log.len) + var/list/badshit=list() + for(var/bad_reagent in target.reagents_to_log) + if(reagents.has_reagent(bad_reagent)) + badshit += reagents_to_log[bad_reagent] + if(badshit.len) + var/hl="\red ([english_list(badshit)]) \black" + message_admins("[user.name] ([user.ckey]) added [reagents.get_reagent_ids(1)] to \a [target] with [src].[hl] (JMP)") + log_game("[user.name] ([user.ckey]) added [reagents.get_reagent_ids(1)] to \a [target] with [src].") + trans = src.reagents.trans_to(target, amount_per_transfer_from_this) user << "\blue You transfer [trans] units of the solution." if (src.reagents.total_volume<=0) diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 292e75c28f7..cf868d65de7 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -117,6 +117,17 @@ user << "\red [target] is full." return + // /vg/: Logging transfers of bad things + if(target.reagents_to_log.len) + var/list/badshit=list() + for(var/bad_reagent in target.reagents_to_log) + if(reagents.has_reagent(bad_reagent)) + badshit += reagents_to_log[bad_reagent] + if(badshit.len) + var/hl="\red ([english_list(badshit)]) \black" + message_admins("[user.name] ([user.ckey]) added [reagents.get_reagent_ids(1)] to \a [target] with [src].[hl] (JMP)") + log_game("[user.name] ([user.ckey]) added [reagents.get_reagent_ids(1)] to \a [target] with [src].") + var/trans = src.reagents.trans_to(target, amount_per_transfer_from_this) user << "\blue You transfer [trans] units of the solution to [target]." diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index 0ac603856f9..d4fbfa96132 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -68,6 +68,18 @@ if(!target.reagents.total_volume) user << "\red [target] is empty. Cant dissolve pill." return + + // /vg/: Logging transfers of bad things + if(target.reagents_to_log.len) + var/list/badshit=list() + for(var/bad_reagent in target.reagents_to_log) + if(reagents.has_reagent(bad_reagent)) + badshit += reagents_to_log[bad_reagent] + if(badshit.len) + var/hl="\red ([english_list(badshit)]) \black" + message_admins("[user.name] ([user.ckey]) added [reagents.get_reagent_ids(1)] to \a [target] with [src].[hl] (JMP)") + log_game("[user.name] ([user.ckey]) added [reagents.get_reagent_ids(1)] to \a [target] with [src].") + user << "\blue You dissolve the pill in [target]" reagents.trans_to(target, reagents.total_volume) for(var/mob/O in viewers(2, user)) diff --git a/code/modules/reagents/reagent_containers/robodropper.dm b/code/modules/reagents/reagent_containers/robodropper.dm index 4161f0f55b8..1e5a2384523 100644 --- a/code/modules/reagents/reagent_containers/robodropper.dm +++ b/code/modules/reagents/reagent_containers/robodropper.dm @@ -24,8 +24,19 @@ var/trans = 0 + if(isobj(target)) + // /vg/: Logging transfers of bad things + if(target.reagents_to_log.len) + var/list/badshit=list() + for(var/bad_reagent in target.reagents_to_log) + if(reagents.has_reagent(bad_reagent)) + badshit += reagents_to_log[bad_reagent] + if(badshit.len) + var/hl="\red ([english_list(badshit)]) \black" + message_admins("[user.name] ([user.ckey]) added [reagents.get_reagent_ids(1)] to \a [target] with [src].[hl] (JMP)") + log_game("[user.name] ([user.ckey]) added [reagents.get_reagent_ids(1)] to \a [target] with [src].") - if(ismob(target)) + else if(ismob(target)) if(istype(target , /mob/living/carbon/human)) var/mob/living/carbon/human/victim = target diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 981e45b335d..4feb53dc196 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -172,6 +172,19 @@ src.reagents.reaction(target, INGEST) if(ismob(target) && target == user) src.reagents.reaction(target, INGEST) + + if(isobj(target)) + // /vg/: Logging transfers of bad things + if(target.reagents_to_log.len) + var/list/badshit=list() + for(var/bad_reagent in target.reagents_to_log) + if(reagents.has_reagent(bad_reagent)) + badshit += reagents_to_log[bad_reagent] + if(badshit.len) + var/hl="\red ([english_list(badshit)]) \black" + message_admins("[user.name] ([user.ckey]) added [reagents.get_reagent_ids(1)] to \a [target] with [src].[hl] (JMP)") + log_game("[user.name] ([user.ckey]) added [reagents.get_reagent_ids(1)] to \a [target] with [src].") + spawn(5) var/datum/reagent/blood/B for(var/datum/reagent/blood/d in src.reagents.reagent_list) diff --git a/icons/effects/genetics.dmi b/icons/effects/genetics.dmi index 8e31fea9613..59df7dcbe2a 100644 Binary files a/icons/effects/genetics.dmi and b/icons/effects/genetics.dmi differ diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi index af333aba64a..ceeae46da7f 100644 Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ diff --git a/icons/mob/blob.dmi b/icons/mob/blob.dmi index 7b265ba2bd1..a3d5d618c7c 100644 Binary files a/icons/mob/blob.dmi and b/icons/mob/blob.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 79d67089365..6b39e0332bc 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index b4bb02e094b..26a05d80e49 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi index 045d913b4e6..1e563ef7cce 100644 Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index df818e448ef..89f2ccf8525 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index d95cb53dfb3..92ef8b8b97d 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index cf29adaac65..c44890b0921 100644 Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi index 2aa679c6fce..55e4c512f27 100755 Binary files a/icons/obj/stationobjs.dmi and b/icons/obj/stationobjs.dmi differ diff --git a/nano/templates/freezer.tmpl b/nano/templates/freezer.tmpl new file mode 100644 index 00000000000..9e1c13edaee --- /dev/null +++ b/nano/templates/freezer.tmpl @@ -0,0 +1,49 @@ +
+
+ Status: +
+
+ {{:~link('On', 'power', {'toggleStatus' : 1}, on ? 'selected' : null)}}{{:~link('Off', 'close', {'toggleStatus' : 1}, on ? null : 'selected')}} +
+
+ +
+
+ Gas Pressure: +
+
+ {{:gasPressure}} kPa +
+
+ +

Gas Temperature

+
+
+ Current: +
+
+ {{:~displayBar(gasTemperature, minGasTemperature, maxGasTemperature, gasTemperatureClass)}} +
+ {{:gasTemperature}} K +
+
+
+ +
+
+ Target: +
+
+ {{:~displayBar(targetGasTemperature, minGasTemperature, maxGasTemperature)}} +
+ {{:~link('-', null, {'temp' : -100}, (targetGasTemperature > minGasTemperature) ? null : 'disabled')}} + {{:~link('-', null, {'temp' : -10}, (targetGasTemperature > minGasTemperature) ? null : 'disabled')}} + {{:~link('-', null, {'temp' : -1}, (targetGasTemperature > minGasTemperature) ? null : 'disabled')}} +
 {{:targetGasTemperature}} K 
+ {{:~link('+', null, {'temp' : 1}, (targetGasTemperature < maxGasTemperature) ? null : 'disabled')}} + {{:~link('+', null, {'temp' : 10}, (targetGasTemperature < maxGasTemperature) ? null : 'disabled')}} + {{:~link('+', null, {'temp' : 100}, (targetGasTemperature < maxGasTemperature) ? null : 'disabled')}} +
+
+
+ diff --git a/scripts/voice.py b/scripts/voice.py new file mode 100644 index 00000000000..47d25a31615 --- /dev/null +++ b/scripts/voice.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python2 +''' +WINDOWS ONLY! +You need espeak: http://sourceforge.net/projects/espeak/files/espeak/espeak-1.47/espeak-1.47.11-win.zip/download +SOund eXchange (sox): http://sourceforge.net/projects/sox/files/sox/14.4.1/sox-14.4.1a-win32.zip/download +and WinVorbis for OggEnc: http://winvorbis.stationplaylist.com/WinVorbisSetup.exe +''' +import sys, os, re, string +from subprocess import call +accent = sys.argv[1] +voice = sys.argv[2] +pitch = sys.argv[3] +echo = sys.argv[4] +speed = sys.argv[5] +text = sys.argv[6] +ckey = sys.argv[7] +espeakpath = "C:/Program Files (x86)/eSpeak/command_line/" +playervoicespath = "C:/Users/Administrator/Dropbox/Baystation12/sound/playervoices/" +soxpath = "C:/Program Files (x86)/sox-14-4-1/" +oggencpath = "C:/Program Files (x86)/WinVorbis/" +text = string.replace(text, "39", "'") +command = "\""+espeakpath+"espeak.exe\" -w "+playervoicespath+""+ckey+"u.wav -v"+accent+""+voice+" \""+text+"\" -p "+pitch+" -s "+speed+" -a 100" +# First we make the voice file, sounds/playervoice/keyu.wav +call(command, shell=True) +command2 = "\""+soxpath+"sox.exe\" "+playervoicespath+""+ckey+"u.wav \""+playervoicespath+""+ckey+".wav\" echo 1 0.5 "+echo+" .5" +# Now we apply effects to it, like echo (there's lots of other effects too) +call(command2, shell=True) +#remove the old keyu.wav +os.remove(playervoicespath+""+ckey+"u.wav") +command3 = "\""+oggencpath+"OggEnc.exe\" "+playervoicespath+""+ckey+".wav" +#Now we turn key.wav into key.ogg to reduce bandwidth +call(command3, shell=True) +#delete the wav +os.remove(playervoicespath+""+ckey+".wav") +sys.exit() \ No newline at end of file diff --git a/sound/effects/bodyfall1.ogg b/sound/effects/bodyfall1.ogg new file mode 100644 index 00000000000..cf217a8e077 Binary files /dev/null and b/sound/effects/bodyfall1.ogg differ diff --git a/sound/effects/bodyfall2.ogg b/sound/effects/bodyfall2.ogg new file mode 100644 index 00000000000..49f6cdd39ad Binary files /dev/null and b/sound/effects/bodyfall2.ogg differ diff --git a/sound/effects/bodyfall3.ogg b/sound/effects/bodyfall3.ogg new file mode 100644 index 00000000000..5a3817510d7 Binary files /dev/null and b/sound/effects/bodyfall3.ogg differ diff --git a/sound/effects/bodyfall4.ogg b/sound/effects/bodyfall4.ogg new file mode 100644 index 00000000000..e6a1661c931 Binary files /dev/null and b/sound/effects/bodyfall4.ogg differ