diff --git a/baystation12.dme b/baystation12.dme index 68d5ab3d3d0..f002ef969d2 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -710,6 +710,7 @@ #include "code\modules\admin\verbs\striketeam_syndicate.dm" #include "code\modules\admin\verbs\ticklag.dm" #include "code\modules\admin\verbs\tripAI.dm" +#include "code\modules\admin\verbs\vox_raiders.dm" #include "code\modules\assembly\assembly.dm" #include "code\modules\assembly\bomb.dm" #include "code\modules\assembly\helpers.dm" @@ -1001,6 +1002,7 @@ #include "code\modules\mob\living\simple_animal\parrot.dm" #include "code\modules\mob\living\simple_animal\shade.dm" #include "code\modules\mob\living\simple_animal\simple_animal.dm" +#include "code\modules\mob\living\simple_animal\vox.dm" #include "code\modules\mob\living\simple_animal\worm.dm" #include "code\modules\mob\living\simple_animal\friendly\cat.dm" #include "code\modules\mob\living\simple_animal\friendly\corgi.dm" diff --git a/code/ZAS/Functions.dm b/code/ZAS/Functions.dm index 7b4ea8dff86..ce24513418e 100644 --- a/code/ZAS/Functions.dm +++ b/code/ZAS/Functions.dm @@ -81,28 +81,43 @@ proc/ZMerge(zone/A,zone/B) if(!istype(A) || !istype(B)) return - //Merges two zones so that they are one. - var/a_size = A.air.group_multiplier - var/b_size = B.air.group_multiplier - var/c_size = a_size + b_size var/new_contents = A.contents + B.contents - //Set air multipliers to one so air represents gas per tile. - A.air.group_multiplier = 1 - B.air.group_multiplier = 1 - - //Remove some air proportional to the size of this zone. - A.air.remove_ratio(a_size/c_size) - B.air.remove_ratio(b_size/c_size) - - //Merge the gases and set the multiplier to the sum of the old ones. - A.air.merge(B.air) - A.air.group_multiplier = c_size - //Set all the zone vars. for(var/turf/simulated/T in B.contents) T.zone = A + if(istype(A.air) && istype(B.air)) + //Merges two zones so that they are one. + var/a_size = A.air.group_multiplier + var/b_size = B.air.group_multiplier + var/c_size = a_size + b_size + + //Set air multipliers to one so air represents gas per tile. + A.air.group_multiplier = 1 + B.air.group_multiplier = 1 + + //Remove some air proportional to the size of this zone. + A.air.remove_ratio(a_size/c_size) + B.air.remove_ratio(b_size/c_size) + + //Merge the gases and set the multiplier to the sum of the old ones. + A.air.merge(B.air) + A.air.group_multiplier = c_size + + //I hate when the air datum somehow disappears. + // Try to make it sorta work anyways. Fakit + else if(istype(B.air)) + A.air = B.air + A.air.group_multiplier = A.contents.len + + else if(istype(A.air)) + A.air.group_multiplier = A.contents.len + + //Doublefakit. + else + A.air = new + //Check for connections to merge into the new zone. for(var/connection/C in B.connections) //The Cleanup proc will delete the connection if the zones are the same. diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index e3f69881daa..9afd8543295 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -122,9 +122,10 @@ proc/get_id_photo(var/mob/living/carbon/human/H) icobase = 'icons/mob/human_races/r_lizard.dmi' if("Skrell") icobase = 'icons/mob/human_races/r_skrell.dmi' - if("Vox") icobase = 'icons/mob/human_races/r_vox.dmi' + if("Kidan") + icobase = 'icons/mob/human_races/r_kidan.dmi' else icobase = 'icons/mob/human_races/r_human.dmi' diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 81abf92546a..df3a72391f7 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -730,7 +730,7 @@ client usr << "This can only be done to instances of type /mob/living/carbon/human" return - var/new_mutantrace = input("Please choose a new mutantrace","Mutantrace",null) as null|anything in list("NONE","golem","lizard","slime","plant","shadow","tajaran","skrell","vox") + var/new_mutantrace = input("Please choose a new mutantrace","Mutantrace",null) as null|anything in list("NONE","golem","lizard","slime","plant","shadow","tajaran","skrell","vox","kidan") switch(new_mutantrace) if(null) return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 175e622788a..4984b982839 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -1220,5 +1220,9 @@ datum/mind mind.assigned_role = "Juggernaut" mind.special_role = "Cultist" +/mob/living/simple_animal/vox/armalis/mind_initialize() + ..() + mind.assigned_role = "Armalis" + mind.special_role = "Vox Raider" diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index d435e55f793..57ddf7817e5 100755 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -66,6 +66,29 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containername = "Monkey crate" group = "Hydroponics" +/datum/supply_packs/farwa + name = "Farwa crate" + contains = list (/obj/item/weapon/storage/box/farwacubes) + cost = 30 + containertype = /obj/structure/closet/crate/freezer + containername = "Farwa crate" + group = "Hydroponics" + +/datum/supply_packs/skrell + name = "Neaera crate" + contains = list (/obj/item/weapon/storage/box/neaeracubes) + cost = 30 + containertype = /obj/structure/closet/crate/freezer + containername = "Neaera crate" + group = "Hydroponics" + +/datum/supply_packs/stok + name = "Stok crate" + contains = list (/obj/item/weapon/storage/box/stokcubes) + cost = 30 + containertype = /obj/structure/closet/crate/freezer + containername = "Stok crate" + group = "Hydroponics" /datum/supply_packs/beanbagammo name = "Beanbag shells" diff --git a/code/game/dna.dm b/code/game/dna.dm index c652140d96c..cb58013e016 100644 --- a/code/game/dna.dm +++ b/code/game/dna.dm @@ -548,7 +548,17 @@ sleep(48) del(animation) - var/mob/living/carbon/monkey/O = new(src) + + var/mob/living/carbon/monkey/O = null + switch(M.dna.mutantrace) + if("tajaran") + O = new /mob/living/carbon/monkey/tajara(src) + if("lizard") + O = new /mob/living/carbon/monkey/unathi(src) + if("skrell") + O = new /mob/living/carbon/monkey/skrell(src) + else + O = new /mob/living/carbon/monkey(src) if(M) if (M.dna) diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index a68276a3100..6fbdba918ed 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -153,6 +153,7 @@ icon_state = "knife" desc = "A general purpose Chef's Knife made by SpaceCook Incorporated. Guaranteed to stay sharp for years to come." flags = FPRINT | TABLEPASS | CONDUCT + sharp = 1 force = 10.0 w_class = 3.0 throwforce = 6.0 diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index b89cfd6a7fd..f1b9319f954 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -277,7 +277,41 @@ ..() for(var/i = 1; i <= 5; i++) new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped(src) +/obj/item/weapon/storage/box/farwacubes + name = "farwa cube box" + desc = "Drymate brand farwa cubes. Just add water!" + icon = 'icons/obj/food.dmi' + icon_state = "monkeycubebox" + storage_slots = 7 + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/farwacube") + New() + ..() + for(var/i = 1; i <= 5; i++) + new /obj/item/weapon/reagent_containers/food/snacks/farwacube/wrapped(src) +/obj/item/weapon/storage/box/stokcubes + name = "stok cube box" + desc = "Drymate brand stok cubes. Just add water!" + icon = 'icons/obj/food.dmi' + icon_state = "monkeycubebox" + storage_slots = 7 + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/stokcube") + New() + ..() + for(var/i = 1; i <= 5; i++) + new /obj/item/weapon/reagent_containers/food/snacks/stokcube/wrapped(src) + +/obj/item/weapon/storage/box/neaeracubes + name = "neaera cube box" + desc = "Drymate brand neaera cubes. Just add water!" + icon = 'icons/obj/food.dmi' + icon_state = "monkeycubebox" + storage_slots = 7 + can_hold = list("/obj/item/weapon/reagent_containers/food/snacks/stokcube") + New() + ..() + for(var/i = 1; i <= 5; i++) + new /obj/item/weapon/reagent_containers/food/snacks/neaeracube/wrapped(src) /obj/item/weapon/storage/box/ids name = "spare IDs" diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 08af5cda280..92e6b78d754 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -146,5 +146,5 @@ item_state = "harpoon" force = 20 throwforce = 15 - w_class = 2 + w_class = 3 attack_verb = list("jabbed","stabbed","ripped") \ No newline at end of file diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index 275d4b7dbf3..7a76a2c9685 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -84,3 +84,65 @@ var/global/normal_ooc_colour = "#002eb8" set desc = "Set to yellow for eye burning goodness." set category = "Fun" normal_ooc_colour = newColor + + +/client/verb/looc(msg as text) + set name = "LOOC" //Gave this shit a shorter name so you only have to time out "ooc" rather than "ooc message" to use it --NeoFite + set desc = "Local OOC, seen only by those in view." + set category = "OOC" + + if(say_disabled) //This is here to try to identify lag problems + usr << "\red Speech is currently admin-disabled." + return + + if(!mob) return + if(IsGuestKey(key)) + src << "Guests may not use OOC." + return + + msg = copytext(sanitize(msg), 1, MAX_MESSAGE_LEN) + if(!msg) return + + if(!(prefs.toggles & CHAT_OOC)) + src << "\red You have OOC muted." + return + + if(!holder) + if(!ooc_allowed) + src << "\red OOC is globally muted" + return + if(!dooc_allowed && (mob.stat == DEAD)) + usr << "\red OOC for dead mobs has been turned off." + return + if(prefs.muted & MUTE_OOC) + src << "\red You cannot use OOC (muted)." + return + if(handle_spam_prevention(msg,MUTE_OOC)) + return + if(findtext(msg, "byond://")) + src << "Advertising other servers is not allowed." + log_admin("[key_name(src)] has attempted to advertise in OOC: [msg]") + message_admins("[key_name_admin(src)] has attempted to advertise in OOC: [msg]") + return + + log_ooc("(LOCAL) [mob.name]/[key] : [msg]") + + for(var/mob/M in hearers()) + if(!M.client) + continue + var/client/C = M.client + if (C in admins) + continue //they are handled after that + + if(C.prefs.toggles & CHAT_OOC) + var/display_name = src.key + if(holder) + if(holder.fakekey) + if(C.holder) + display_name = "[holder.fakekey]/([src.key])" + else + display_name = holder.fakekey + C << "LOOC: [display_name]: [msg]" + for(var/client/C in admins) + if(C.prefs.toggles & CHAT_OOC) + C << "LOOC: [src.key]: [msg]" \ No newline at end of file diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index c36a0ab99d2..acb7e3b2283 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -647,7 +647,7 @@ var/list/admin_verbs_mod = list( if(!istype(M, /mob/living/carbon/human)) usr << "\red You can only do this to humans!" return - switch(alert("Are you sure you wish to edit this mob's appearance? Skrell, Unathi, Vox and Tajaran can result in unintended consequences.",,"Yes","No")) + switch(alert("Are you sure you wish to edit this mob's appearance? Skrell, Unathi, Vox, Kida, and Tajara can result in unintended consequences.",,"Yes","No")) if("No") return var/new_facial = input("Please select facial hair color.", "Character Generation") as color diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 292327ca274..6303e8d0da0 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -11,31 +11,31 @@ if("1") log_admin("[key_name(usr)] has spawned a traitor.") if(!src.makeTraitors()) - usr << "\red Unfortunatly there were no candidates available" + usr << "\red Unfortunately there weren't enough candidates available." if("2") log_admin("[key_name(usr)] has spawned a changeling.") if(!src.makeChanglings()) - usr << "\red Unfortunatly there were no candidates available" + usr << "\red Unfortunately there weren't enough candidates available." if("3") log_admin("[key_name(usr)] has spawned revolutionaries.") if(!src.makeRevs()) - usr << "\red Unfortunatly there were no candidates available" + usr << "\red Unfortunately there weren't enough candidates available." if("4") log_admin("[key_name(usr)] has spawned a cultists.") if(!src.makeCult()) - usr << "\red Unfortunatly there were no candidates available" + usr << "\red Unfortunately there weren't enough candidates available." if("5") log_admin("[key_name(usr)] has spawned a malf AI.") if(!src.makeMalfAImode()) - usr << "\red Unfortunatly there were no candidates available" + usr << "\red Unfortunately there weren't enough candidates available." if("6") log_admin("[key_name(usr)] has spawned a wizard.") if(!src.makeWizard()) - usr << "\red Unfortunatly there were no candidates available" + usr << "\red Unfortunately there weren't enough candidates available." if("7") log_admin("[key_name(usr)] has spawned a nuke team.") if(!src.makeNukeTeam()) - usr << "\red Unfortunatly there were no candidates available" + usr << "\red Unfortunately there weren't enough candidates available." if("8") log_admin("[key_name(usr)] has spawned a ninja.") src.makeSpaceNinja() @@ -44,8 +44,10 @@ src.makeAliens() if("10") log_admin("[key_name(usr)] has spawned a death squad.") - if(!src.makeDeathsquad()) - usr << "\red Unfortunatly there were no candidates available" + if("11") + log_admin("[key_name(usr)] has spawned vox raiders.") + if(!src.makeVoxRaiders()) + usr << "\red Unfortunately there weren't enough candidates available." else if(href_list["dbsearchckey"] || href_list["dbsearchadmin"]) var/adminckey = href_list["dbsearchadmin"] var/playerckey = href_list["dbsearchckey"] diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm index 8ef53eb0232..8bb15c1cb3b 100644 --- a/code/modules/admin/verbs/one_click_antag.dm +++ b/code/modules/admin/verbs/one_click_antag.dm @@ -17,6 +17,7 @@ client/proc/one_click_antag() Make Cult
Make Malf AI
Make Wizard (Requires Ghosts)
+ Make Vox Raiders (Requires Ghosts)
"} /* These dont work just yet Ninja, aliens and deathsquad I have not looked into yet @@ -429,4 +430,94 @@ client/proc/one_click_antag() ticker.mode.traitors += new_syndicate_commando.mind new_syndicate_commando.equip_syndicate_commando(syndicate_leader_selected) - return new_syndicate_commando \ No newline at end of file + return new_syndicate_commando + +/datum/admins/proc/makeVoxRaiders() + + var/list/mob/dead/observer/candidates = list() + var/mob/dead/observer/theghost = null + var/time_passed = world.time + var/input = "Disregard shinies, acquire hardware." + + var/leader_chosen = 0 //when the leader is chosen. The last person spawned. + + //Generates a list of candidates from active ghosts. The admin picks which players to respawn as the vox. + for(var/mob/dead/observer/G in player_list) + spawn(0) + if(is_alien_whitelisted(src, "Vox") || !config.usealienwhitelist) + switch(alert(G,"Do you wish to be considered for a vox raiding party arriving on the station?","Please answer in 30 seconds!","Yes","No")) + if("Yes") + if((world.time-time_passed)>300)//If more than 30 game seconds passed. + return + candidates += G + if("No") + return + else + return + + sleep(300) //Debug. + + for(var/mob/dead/observer/G in candidates) + if(!G.key) + candidates.Remove(G) + + if(candidates.len) + var/raiders = 4 + //Spawns vox raiders and equips them. + for (var/obj/effect/landmark/L in world) + if(L.name == "Response Team") + if(raiders<=0) + break + + var/mob/living/carbon/human/new_vox = create_vox_raider(L, leader_chosen) + + while((!theghost || !theghost.client) && candidates.len) + theghost = pick(candidates) + candidates.Remove(theghost) + + if(!theghost) + del(new_vox) + break + + new_vox.key = theghost.key + new_vox << "\blue You are a Vox Primalis, fresh out of the Shoal. Your ship has arrived at the Tau Ceti system hosting the NSV Exodus... or was it the Luna? NSS? Utopia? Nobody is really sure, but everyong is raring to start pillaging! Your current goal is: \red [input]" + new_vox << "\red Don't forget to turn on your nitrogen internals!" + + raiders-- + if(raiders >= 4) + return 0 + else + return 0 + return 1 + +/datum/admins/proc/create_vox_raider(obj/spawn_location, leader_chosen = 0) + var/mob/living/carbon/human/new_vox = new(spawn_location.loc) + + new_vox.gender = pick(MALE, FEMALE) + var/datum/preferences/A = new() //Randomize appearance for the raider. + A.randomize_appearance_for(new_vox) + new_vox.h_style = "Short Vox Quills" + new_vox.regenerate_icons() + + var/sounds = rand(2,10) + var/i = 0 + var/newname = "" + + while(i<=sounds) + i++ + newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah")) + + new_vox.real_name = capitalize(newname) + new_vox.name = new_vox.real_name + new_vox.age = rand(12,20) + + new_vox.dna.ready_dna(new_vox) // Creates DNA. + new_vox.dna.mutantrace = "vox" // Actually makes the vox! How about that. + new_vox.mind_initialize() + new_vox.mind.assigned_role = "MODE" + new_vox.mind.special_role = "Vox Raider" + + ticker.mode.traitors += new_vox.mind + new_vox.equip_vox_raider() + + return new_vox \ No newline at end of file diff --git a/code/modules/admin/verbs/vox_raiders.dm b/code/modules/admin/verbs/vox_raiders.dm new file mode 100644 index 00000000000..93f6af6eb5a --- /dev/null +++ b/code/modules/admin/verbs/vox_raiders.dm @@ -0,0 +1,66 @@ +/mob/living/carbon/human/proc/equip_vox_raider() + + var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(src) + R.set_frequency(SYND_FREQ) //Same frequency as the syndicate team in Nuke mode. + equip_to_slot_or_del(R, slot_ears) + + equip_to_slot_or_del(new /obj/item/clothing/under/vox/vox_robes(src), slot_w_uniform) + equip_to_slot_or_del(new /obj/item/clothing/shoes/magboots/vox(src), slot_shoes) // REPLACE THESE WITH CODED VOX ALTERNATIVES. + equip_to_slot_or_del(new /obj/item/clothing/gloves/yellow/vox(src), slot_gloves) // AS ABOVE. + + switch(rand(1,4)) // Come up with a better way of doing this - ticker of some sort maybe. + if(1) // Vox raider! + equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/carapace(src), slot_wear_suit) + equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/carapace(src), slot_head) + equip_to_slot_or_del(new /obj/item/weapon/melee/telebaton(src), slot_belt) + equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. + equip_to_slot_or_del(new /obj/item/device/chameleon(src), slot_l_store) + + var/obj/item/weapon/crossbow/W = new(src) + W.cell = new /obj/item/weapon/cell/crap(W) + W.cell.charge = 500 + equip_to_slot_or_del(W, slot_r_hand) + + if(2) // Vox engineer! + equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/pressure(src), slot_wear_suit) + equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/pressure(src), slot_head) + equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(src), slot_belt) + equip_to_slot_or_del(new /obj/item/clothing/glasses/meson(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. + equip_to_slot_or_del(new /obj/item/weapon/storage/box/emps(src), slot_l_store) + + equip_to_slot_or_del(new /obj/item/weapon/pickaxe/plasmacutter(src), slot_r_hand) + + if(3) // Vox saboteur! + equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/carapace(src), slot_wear_suit) + equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/carapace(src), slot_head) + equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(src), slot_belt) + equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. + equip_to_slot_or_del(new /obj/item/weapon/card/emag(src), slot_l_store) + + var/obj/item/weapon/storage/pneumatic/W = new(src) + W.tank = new /obj/item/weapon/tank/nitrogen(W) + equip_to_slot_or_del(W, slot_r_hand) + + if(4) // Vox medic! + equip_to_slot_or_del(new /obj/item/clothing/suit/space/vox/pressure(src), slot_wear_suit) + equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/vox/pressure(src), slot_head) + equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(src), slot_belt) // Who needs actual surgical tools? + equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/health(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE. + equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/hypospray(src), slot_l_store) + + equip_to_slot_or_del(new /obj/item/weapon/circular_saw(src), slot_l_hand) + equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/toxin(src), slot_r_hand) + + equip_to_slot_or_del(new /obj/item/clothing/mask/breath/vox(src), slot_wear_mask) + equip_to_slot_or_del(new /obj/item/weapon/tank/nitrogen(src), slot_back) + equip_to_slot_or_del(new /obj/item/device/flashlight(src), slot_r_store) + + var/obj/item/weapon/card/id/syndicate/W = new(src) + W.name = "[real_name]'s Legitimate Human ID Card" + W.icon_state = "id" + W.access = list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage, access_syndicate) + W.assignment = "Trader" + W.registered_name = real_name + equip_to_slot_or_del(W, slot_wear_id) + + return 1 \ No newline at end of file diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 8d5376c3131..e6a76d88e8e 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -792,18 +792,18 @@ datum/preferences if(is_alien_whitelisted(user, "Skrell")) //Check for Skrell and admins new_species += "Skrell" whitelisted = 1 - if(is_alien_whitelisted(user, "Vox")) //Check for Skrell and admins - new_species += "Vox" + if(is_alien_whitelisted(user, "Kidan")) // Check for Kidan and admins + new_species += "Kidan" whitelisted = 1 - if(!whitelisted) alert(user, "You cannot change your species as you need to be whitelisted. If you wish to be whitelisted contact an admin in-game, on the forums, or on IRC.") + else //Not using the whitelist? Aliens for everyone! new_species += "Tajaran" new_species += "Unathi" new_species += "Skrell" - new_species += "Vox" + new_species += "Kidan" species = input("Please select a species", "Character Generation", null) in new_species if(prev_species != species) diff --git a/code/modules/clothing/spacesuits/alien.dm b/code/modules/clothing/spacesuits/alien.dm index 3a8824e644e..c17f1b5aeaf 100644 --- a/code/modules/clothing/spacesuits/alien.dm +++ b/code/modules/clothing/spacesuits/alien.dm @@ -104,4 +104,56 @@ desc = "Weird and flowing!" icon_state = "vox-casual-2" color = "vox-casual-2" - item_state = "vox-casual-2" \ No newline at end of file + item_state = "vox-casual-2" + +/obj/item/clothing/gloves/yellow/vox + desc = "These bizarre gauntlets seem to be fitted for... bird claws?" + name = "insulated gauntlets" + icon_state = "gloves-vox" + item_state = "gloves-vox" + siemens_coefficient = 0 + permeability_coefficient = 0.05 + color="gloves-vox" + +/obj/item/clothing/gloves/yellow/vox/mob_can_equip(M as mob, slot) + var/mob/living/carbon/human/U = M + if(U.dna.mutantrace != "vox") + U << "This clearly isn't designed for your species!" + return 0 + return ..() + +/obj/item/clothing/shoes/magboots/vox + + desc = "A pair of heavy, jagged armoured foot pieces, seemingly suitable for a velociraptor." + name = "vox boots" + item_state = "boots-vox" + icon_state = "boots-vox" + + toggle() + name = "Toggle Floor Grip" + + if(src.magpulse) + src.flags &= ~NOSLIP + src.magpulse = 0 + usr << "You relax your deathgrip on the flooring." + else + src.flags |= NOSLIP + src.magpulse = 1 + usr << "You dig your claws deeply into the flooring, bracing yourself." + + + examine() + set src in view() + ..() + var/state = "loosely" + if(src.flags&NOSLIP) + state = "tightly" + usr << "The wearer seems to be gripping the floor [state]." + + +/obj/item/clothing/shoes/magboots/vox/mob_can_equip(M as mob, slot) + var/mob/living/carbon/human/U = M + if(U.dna.mutantrace != "vox") + U << "This clearly isn't designed for your species!" + return 0 + return ..() \ No newline at end of file diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index 7bafd4a31fc..448425e454d 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -34,9 +34,11 @@ attack(mob/living/carbon/human/M as mob, mob/user as mob) if (!ishuman(M)) user << "\red [M] is not human and cannot have the fingerprints." + flick("forensic0",src) return 0 if (( !( istype(M.dna, /datum/dna) ) || M.gloves) ) user << "\blue No fingerprints found on [M]" + flick("forensic0",src) return 0 else if (src.amount < 1) @@ -71,6 +73,7 @@ return if(istype(A,/obj/item/weapon/f_card)) user << "The scanner displays on the screen: \"ERROR 43: Object on Excluded Object List.\"" + flick("forensic0",src) return add_fingerprint(user) @@ -81,6 +84,7 @@ if(!isnull(A.blood_DNA)) for(var/blood in A.blood_DNA) user << "\blue Blood type: [A.blood_DNA[blood]]\nDNA: [blood]" + flick("forensic2",src) return //General @@ -88,10 +92,12 @@ user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\ "\blue Unable to locate any fingerprints, materials, fibers, or blood on [A]!",\ "You hear a faint hum of electrical equipment.") + flick("forensic0",src) return 0 if(add_data(A)) user << "\blue Object already in internal memory. Consolidating data..." + flick("forensic2",src) return @@ -116,6 +122,7 @@ //FIBERS if(A.suit_fibers) user << "\blue Fibers/Materials Data Stored: Scan with Hi-Res Forensic Scanner to retrieve." + flick("forensic2",src) //Blood if (A.blood_DNA) @@ -127,11 +134,13 @@ user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\ "You finish scanning \the [A].",\ "You hear a faint hum of electrical equipment.") + flick("forensic2",src) return 0 else user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]\n[user.gender == MALE ? "He" : "She"] seems to perk up slightly at the readout." ,\ "The results of the scan pique your interest.",\ "You hear a faint hum of electrical equipment, and someone making a thoughtful noise.") + flick("forensic2",src) return 0 return diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 63d685bfbdd..02fffec17b4 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -45,7 +45,7 @@ if(istype(tmob, /mob/living/carbon/human)) for(var/mob/M in range(tmob, 1)) - if( ((M.pulling == tmob && ( tmob.restrained() && !( M.restrained() ) && M.stat == 0)) || locate(/obj/item/weapon/grab, tmob.grabbed_by.len)) ) + if(tmob.pinned.len || ((M.pulling == tmob && ( tmob.restrained() && !( M.restrained() ) && M.stat == 0)) || locate(/obj/item/weapon/grab, tmob.grabbed_by.len)) ) if ( !(world.time % 5) ) src << "\red [tmob] is restrained, you cannot push past" now_pushing = 0 @@ -817,6 +817,8 @@ return "Mobile vegetation" if("golem") return "Animated Construct" + if("kidan") + return "Kidan" else return "Human" @@ -829,7 +831,9 @@ else if(src.dna.mutantrace == "tajaran") return "Tajaran" else if(src.dna.mutantrace == "vox") - return "vox" + return "Vox" + else if(src.dna.mutantrace == "kidan") + return "Kidan" /mob/living/carbon/proc/update_mutantrace_languages() if(src.dna) @@ -841,6 +845,8 @@ src.tajaran_talk_understand = 1 else if(src.dna.mutantrace == "vox") src.vox_talk_understand = 1 + else if(src.dna.mutantrace == "kidan") + src.kidan_talk_understand = 1 /mob/living/carbon/human/proc/play_xylophone() if(!src.xylophone) @@ -1113,50 +1119,79 @@ del(feet_blood_DNA) return 1 -/mob/living/carbon/human/verb/yank_out_object() +mob/living/carbon/human/yank_out_object() + set category = "Object" set name = "Yank out object" set desc = "Remove an embedded item at the cost of bleeding and pain." - set category = "Object" + set src in view(1) if(!isliving(usr) || usr.next_move > world.time) return usr.next_move = world.time + 20 - var/list/valid_objects = get_visible_implants(1) + if(usr.stat == 1) + usr << "You are unconcious and cannot do that!" + return + + if(usr.restrained()) + usr << "You are restrained and cannot do that!" + return + + var/list/valid_objects = list() var/datum/organ/external/affected = null + var/mob/living/carbon/human/S = src + var/mob/living/carbon/human/U = usr + var/self = null + + if(S == U) + self = 1 // Removing object from yourself. + + valid_objects = get_visible_implants(1) if(!valid_objects.len) - src << "You have nothing stuck in your wounds that is large enough to remove without surgery." - return - - if(src.stat == 1) - src << "You are unconcious and cannot do that!" - return - - if(src.restrained()) - src << "You are restrained and cannot do that!" + if(self) + src << "You have nothing stuck in your wounds that is large enough to remove without surgery." + else + U << "[src] has nothing stuck in their wounds that is large enough to remove without surgery." return var/obj/item/weapon/selection = input("What do you want to yank out?", "Embedded objects") in valid_objects - for(var/datum/organ/external/organ in src.organs) //Grab the organ holding the implant. Messy as Hell, TBD: fix. + for(var/datum/organ/external/organ in organs) //Grab the organ holding the implant. for(var/obj/item/weapon/O in organ.implants) if(O == selection) affected = organ + if(self) + src << "You attempt to get a good grip on the [selection] in your [affected] with bloody fingers." + else + U << "You attempt to get a good grip on the [selection] in [S]'s [affected] with bloody fingers." - src << "You attempt to get a good grip on the [selection] in your [affected] with bloody fingers." - bloody_hands(src) + if(istype(U,/mob/living/carbon/human/)) U.bloody_hands(S) - spawn(80) + if(!do_after(U, 80)) + return + + if(!selection || !affected || !S || !U) + return + if(self) visible_message("[src] rips [selection] out of their [affected] in a welter of blood.","You rip [selection] out of your [affected] in a welter of blood.") - selection.loc = get_turf(src) - affected.implants -= selection - shock_stage+=10 + else + visible_message("[usr] rips [selection] out of [src]'s [affected] in a welter of blood.","[src] rips [selection] out of your [affected] in a welter of blood.") - if(prob(10)) //I'M SO ANEMIC I COULD JUST -DIE-. - var/datum/wound/internal_bleeding/I = new (15) - affected.wounds += I - src.custom_pain("Something tears wetly in your [affected] as [selection] is pulled free!", 1) + selection.loc = get_turf(src) + affected.implants -= selection + shock_stage+=10 + + for(var/obj/item/weapon/O in pinned) + if(O == selection) + pinned -= O + if(!pinned.len) + anchored = 0 + + if(prob(10)) //I'M SO ANEMIC I COULD JUST -DIE-. + var/datum/wound/internal_bleeding/I = new (15) + affected.wounds += I + custom_pain("Something tears wetly in your [affected] as [selection] is pulled free!", 1) return 1 /mob/living/carbon/human/proc/get_visible_implants(var/class = 0) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 1cf951c53b8..78038f5c84a 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -226,15 +226,22 @@ //Embedded projectile code. if(!organ) return if(istype(used_weapon,/obj/item/weapon)) - var/obj/item/weapon/W = used_weapon + var/obj/item/weapon/W = used_weapon //Sharp objects will always embed if they do enough damage. if(damage > (5*W.w_class) && (prob(damage/W.w_class) || sharp)) //The larger it is, the harder it needs to hit to stick. - W.loc = src //Sharp objects will always embed if they do enough damage. organ.implants += W visible_message("\The [W] sticks in the wound!") W.add_blood(src) + if(ismob(W.loc)) + var/mob/living/H = W.loc + H.drop_item() + W.loc = src + else if(istype(used_weapon,/obj/item/projectile)) //We don't want to use the actual projectile item, so we spawn some shrapnel. if(prob(50) && damagetype == BRUTE) + var/obj/item/projectile/P = used_weapon var/obj/item/weapon/shard/shrapnel/S = new() + S.name = "[P.name] shrapnel" + S.desc = "[S.desc] It looks like it was fired from [P.shot_from]." S.loc = src organ.implants += S visible_message("The projectile sticks in the wound!") diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 5d8dc1055b0..0db1f949c5f 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -470,7 +470,7 @@ reagents.add_reagent("plasma", Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) toxins_alert = max(toxins_alert, 1) else if(O2_pp > vox_oxygen_max && src.dna.mutantrace=="vox") //Oxygen is toxic to vox. - var/ratio = (breath.oxygen/vox_oxygen_max) * 10 + var/ratio = (breath.oxygen/vox_oxygen_max) * 1000 adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) toxins_alert = max(toxins_alert, 1) else @@ -490,7 +490,7 @@ if( (abs(310.15 - breath.temperature) > 50) && !(COLD_RESISTANCE in mutations)) // Hot air hurts :( if(status_flags & GODMODE) return 1 //godmode - if(breath.temperature < 260.15) + if(breath.temperature < 260.15 && dna.mutantrace != "vox") //Vox are resistant to cold. if(prob(20)) src << "\red You feel your face freezing and an icicle forming in your lungs!" else if(breath.temperature > 360.15) @@ -501,10 +501,10 @@ if(-INFINITY to 120) apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Cold") fire_alert = max(fire_alert, 1) - if(120 to 200) + if(120 to 200 && dna.mutantrace != "vox") //Vox are resistant to cold. apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Cold") fire_alert = max(fire_alert, 1) - if(200 to 260) + if(200 to 260 && dna.mutantrace != "vox") //Vox are resistant to cold. apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, "head", used_weapon = "Excessive Cold") fire_alert = max(fire_alert, 1) if(360 to 400) @@ -602,7 +602,7 @@ if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE) pressure_alert = -1 else - if( !(COLD_RESISTANCE in mutations) && src.dna.mutantrace!="vox") + if( !(COLD_RESISTANCE in mutations) && src.dna.mutantrace!="vox") //Vox are resistant to pressure loss. adjustBruteLoss( LOW_PRESSURE_DAMAGE ) pressure_alert = -2 else diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 9d29d317c80..f10120d66c6 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -444,10 +444,12 @@ proc/get_damage_icon_part(damage_state, body_part) if("skrell") race_icon = 'icons/mob/human_races/r_skrell.dmi' deform_icon = 'icons/mob/human_races/r_def_skrell.dmi' - if("vox") race_icon = 'icons/mob/human_races/r_vox.dmi' deform_icon = 'icons/mob/human_races/r_def_vox.dmi' + if("kidan") + race_icon = 'icons/mob/human_races/r_kidan.dmi' + deform_icon = 'icons/mob/human_races/r_def_kidan.dmi' else race_icon = 'icons/mob/human_races/r_human.dmi' diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index 45e57a3da77..5e215b6966e 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -438,21 +438,36 @@ if(!reagents.has_reagent("inaprovaline")) adjustOxyLoss(1) Paralyse(3) + if(halloss > 100) + src << "You're in too much pain to keep going..." + for(var/mob/O in oviewers(src, null)) + O.show_message("[src] slumps to the ground, too weak to continue fighting.", 1) + Paralyse(10) + setHalLoss(99) if(paralysis) AdjustParalysis(-1) blinded = 1 stat = UNCONSCIOUS + if(halloss > 0) + adjustHalLoss(-6) else if(sleeping) + handle_dreams() + adjustHalLoss(-6) sleeping = max(sleeping-1, 0) blinded = 1 stat = UNCONSCIOUS - if( prob(10) && health ) + if( prob(10) && health && !hal_crit ) spawn(0) emote("snore") + else if(resting) + if(halloss > 0) + adjustHalLoss(-6) //CONSCIOUS else stat = CONSCIOUS + if(halloss > 0) + adjustHalLoss(-2) //Eyes if(sdisabilities & BLIND) //disabled-blind, doesn't get better on its own diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 5dcc1158545..3b0240fe39c 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -3,13 +3,113 @@ voice_name = "monkey" voice_message = "chimpers" say_message = "chimpers" - icon = 'icons/mob/monkey.dmi' icon_state = "monkey1" + icon = 'icons/mob/monkey.dmi' gender = NEUTER pass_flags = PASSTABLE update_icon = 0 ///no need to call regenerate_icon var/obj/item/weapon/card/id/wear_id = null // Fix for station bounced radios -- Skie +/mob/living/carbon/monkey/tajara + name = "farwa" + voice_name = "farwa" + voice_message = "mews" + say_message = "mews" + icon_state = "tajkey1" + +/mob/living/carbon/monkey/skrell + name = "neaera" + voice_name = "neaera" + voice_message = "squicks" + say_message = "squicks" + icon_state = "skrellkey1" +/mob/living/carbon/monkey/unathi + name = "stok" + voice_name = "stok" + voice_message = "hisses" + say_message = "hisses" + icon_state = "stok1" + +/mob/living/carbon/monkey/unathi/New() + var/datum/reagents/R = new/datum/reagents(1000) + reagents = R + R.my_atom = src + + if(name == "stok") + name = text("stok ([rand(1, 1000)])") + real_name = name + if (!(dna)) + if(gender == NEUTER) + gender = pick(MALE, FEMALE) + dna = new /datum/dna( null ) + dna.real_name = real_name + dna.uni_identity = "000000000000000000DC0000066000" + dna.struc_enzymes = "43359156756131E13763334D1C369012032164D4FE4CD61544B6C03F251B6C60A42821D26BA3B0FD6" + dna.unique_enzymes = md5(name) + dna.mutantrace = "lizard" + //////////blah + var/gendervar + if (gender == MALE) + gendervar = add_zero2(num2hex((rand(1,2049)),1), 3) + else + gendervar = add_zero2(num2hex((rand(2051,4094)),1), 3) + dna.uni_identity += gendervar + dna.uni_identity += "044" + dna.uni_identity += "C5D" + ..() +/mob/living/carbon/monkey/skrell/New() + var/datum/reagents/R = new/datum/reagents(1000) + reagents = R + R.my_atom = src + if(name == "neaera") + name = text("neaera ([rand(1, 1000)])") + real_name = name + if (!(dna)) + if(gender == NEUTER) + gender = pick(MALE, FEMALE) + dna = new /datum/dna( null ) + dna.real_name = real_name + dna.uni_identity = "000000000000000000DC0000066000" + dna.struc_enzymes = "43359156756131E13763334D1C369012032164D4FE4CD61544B6C03F251B6C60A42821D26BA3B0FD6" + dna.unique_enzymes = md5(name) + dna.mutantrace = "skrell" + //////////blah + var/gendervar + if (gender == MALE) + gendervar = add_zero2(num2hex((rand(1,2049)),1), 3) + else + gendervar = add_zero2(num2hex((rand(2051,4094)),1), 3) + dna.uni_identity += gendervar + dna.uni_identity += "01C" + dna.uni_identity += "C92" + ..() +/mob/living/carbon/monkey/tajara/New() + var/datum/reagents/R = new/datum/reagents(1000) + reagents = R + R.my_atom = src + + if(name == "farwa") + name = text("farwa ([rand(1, 1000)])") + real_name = name + if (!(dna)) + if(gender == NEUTER) + gender = pick(MALE, FEMALE) + dna = new /datum/dna( null ) + dna.real_name = real_name + dna.uni_identity = "000000000000000000DC0000066000" + dna.struc_enzymes = "43359156756131E13763334D1C369012032164D4FE4CD61544B6C03F251B6C60A42821D26BA3B0FD6" + dna.unique_enzymes = md5(name) + dna.mutantrace = "tajaran" + //////////blah + var/gendervar + if (gender == MALE) + gendervar = add_zero2(num2hex((rand(1,2049)),1), 3) + else + gendervar = add_zero2(num2hex((rand(2051,4094)),1), 3) + dna.uni_identity += gendervar + dna.uni_identity += "0A0" + dna.uni_identity += "E00" + ..() /mob/living/carbon/monkey/New() var/datum/reagents/R = new/datum/reagents(1000) diff --git a/code/modules/mob/living/carbon/monkey/update_icons.dm b/code/modules/mob/living/carbon/monkey/update_icons.dm index 9dd3e416410..c6895db0070 100644 --- a/code/modules/mob/living/carbon/monkey/update_icons.dm +++ b/code/modules/mob/living/carbon/monkey/update_icons.dm @@ -28,12 +28,20 @@ update_hud() lying_prev = lying //so we don't update overlays for lying/standing unless our stance changes again overlays.Cut() + var/ico = "monkey" + switch(src.dna.mutantrace) //On monkey spawn, check the DNA of the mob. If alien, change to appropriate alien monkey sprite + if("tajaran") + ico = "tajkey" + if("lizard") + ico = "stok" + if("skrell") + icon_state = "skrellkey" if(lying) - icon_state = "monkey0" + icon_state = ico + "0" for(var/image/I in overlays_lying) overlays += I else - icon_state = "monkey1" + icon_state = ico + "1" for(var/image/I in overlays_standing) overlays += I diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 78b04c9245d..333cc07380b 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -28,7 +28,7 @@ return 1 -/mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/def_zone = null, var/blocked = 0, var/halloss = 0) +/mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/halloss = 0, var/def_zone = null, var/blocked = 0) if(blocked >= 2) return 0 if(brute) apply_damage(brute, BRUTE, def_zone, blocked) if(burn) apply_damage(burn, BURN, def_zone, blocked) @@ -64,7 +64,7 @@ return 1 -/mob/living/proc/apply_effects(var/stun = 0, var/weaken = 0, var/paralyze = 0, var/irradiate = 0, var/stutter = 0, var/eyeblur = 0, var/drowsy = 0, var/blocked = 0, var/agony = 0) +/mob/living/proc/apply_effects(var/stun = 0, var/weaken = 0, var/paralyze = 0, var/irradiate = 0, var/stutter = 0, var/eyeblur = 0, var/drowsy = 0, var/agony = 0, var/blocked = 0) if(blocked >= 2) return 0 if(stun) apply_effect(stun, STUN, blocked) if(weaken) apply_effect(weaken, WEAKEN, blocked) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index a3bc884c171..4107b30d877 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -61,7 +61,7 @@ P.on_hit(src, absorb) return absorb -/mob/living/hitby(atom/movable/AM as mob|obj,var/speed)//Standardization and logging -Sieve +/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = 5)//Standardization and logging -Sieve if(istype(AM,/obj/)) var/obj/O = AM var/zone = ran_zone("chest",75)//Hits a random part of the body, geared towards the chest @@ -73,11 +73,49 @@ var/armor = run_armor_check(zone, "melee", "Your armor has protected your [zone].", "Your armor has softened hit to your [zone].") if(armor < 2) apply_damage(O.throwforce*(speed/5), dtype, zone, armor, O.sharp, O) + if(!O.fingerprintslast) return + var/client/assailant = directory[ckey(O.fingerprintslast)] if(assailant && assailant.mob && istype(assailant.mob,/mob)) var/mob/M = assailant.mob src.attack_log += text("\[[time_stamp()]\] Has been hit with [O], last touched by [M.name] ([assailant.ckey])") M.attack_log += text("\[[time_stamp()]\] Hit [src.name] ([src.ckey]) with [O]") log_attack("[src.name] ([src.ckey]) was hit by [O], last touched by [M.name] ([assailant.ckey])") + + // Begin BS12 momentum-transfer code. + + if(speed >= 20) + var/obj/item/weapon/W = O + var/momentum = speed/2 + var/dir = get_dir(M,src) + visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!") + + src.throw_at(get_edge_target_turf(src,dir),1,momentum) + + if(near_wall(dir,2) && W.w_class >= 3 && W.sharp) //If they're close to a wall and the projectile is suitable. + visible_message("[src] is pinned to the wall by [O]!","You are pinned to the wall by [O]!") + if(!istype(src,/mob/living/carbon/human)) + O.loc = src + src.embedded += O + src.anchored = 1 + src.pinned += O + else + src.anchored = 1 + src.pinned += O + + +/mob/living/proc/near_wall(var/direction,var/distance=1) + var/turf/T = get_step(get_turf(src),direction) + var/i = 1 + while(i>0 && i<=distance) + if(T.density) //Turf is a wall! + return 1 + i++ + T = get_step(T,direction) + + return 0 + + +// End BS12 momentum-transfer code. \ No newline at end of file diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 19d94b42f5a..8d76b47513c 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -24,7 +24,6 @@ //Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects. var/incorporeal_move = 0 //0 is off, 1 is normal, 2 is for ninjas. - var/t_plasma = null var/t_oxygen = null var/t_sl_gas = null diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 420e20a1b92..838187f62ed 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -19,6 +19,7 @@ var/list/department_radio_keys = list( ":j" = "tajaran", "#j" = "tajaran", ".j" = "tajaran", ":o" = "soghun", "#o" = "soghun", ".o" = "soghun", ":v" = "vox", "#v" = "vox", ".v" = "vox", + ":q" = "kidan", "#q" = "kidan", ".q" = "kidan", ":R" = "right hand", "#R" = "right hand", ".R" = "right hand", ":L" = "left hand", "#L" = "left hand", ".L" = "left hand", @@ -39,6 +40,7 @@ var/list/department_radio_keys = list( ":J" = "tajaran", "#J" = "tajaran", ".J" = "tajaran", ":O" = "soghun", "#O" = "soghun", ".O" = "soghun", ":V" = "vox", "#V" = "vox", ".V" = "vox", + ":Q" = "kidan", "#Q" = "kidan", ".Q" = "kidan", //kinda localization -- rastaf0 //same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding. @@ -188,6 +190,7 @@ var/list/department_radio_keys = list( var/is_speaking_soghun = 0 var/is_speaking_taj = 0 var/is_speaking_vox = 0 + var/is_speaking_kidan = 0 var/is_speaking_radio = 0 switch (message_mode) @@ -290,6 +293,10 @@ var/list/department_radio_keys = list( if(vox_talk_understand || universal_speak) is_speaking_vox = 1 + if ("kidan") + if(kidan_talk_understand || universal_speak) + is_speaking_kidan = 1 + if("changeling") if(mind && mind.changeling) for(var/mob/Changeling in mob_list) @@ -388,6 +395,8 @@ var/list/department_radio_keys = list( heard_a += M else if(is_speaking_vox && (M:vox_talk_understand || M:universal_speak)) heard_a += M + else if(is_speaking_kidan && (M:kidan_talk_understand || M:universal_speak)) + heard_a += M else heard_b += M else @@ -403,7 +412,7 @@ var/list/department_radio_keys = list( var/rendered = null if (length(heard_a)) - var/message_a = say_quote(message,is_speaking_soghun,is_speaking_skrell,is_speaking_taj,is_speaking_vox) + var/message_a = say_quote(message,is_speaking_soghun,is_speaking_skrell,is_speaking_taj,is_speaking_vox,is_speaking_kidan) if (italics) message_a = "[message_a]" @@ -428,7 +437,7 @@ var/list/department_radio_keys = list( message_b = voice_message else message_b = stars(message) - message_b = say_quote(message_b,is_speaking_soghun,is_speaking_skrell,is_speaking_taj,is_speaking_vox) + message_b = say_quote(message_b,is_speaking_soghun,is_speaking_skrell,is_speaking_taj,is_speaking_vox,is_speaking_kidan) if (italics) message_b = "[message_b]" diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index f7154694f7e..74bd81ca934 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -96,7 +96,7 @@ AdjustParalysis(-1) //Movement - if(!client && !stop_automated_movement && wander) + if(!client && !stop_automated_movement && wander && !anchored) if(isturf(src.loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc. turns_since_move++ if(turns_since_move >= turns_per_move) diff --git a/code/modules/mob/living/simple_animal/vox.dm b/code/modules/mob/living/simple_animal/vox.dm new file mode 100644 index 00000000000..2ea43707ba8 --- /dev/null +++ b/code/modules/mob/living/simple_animal/vox.dm @@ -0,0 +1,161 @@ +/mob/living/simple_animal/vox/armalis/ + + name = "serpentine alien" + real_name = "serpentine alien" + desc = "A one-eyed, serpentine creature, half-machine, easily nine feet from tail to beak!" + icon = 'icons/mob/vox.dmi' + icon_state = "armalis" + icon_living = "armalis" + maxHealth = 500 + health = 500 + response_harm = "slashes at the" + harm_intent_damage = 0 + melee_damage_lower = 30 + 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 + vox_talk_understand = 1 + + var/armour = null + var/amp = null + var/quills = 3 + +/mob/living/simple_animal/vox/armalis/Die() + + living_mob_list -= src + dead_mob_list += src + stat = DEAD + visible_message("\red [src] shudders violently and explodes!","\red You feel your body rupture!") + explosion(get_turf(loc), -1, -1, 3, 5) + src.gib() + return + +/mob/living/simple_animal/vox/armalis/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(O.force) + if(O.force >= 25) + var/damage = O.force + if (O.damtype == HALLOSS) + damage = 0 + health -= damage + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red \b [src] has been attacked with the [O] by [user]. ") + else + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red \b The [O] bounces harmlessly off of [src]. ") + else + usr << "\red This weapon is ineffective, it does no damage." + for(var/mob/M in viewers(src, null)) + if ((M.client && !( M.blinded ))) + M.show_message("\red [user] gently taps [src] with the [O]. ") + +/mob/living/simple_animal/vox/armalis/verb/fire_quill(mob/target as mob in oview()) + + set name = "Fire quill" + set desc = "Fires a viciously pointed quill at a high speed." + set category = "Alien" + + if(quills<=0) + return + + src << "\red You launch a razor-sharp quill at [target]!" + for(var/mob/O in oviewers()) + if ((O.client && !( O.blinded ))) + O << "\red [src] launches a razor-sharp quill at [target]!" + + var/obj/item/weapon/arrow/quill/Q = new(loc) + Q.fingerprintslast = src.ckey + Q.throw_at(target,10,20) + quills-- + + spawn(100) + src << "\red You feel a fresh quill slide into place." + quills++ + +/mob/living/simple_animal/vox/armalis/verb/message_mob() + set category = "Alien" + set name = "Commune with creature" + set desc = "Send a telepathic message to an unlucky recipient." + + var/list/targets = list() + var/target = null + var/text = null + + targets += getmobs() //Fill list, prompt user with list + target = input("Select a creature!", "Speak to creature", null, null) as null|anything in targets + text = input("What would you like to say?", "Speak to creature", null, null) + + if (!target || !text) + return + + var/mob/M = targets[target] + + if(istype(M, /mob/dead/observer) || M.stat == DEAD) + src << "Not even the armalis can speak to the dead." + return + + M << "\blue Like lead slabs crashing into the ocean, alien thoughts drop into your mind: [text]" + if(istype(M,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + if(H.dna.mutantrace == "vox") + return + H << "\red Your nose begins to bleed..." + H.drip(1) + +/mob/living/simple_animal/vox/armalis/verb/shriek() + set category = "Alien" + set name = "Shriek" + set desc = "Give voice to a psychic shriek." + +/mob/living/simple_animal/vox/armalis/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O,/obj/item/vox/armalis_armour)) + user.drop_item() + armour = O + speed = 1 + maxHealth += 200 + health += 200 + O.loc = src + visible_message("\blue [src] is quickly outfitted in [O] by [user].","\blue You quickly outfit [src] in [O].") + regenerate_icons() + return + if(istype(O,/obj/item/vox/armalis_amp)) + user.drop_item() + amp = O + O.loc = src + visible_message("\blue [src] is quickly outfitted in [O] by [user].","\blue You quickly outfit [src] in [O].") + regenerate_icons() + return + return ..() + +/mob/living/simple_animal/vox/armalis/regenerate_icons() + + overlays = list() + if(armour) + var/icon/armour = image('icons/mob/vox.dmi',"armour") + speed = 1 + overlays += armour + if(amp) + var/icon/amp = image('icons/mob/vox.dmi',"amplifier") + overlays += amp + return + +/obj/item/vox/armalis_armour + + name = "strange armour" + desc = "Hulking reinforced armour for something huge." + icon = 'icons/obj/clothing/suits.dmi' + icon_state = "armalis_armour" + item_state = "armalis_armour" + +/obj/item/vox/armalis_amp + + name = "strange lenses" + desc = "A series of metallic lenses and chains." + icon = 'icons/obj/clothing/hats.dmi' + icon_state = "amp" + item_state = "amp" \ No newline at end of file diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 253e4ee43dc..02ea1aa4e7f 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -583,24 +583,29 @@ var/list/slot_equipment_priority = list( \ pulling = null /mob/proc/start_pulling(var/atom/movable/AM) + if ( !AM || !usr || src==AM || !isturf(src.loc) ) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort! return - if (!( AM.anchored )) - if(pulling) - var/pulling_old = pulling - stop_pulling() - // Are we pulling the same thing twice? Just stop pulling. - if(pulling_old == AM) - return - src.pulling = AM - AM.pulledby = src - if(ismob(AM)) - var/mob/M = AM - if(!iscarbon(src)) - M.LAssailant = null - else - M.LAssailant = usr + if (AM.anchored) + return + + var/mob/M = AM + if(ismob(AM)) + if(!iscarbon(src)) + M.LAssailant = null + else + M.LAssailant = usr + return + + if(pulling) + var/pulling_old = pulling + stop_pulling() + // Are we pulling the same thing twice? Just stop pulling. + if(pulling_old == AM) + return + src.pulling = AM + AM.pulledby = src /mob/proc/can_use_hands() return @@ -888,3 +893,66 @@ note dizziness decrements automatically in the mob's Life() proc. /mob/proc/flash_weak_pain() flick("weak_pain",pain) + +mob/verb/yank_out_object() + set category = "Object" + set name = "Yank out object" + set desc = "Remove an embedded item at the cost of bleeding and pain." + set src in view(1) + + if(!isliving(usr) || usr.next_move > world.time) + return + usr.next_move = world.time + 20 + + if(usr.stat == 1) + usr << "You are unconcious and cannot do that!" + return + + if(usr.restrained()) + usr << "You are restrained and cannot do that!" + return + + var/mob/S = src + var/mob/U = usr + var/list/valid_objects = list() + var/self = null + + if(S == U) + self = 1 // Removing object from yourself. + + for(var/obj/item/weapon/W in embedded) + if(W.w_class >= 2) + valid_objects += W + + if(!valid_objects.len) + if(self) + src << "You have nothing stuck in your body that is large enough to remove." + else + U << "[src] has nothing stuck in their wounds that is large enough to remove." + return + + var/obj/item/weapon/selection = input("What do you want to yank out?", "Embedded objects") in valid_objects + + if(self) + src << "You attempt to get a good grip on the [selection] in your body." + else + U << "You attempt to get a good grip on the [selection] in [S]'s body." + + if(!do_after(U, 80)) + return + if(!selection || !S || !U) + return + + if(self) + visible_message("[src] rips [selection] out of their body.","You rip [selection] out of your body.") + else + visible_message("[usr] rips [selection] out of [src]'s body.","[src] rips [selection] out of your body.") + + selection.loc = get_turf(src) + + for(var/obj/item/weapon/O in pinned) + if(O == selection) + pinned -= O + if(!pinned.len) + anchored = 0 + return 1 diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 9715e6ed20c..0a41d0d60ce 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -85,6 +85,8 @@ var/lastpuke = 0 var/unacidable = 0 var/small = 0 + var/list/pinned = list() //List of things pinning this creature to walls (see living_defense.dm) + var/list/embedded = list() //Embedded items, since simple mobs don't have organs. var/name_archive //For admin things like possession @@ -206,12 +208,13 @@ //Whether or not mobs can understand other mobtypes. These stay in /mob so that ghosts can hear everything. var/universal_speak = 0 // Set to 1 to enable the mob to speak to everyone -- TLE - var/robot_talk_understand = 0 - var/alien_talk_understand = 0 - var/tajaran_talk_understand = 0 - var/soghun_talk_understand = 0 - var/skrell_talk_understand = 0 - var/vox_talk_understand = 0 + var/robot_talk_understand = 0 + var/alien_talk_understand = 0 + var/tajaran_talk_understand = 0 + var/soghun_talk_understand = 0 + var/skrell_talk_understand = 0 + var/vox_talk_understand = 0 + var/kidan_talk_understand = 0 var/has_limbs = 1 //Whether this mob have any limbs he can move with var/can_stand = 1 //Whether this mob have ability to stand diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index cec9b06861a..80d55c0a041 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -256,7 +256,6 @@ if(!mob.canmove) return - //if(istype(mob.loc, /turf/space) || (mob.flags & NOGRAV)) // if(!mob.Process_Spacemove(0)) return 0 @@ -279,6 +278,10 @@ src << "\blue You're restrained! You can't move!" return 0 + if(mob.pinned.len) + src << "\blue You're pinned to a wall by [mob.pinned[1]]!" + return 0 + move_delay = world.time//set move delay mob.last_move_intent = world.time + 10 switch(mob.m_intent) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 686007c7173..7f1dbc9f31a 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -349,10 +349,10 @@ if(is_alien_whitelisted(src, "Skrell"|| !config.usealienwhitelist)) new_character.dna.mutantrace = "skrell" new_character.skrell_talk_understand = 1 - if(client.prefs.species == "Vox") - if(is_alien_whitelisted(src, "Vox"|| !config.usealienwhitelist)) - new_character.dna.mutantrace = "vox" - new_character.vox_talk_understand = 1 + if(client.prefs.species == "Kidan") + if(is_alien_whitelisted(src, "Kidan"|| !config.usealienwhitelist)) + new_character.dna.mutantrace = "kidan" + new_character.kidan_talk_understand = 1 if(ticker.random_players) new_character.gender = pick(MALE, FEMALE) diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index f7c965d2fdf..36cf966566d 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -144,9 +144,10 @@ datum/preferences icobase = 'icons/mob/human_races/r_lizard.dmi' if("Skrell") icobase = 'icons/mob/human_races/r_skrell.dmi' - if("Vox") icobase = 'icons/mob/human_races/r_vox.dmi' + if("Kidan") + icobase = 'icons/mob/human_races/r_kidan.dmi' else icobase = 'icons/mob/human_races/r_human.dmi' diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 4d4baf0ba18..9a321f20382 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -285,7 +285,6 @@ icon_state = "hair_e" gender = MALE // turnoff! - bald name = "Bald" icon_state = "bald" @@ -306,7 +305,7 @@ name = "Shaved" icon_state = "bald" gender = NEUTER - species_allowed = list("Human","Unathi","Tajaran","Skrell","Vox") + species_allowed = list("Human","Unathi","Tajaran","Skrell","Vox","Kidan") watson name = "Watson Mustache" @@ -484,7 +483,7 @@ species_allowed = list("Tajaran") taj_ears_spiky - name = "Tajara Spiky" + name = "Tajara Spiky" icon_state = "hair_tajspiky" species_allowed = list("Tajaran") diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index 9f3660eb7c5..2ed7f47a101 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -69,7 +69,7 @@ return 1 return 0 -/mob/proc/say_quote(var/text,var/is_speaking_soghun,var/is_speaking_skrell,var/is_speaking_tajaran,var/is_speaking_vox) +/mob/proc/say_quote(var/text,var/is_speaking_soghun,var/is_speaking_skrell,var/is_speaking_tajaran,var/is_speaking_vox,var/is_speaking_kidan) if(!text) return "says, \"...\""; //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code //tcomms code is still runtiming somewhere here @@ -81,7 +81,9 @@ if (is_speaking_tajaran) return "mrowls, \"[text]\""; if (is_speaking_vox) - return "chirps, \"[text]\""; + return "shrieks, \"[text]\""; + if (is_speaking_kidan) + return "chitters, \"[text]\""; //Needs Virus2 // if (src.disease_symptoms & DISEASE_HOARSE) // return "rasps, \"[text]\""; diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 9e3ed4b3a11..0da452cd318 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -20,29 +20,104 @@ flick("h2monkey", animation) sleep(48) //animation = null - var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey( loc ) - del(animation) - O.name = "monkey" - O.dna = dna - dna = null - O.dna.uni_identity = "00600200A00E0110148FC01300B009" - //O.dna.struc_enzymes = "0983E840344C39F4B059D5145FC5785DC6406A4BB8" - O.dna.struc_enzymes = "[copytext(O.dna.struc_enzymes,1,1+3*(STRUCDNASIZE-1))]BB8" - O.loc = loc - O.viruses = viruses - viruses = list() - for(var/datum/disease/D in O.viruses) - D.affected_mob = O + var/mob/living/carbon/monkey/O = null + + switch(dna.mutantrace) + if("tajara") + O = new /mob/living/carbon/monkey/tajara( loc ) + O.name = "farwa" + O.dna = dna + dna = null + O.dna.uni_identity = "000000000000000000DC00000660004DA0A0E00" + //O.dna.struc_enzymes = "0983E840344C39F4B059D5145FC5785DC6406A4BB8" + O.dna.struc_enzymes = "[copytext(O.dna.struc_enzymes,1,1+3*(STRUCDNASIZE-1))]BB8" + O.loc = loc + O.viruses = viruses + viruses = list() + for(var/datum/disease/D in O.viruses) + D.affected_mob = O + + if (client) + client.mob = O + if(mind) + mind.transfer_to(O) + O << "You are now a farwa. " + O.a_intent = "hurt" + spawn(0)//To prevent the proc from returning null. + del(src) + del(animation) + if("lizard") + O = new /mob/living/carbon/monkey/unathi( loc ) + O.name = "stok" + O.dna = dna + dna = null + O.dna.uni_identity = "000000000000000000DC00000660002A8044C5D" + //O.dna.struc_enzymes = "0983E840344C39F4B059D5145FC5785DC6406A4BB8" + O.dna.struc_enzymes = "[copytext(O.dna.struc_enzymes,1,1+3*(STRUCDNASIZE-1))]BB8" + O.loc = loc + O.viruses = viruses + viruses = list() + for(var/datum/disease/D in O.viruses) + D.affected_mob = O + + if (client) + client.mob = O + if(mind) + mind.transfer_to(O) + O << "You are now a stok. " + O.a_intent = "hurt" + spawn(0)//To prevent the proc from returning null. + del(src) + del(animation) + if("skrell") + O = new /mob/living/carbon/monkey/unathi( loc ) + O.name = "neaera" + O.dna = dna + dna = null + O.dna.uni_identity = "000000000000000000DC00000660002A8044C5D" + //O.dna.struc_enzymes = "0983E840344C39F4B059D5145FC5785DC6406A4BB8" + O.dna.struc_enzymes = "[copytext(O.dna.struc_enzymes,1,1+3*(STRUCDNASIZE-1))]BB8" + O.loc = loc + O.viruses = viruses + viruses = list() + for(var/datum/disease/D in O.viruses) + D.affected_mob = O + + if (client) + client.mob = O + if(mind) + mind.transfer_to(O) + O << "You are now a neaera. " + O.a_intent = "hurt" + spawn(0)//To prevent the proc from returning null. + del(src) + del(animation) + else + O = new /mob/living/carbon/monkey( loc ) + O.name = "monkey" + O.dna = dna + dna = null + O.dna.uni_identity = "00600200A00E0110148FC01300B009" + //O.dna.struc_enzymes = "0983E840344C39F4B059D5145FC5785DC6406A4BB8" + O.dna.struc_enzymes = "[copytext(O.dna.struc_enzymes,1,1+3*(STRUCDNASIZE-1))]BB8" + O.loc = loc + O.viruses = viruses + viruses = list() + for(var/datum/disease/D in O.viruses) + D.affected_mob = O + + if (client) + client.mob = O + if(mind) + mind.transfer_to(O) + O << "You are now a monkey." + O.a_intent = "hurt" + spawn(0)//To prevent the proc from returning null. + del(src) + del(animation) + - if (client) - client.mob = O - if(mind) - mind.transfer_to(O) - O.a_intent = "hurt" - O << "You are now a monkey." - spawn(0)//To prevent the proc from returning null. - del(src) return O /mob/new_player/AIize() diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index d166dccd38c..5e1fba994c7 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -740,9 +740,10 @@ obj/item/weapon/organ/New(loc, mob/living/carbon/human/H) base = new('icons/mob/human_races/r_lizard.dmi') if("skrell") base = new('icons/mob/human_races/r_skrell.dmi') - if("vox") base = new('icons/mob/human_races/r_vox.dmi') + if("kidan") + base = new('icons/mob/human_races/r_kidan.dmi') else base = new('icons/mob/human_races/r_human.dmi') diff --git a/code/modules/projectiles/guns/projectile/bow.dm b/code/modules/projectiles/guns/projectile/bow.dm index a052f198422..aa113e86599 100644 --- a/code/modules/projectiles/guns/projectile/bow.dm +++ b/code/modules/projectiles/guns/projectile/bow.dm @@ -6,13 +6,22 @@ icon_state = "bolt" item_state = "bolt" flags = FPRINT | TABLEPASS - throwforce = 12 - w_class = 2.0 + throwforce = 8 + w_class = 3.0 sharp = 1 -/obj/item/weapon/arrow/proc/removed() //Helper for metal rods falling apart.. +/obj/item/weapon/arrow/proc/removed() //Helper for metal rods falling apart. return +/obj/item/weapon/arrow/quill + + name = "vox quill" + desc = "A wickedly barbed quill from some bizarre animal." + icon = 'icons/obj/weapons.dmi' + icon_state = "quill" + item_state = "quill" + throwforce = 5 + /obj/item/weapon/arrow/rod name = "metal rod" @@ -20,7 +29,7 @@ icon_state = "metal-rod" /obj/item/weapon/arrow/rod/removed(mob/user) - if(throwforce == 20) // The rod has been superheated - we don't want it to be useable when removed from the bow. + if(throwforce == 15) // The rod has been superheated - we don't want it to be useable when removed from the bow. user << "[src] shatters into a scattering of overstressed metal shards as it leaves the crossbow." var/obj/item/weapon/shard/shrapnel/S = new() S.loc = get_turf(src) @@ -33,7 +42,7 @@ icon = 'icons/obj/weapons.dmi' icon_state = "crossbow" item_state = "crossbow-solid" - w_class = 4.0 + w_class = 5.0 flags = FPRINT | TABLEPASS | CONDUCT | USEDELAY slot_flags = SLOT_BELT | SLOT_BACK @@ -59,14 +68,16 @@ var/obj/item/stack/rods/R = W R.use(1) arrow = new /obj/item/weapon/arrow/rod(src) + arrow.fingerprintslast = src.fingerprintslast arrow.loc = src + icon_state = "crossbow-nocked" user.visible_message("[user] haphazardly jams [arrow] into [src].","You jam [arrow] into [src].") if(cell) if(cell.charge >= 500) user << "[arrow] plinks and crackles as it begins to glow red-hot." - arrow.throwforce = 20 + arrow.throwforce = 15 arrow.icon_state = "metal-rod-superheated" - + cell.charge -= 500 return if(istype(W, /obj/item/weapon/cell)) @@ -78,7 +89,7 @@ if(arrow) if(istype(arrow,/obj/item/weapon/arrow/rod) && cell.charge >= 500) user << "[arrow] plinks and crackles as it begins to glow red-hot." - arrow.throwforce = 20 + arrow.throwforce = 15 arrow.icon_state = "metal-rod-superheated" cell.charge -= 500 else @@ -156,6 +167,10 @@ else if(target == user) return + if(!tension) + user << "You haven't drawn back the bolt!" + return 0 + if (!arrow) user << "You have no arrow nocked to [src]!" return 0 diff --git a/code/modules/projectiles/guns/projectile/pneumatic.dm b/code/modules/projectiles/guns/projectile/pneumatic.dm index 7d2f0c3b498..fe6c2651bd5 100644 --- a/code/modules/projectiles/guns/projectile/pneumatic.dm +++ b/code/modules/projectiles/guns/projectile/pneumatic.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/gun.dmi' icon_state = "pneumatic" item_state = "pneumatic" - w_class = 4.0 + w_class = 5.0 flags = FPRINT | TABLEPASS | CONDUCT | USEDELAY slot_flags = SLOT_BELT max_w_class = 3 diff --git a/code/modules/projectiles/projectile/change.dm b/code/modules/projectiles/projectile/change.dm index 2b4b4c457d8..604cf5428b9 100644 --- a/code/modules/projectiles/projectile/change.dm +++ b/code/modules/projectiles/projectile/change.dm @@ -74,7 +74,7 @@ var/mob/living/carbon/human/H = new_mob if(H.dna) - H.dna.mutantrace = pick("lizard","tajaran","skrell","golem","slime","plant","vox",4;"") + H.dna.mutantrace = pick("lizard","tajaran","skrell","golem","slime","plant","vox","kidan",4;"") else return diff --git a/code/modules/reagents/reagent_containers/food/snacks.dm b/code/modules/reagents/reagent_containers/food/snacks.dm index a5985618ec5..f15c3410947 100644 --- a/code/modules/reagents/reagent_containers/food/snacks.dm +++ b/code/modules/reagents/reagent_containers/food/snacks.dm @@ -1367,6 +1367,126 @@ icon_state = "monkeycubewrap" wrapped = 1 +/obj/item/weapon/reagent_containers/food/snacks/farwacube + name = "farwa cube" + desc = "Just add water!" + icon_state = "monkeycube" + bitesize = 12 + var/wrapped = 0 + + New() + ..() + reagents.add_reagent("nutriment",10) + + afterattack(obj/O as obj, mob/user as mob) + if(istype(O,/obj/structure/sink) && !wrapped) + user << "You place [name] under a stream of water..." + loc = get_turf(O) + return Expand() + ..() + + attack_self(mob/user as mob) + if(wrapped) + Unwrap(user) + + proc/Expand() + for(var/mob/M in viewers(src,7)) + M << "\red The farwa cube expands!" + new /mob/living/carbon/monkey/tajara(get_turf(src)) + del(src) + + proc/Unwrap(mob/user as mob) + icon_state = "monkeycube" + desc = "Just add water!" + user << "You unwrap the cube." + wrapped = 0 + return + +/obj/item/weapon/reagent_containers/food/snacks/stokcube + name = "stok cube" + desc = "Just add water!" + icon_state = "monkeycube" + bitesize = 12 + var/wrapped = 0 + + New() + ..() + reagents.add_reagent("nutriment",10) + + afterattack(obj/O as obj, mob/user as mob) + if(istype(O,/obj/structure/sink) && !wrapped) + user << "You place [name] under a stream of water..." + loc = get_turf(O) + return Expand() + ..() + + attack_self(mob/user as mob) + if(wrapped) + Unwrap(user) + + proc/Expand() + for(var/mob/M in viewers(src,7)) + M << "\red The stok cube expands!" + new /mob/living/carbon/monkey/unathi(get_turf(src)) + del(src) + + proc/Unwrap(mob/user as mob) + icon_state = "monkeycube" + desc = "Just add water!" + user << "You unwrap the cube." + wrapped = 0 + return +/obj/item/weapon/reagent_containers/food/snacks/neaeracube + name = "neaera cube" + desc = "Just add water!" + icon_state = "monkeycube" + bitesize = 12 + var/wrapped = 0 + + New() + ..() + reagents.add_reagent("nutriment",10) + + afterattack(obj/O as obj, mob/user as mob) + if(istype(O,/obj/structure/sink) && !wrapped) + user << "You place [name] under a stream of water..." + loc = get_turf(O) + return Expand() + ..() + + attack_self(mob/user as mob) + if(wrapped) + Unwrap(user) + + proc/Expand() + for(var/mob/M in viewers(src,7)) + M << "\red The neaera cube expands!" + new /mob/living/carbon/monkey/skrell(get_turf(src)) + del(src) + + proc/Unwrap(mob/user as mob) + icon_state = "monkeycube" + desc = "Just add water!" + user << "You unwrap the cube." + wrapped = 0 + return + +/obj/item/weapon/reagent_containers/food/snacks/neaeracube/wrapped + desc = "Still wrapped in some paper." + icon_state = "monkeycubewrap" + wrapped = 1 +/obj/item/weapon/reagent_containers/food/snacks/stokcube/wrapped + desc = "Still wrapped in some paper." + icon_state = "monkeycubewrap" + wrapped = 1 + + +/obj/item/weapon/reagent_containers/food/snacks/farwacube/wrapped + desc = "Still wrapped in some paper." + icon_state = "monkeycubewrap" + wrapped = 1 + + /obj/item/weapon/reagent_containers/food/snacks/spellburger name = "Spell Burger" diff --git a/code/stylesheet.dm b/code/stylesheet.dm index 902160e9ef9..5eb0ec9991a 100644 --- a/code/stylesheet.dm +++ b/code/stylesheet.dm @@ -56,6 +56,7 @@ h1.alert, h2.alert {color: #000000;} .skrell {color: #00CED1;} .soghun {color: #228B22;} .vox {color: #AA00AA;} +.kidan {color: #cc9900;} .say_quote {font-family: Georgia, Verdana, sans-serif;} .interface {color: #330033;} diff --git a/icons/effects/footprints.dmi b/icons/effects/footprints.dmi index ede9c8e17d6..b849de00fff 100644 Binary files a/icons/effects/footprints.dmi and b/icons/effects/footprints.dmi differ diff --git a/icons/mob/feet.dmi b/icons/mob/feet.dmi index 81c75323041..d994f6a63c1 100644 Binary files a/icons/mob/feet.dmi and b/icons/mob/feet.dmi differ diff --git a/icons/mob/hands.dmi b/icons/mob/hands.dmi index 44dfaabf477..6e2862349be 100644 Binary files a/icons/mob/hands.dmi and b/icons/mob/hands.dmi differ diff --git a/icons/mob/human_races/r_def_kidan.dmi b/icons/mob/human_races/r_def_kidan.dmi new file mode 100644 index 00000000000..0d7b050b7ce Binary files /dev/null and b/icons/mob/human_races/r_def_kidan.dmi differ diff --git a/icons/mob/human_races/r_def_vox.dmi b/icons/mob/human_races/r_def_vox.dmi index 4dad2129d50..2024f52583b 100644 Binary files a/icons/mob/human_races/r_def_vox.dmi and b/icons/mob/human_races/r_def_vox.dmi differ diff --git a/icons/mob/human_races/r_kidan.dmi b/icons/mob/human_races/r_kidan.dmi new file mode 100644 index 00000000000..c8be5e21ed1 Binary files /dev/null and b/icons/mob/human_races/r_kidan.dmi differ diff --git a/icons/mob/human_races/r_vox.dmi b/icons/mob/human_races/r_vox.dmi index 4dad2129d50..6aada937c25 100644 Binary files a/icons/mob/human_races/r_vox.dmi and b/icons/mob/human_races/r_vox.dmi differ diff --git a/icons/mob/monkey.dmi b/icons/mob/monkey.dmi index 437ba085b15..75ce4c4596d 100644 Binary files a/icons/mob/monkey.dmi and b/icons/mob/monkey.dmi differ diff --git a/icons/mob/vox.dmi b/icons/mob/vox.dmi new file mode 100644 index 00000000000..6abba5c9e03 Binary files /dev/null and b/icons/mob/vox.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index 9a8ee374dd3..8160eefd314 100644 Binary files a/icons/obj/clothing/gloves.dmi and b/icons/obj/clothing/gloves.dmi differ diff --git a/icons/obj/clothing/shoes.dmi b/icons/obj/clothing/shoes.dmi index 6134bd60686..66f08d71d48 100644 Binary files a/icons/obj/clothing/shoes.dmi and b/icons/obj/clothing/shoes.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 29487a42863..cf9c6d511d6 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/cryobag.dmi b/icons/obj/cryobag.dmi index fe543fad642..68255b8b2c3 100644 Binary files a/icons/obj/cryobag.dmi and b/icons/obj/cryobag.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 1e9f1c1efb4..003bf5c9f10 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi index ecce9fa6aae..c15523cd40a 100644 Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ