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/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/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/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/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 75ead11e4c5..e6a76d88e8e 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -792,9 +792,6 @@ 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 Vox and admins - new_species += "Vox" - whitelisted = 1 if(is_alien_whitelisted(user, "Kidan")) // Check for Kidan and admins new_species += "Kidan" whitelisted = 1 @@ -806,7 +803,6 @@ datum/preferences 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 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/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 77811f9c81f..05f4b222a8e 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 @@ -1119,51 +1119,107 @@ del(feet_blood_DNA) return 1 -/mob/living/carbon/human/verb/yank_out_object() +mob/living/carbon/human/verb/yank_out_object() + set category = "IC" 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 - if(!valid_objects.len) - src << "You have nothing stuck in your wounds that is large enough to remove without surgery." - return + if(S == U) // Removing something from yourself. + valid_objects = get_visible_implants(1) - if(src.stat == 1) - src << "You are unconcious and cannot do that!" - return + if(!valid_objects.len) + src << "You have nothing stuck in your wounds that is large enough to remove without surgery." + return - if(src.restrained()) - src << "You are restrained and cannot do that!" - return + var/obj/item/weapon/selection = input("What do you want to yank out?", "Embedded objects") in valid_objects - 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 organs) //Grab the organ holding the implant. Messy as Hell, TBD: fix. + for(var/obj/item/weapon/O in organ.implants) + if(O == selection) + affected = organ - for(var/datum/organ/external/organ in src.organs) //Grab the organ holding the implant. Messy as Hell, TBD: fix. - for(var/obj/item/weapon/O in organ.implants) - if(O == selection) - affected = organ + src << "You attempt to get a good grip on the [selection] in your [affected] with bloody fingers." + bloody_hands(S) - src << "You attempt to get a good grip on the [selection] in your [affected] with bloody fingers." - bloody_hands(src) + if(!do_after(U, 80)) + return + + if(!selection || !affected || !S || !U) + return - spawn(80) 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 + for(var/obj/item/weapon/O in pinned) + if(O == selection) + pinned -= O + anchored = 0 + 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) - return 1 + custom_pain("Something tears wetly in your [affected] as [selection] is pulled free!", 1) + return 1 + + else // Removing something from someone else. + valid_objects = src.get_visible_implants(1) + + if(!valid_objects.len) + 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/obj/item/weapon/O in organ.implants) + if(O == selection) + affected = organ + + U << "You attempt to get a good grip on the [selection] in [S]'s [affected] with bloody fingers." + U.bloody_hands(S) + + if(!do_after(U, 80)) + return + + if(!selection || !affected || !S || !U) + return + + 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.") + selection.loc = get_turf(usr) + affected.implants -= selection + src.shock_stage+=10 + + for(var/obj/item/weapon/O in S.pinned) + if(O == selection) + S.pinned -= O + S.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/living_defense.dm b/code/modules/mob/living/living_defense.dm index a3bc884c171..f7b2caecae3 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,43 @@ 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]!") + 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/simple_animal/vox.dm b/code/modules/mob/living/simple_animal/vox.dm new file mode 100644 index 00000000000..e73249f2bc8 --- /dev/null +++ b/code/modules/mob/living/simple_animal/vox.dm @@ -0,0 +1,54 @@ +/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 = "flails ineffectually 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 + +/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" + + 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 + Q.throw_at(target,10,15) \ No newline at end of file diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 253e4ee43dc..6e9beda1bad 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -583,24 +583,31 @@ 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 + if (M.pinned.len) + usr << "They're pinned, gtfo." + 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 diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 8f1868b7168..c83909fd8a9 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -85,6 +85,7 @@ 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/name_archive //For admin things like possession 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 f2859af519d..7f1dbc9f31a 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -349,12 +349,8 @@ 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, "Vox"|| !config.usealienwhitelist)) + if(is_alien_whitelisted(src, "Kidan"|| !config.usealienwhitelist)) new_character.dna.mutantrace = "kidan" new_character.kidan_talk_understand = 1 diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index a0b765d8d43..2ed7f47a101 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -81,7 +81,7 @@ 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 diff --git a/code/modules/projectiles/guns/projectile/bow.dm b/code/modules/projectiles/guns/projectile/bow.dm index a052f198422..6a8c3510f8e 100644 --- a/code/modules/projectiles/guns/projectile/bow.dm +++ b/code/modules/projectiles/guns/projectile/bow.dm @@ -7,12 +7,21 @@ item_state = "bolt" flags = FPRINT | TABLEPASS throwforce = 12 - w_class = 2.0 + w_class = 3.0 sharp = 1 /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/mob/vox.dmi' + icon_state = "quill" + item_state = "quill" + throwforce = 15 + /obj/item/weapon/arrow/rod name = "metal rod" @@ -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.icon_state = "metal-rod-superheated" - + cell.charge -= 500 return if(istype(W, /obj/item/weapon/cell)) @@ -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/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_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_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/vox.dmi b/icons/mob/vox.dmi new file mode 100644 index 00000000000..6f0172bba70 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