Merge remote-tracking branch 'citadel/master' into actual_ghost_newscasters

This commit is contained in:
kevinz000
2020-02-10 04:29:22 -07:00
227 changed files with 7890 additions and 7395 deletions
+1 -1
View File
@@ -214,4 +214,4 @@ GLOBAL_VAR(antag_prototypes)
var/datum/browser/panel = new(usr, "traitorpanel", "", 600, 600)
panel.set_content(out)
panel.open()
return
return
@@ -20,6 +20,7 @@ GLOBAL_LIST_EMPTY(antagonists)
var/show_in_antagpanel = TRUE //This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind
var/antagpanel_category = "Uncategorized" //Antagpanel will display these together, REQUIRED
var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type
var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute) // Quirks that will be removed upon gaining this antag. Pacifist and mute are default.
/datum/antagonist/New()
GLOB.antagonists += src
@@ -70,6 +71,7 @@ GLOBAL_LIST_EMPTY(antagonists)
greet()
apply_innate_effects()
give_antag_moodies()
remove_blacklisted_quirks()
if(is_banned(owner.current) && replace_banned)
replace_banned_player()
@@ -117,6 +119,18 @@ GLOBAL_LIST_EMPTY(antagonists)
return
SEND_SIGNAL(owner.current, COMSIG_CLEAR_MOOD_EVENT, "antag_moodlet")
/datum/antagonist/proc/remove_blacklisted_quirks()
var/mob/living/L = owner.current
if(istype(L))
var/list/my_quirks = L.client?.prefs.all_quirks.Copy()
SSquirks.filter_quirks(my_quirks,blacklisted_quirks)
for(var/q in L.roundstart_quirks)
var/datum/quirk/Q = q
if(!(SSquirks.quirk_name_by_path(Q.type) in my_quirks))
if(initial(Q.antag_removal_text))
to_chat(L, "<span class='boldannounce'>[initial(Q.antag_removal_text)]</span>")
L.remove_quirk(Q.type)
//Returns the team antagonist belongs to if any.
/datum/antagonist/proc/get_team()
return
@@ -134,7 +148,7 @@ GLOBAL_LIST_EMPTY(antagonists)
if(objectives.len)
report += printobjectives(objectives)
for(var/datum/objective/objective in objectives)
if(!objective.check_completion())
if(objective.completable && !objective.check_completion())
objectives_complete = FALSE
break
+10 -4
View File
@@ -36,11 +36,17 @@
var/win = TRUE
var/objective_count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
report += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
if(objective.completable)
var/completion = objective.check_completion()
if(completion >= 1)
report += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
else if(completion <= 0)
report += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
win = FALSE
else
report += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
else
report += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
win = FALSE
report += "<B>Objective #[objective_count]</B>: [objective.explanation_text]"
objective_count++
if(win)
report += "<span class='greentext'>The [name] was successful!</span>"
@@ -31,12 +31,11 @@
if(was_running)
user.toggle_move_intent()
ADD_TRAIT(user, TRAIT_NORUNNING, "cloak of darkness")
while(bloodsuckerdatum && ContinueActive(user) || user.m_intent == MOVE_INTENT_RUN)
while(bloodsuckerdatum && ContinueActive(user))
// Pay Blood Toll (if awake)
owner.alpha = max(20, owner.alpha - min(75, 10 + 5 * level_current))
bloodsuckerdatum.AddBloodVolume(-0.2)
sleep(5) // Check every few ticks that we haven't disabled this power
// Return to Running (if you were before)
/datum/action/bloodsucker/cloak/ContinueActive(mob/living/user, mob/living/target)
if (!..())
+10 -4
View File
@@ -108,11 +108,17 @@
var/win = TRUE
var/objective_count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
if(objective.completable)
var/completion = objective.check_completion()
if(completion >= 1)
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
else if(completion <= 0)
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
win = FALSE
else
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
else
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
win = FALSE
parts += "<B>Objective #[objective_count]</B>: [objective.explanation_text]"
objective_count++
if(win)
parts += "<span class='greentext'>The blood brothers were successful!</span>"
@@ -54,8 +54,10 @@
var/honorific
if(owner.current.gender == FEMALE)
honorific = "Ms."
else
else if(owner.current.gender == MALE)
honorific = "Mr."
else
honorific = "Mx."
if(GLOB.possible_changeling_IDs.len)
changelingID = pick(GLOB.possible_changeling_IDs)
GLOB.possible_changeling_IDs -= changelingID
@@ -552,11 +554,17 @@
if(objectives.len)
var/count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</b></span>"
if(objective.completable)
var/completion = objective.check_completion()
if(completion >= 1)
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
else if(completion <= 0)
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
changelingwin = FALSE
else
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
else
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
changelingwin = 0
parts += "<B>Objective #[count]</B>: [objective.explanation_text]"
count++
if(changelingwin)
@@ -0,0 +1,19 @@
/datum/antagonist/collector
name = "Contraband Collector"
show_in_antagpanel = FALSE
show_name_in_check_antagonists = FALSE
blacklisted_quirks = list() // no blacklist, these guys are harmless
/datum/antagonist/collector/proc/forge_objectives()
var/datum/objective/hoard/collector/O = new
O.owner = owner
O.find_target()
objectives += O
/datum/antagonist/collector/on_gain()
forge_objectives()
. = ..()
/datum/antagonist/collector/greet()
to_chat(owner, "<B>You are a contraband collector!</B>")
owner.announce_objectives()
+9 -3
View File
@@ -425,10 +425,16 @@
parts += "<b>The cultists' objectives were:</b>"
var/count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='greentext'>Success!</span>"
if(objective.completable)
var/completion = objective.check_completion()
if(completion >= 1)
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
else if(completion <= 0)
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
else
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
else
parts += "<b>Objective #[count]</b>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
parts += "<B>Objective #[count]</B>: [objective.explanation_text]"
count++
if(members.len)
@@ -44,11 +44,17 @@
var/objectives_text = ""
var/count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'>Success!</span>"
if(objective.completable)
var/completion = objective.check_completion()
if(completion >= 1)
result += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
else if(completion <= 0)
result += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
win = FALSE
else
result += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
else
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
win = FALSE
result += "<B>Objective #[count]</B>: [objective.explanation_text]"
count++
result += objectives_text
+9 -16
View File
@@ -63,10 +63,10 @@
possible_targets.Cut(index,index+1)
if(is_bad_guy ^ helping_station) //kill (good-ninja + bad-guy or bad-ninja + good-guy)
var/datum/objective/assassinate/O = new /datum/objective/assassinate()
var/datum/objective/assassinate/once/O = new /datum/objective/assassinate()
O.owner = owner
O.target = M
O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]."
O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]. You may let [M.p_they()] live, if they come back from death."
objectives += O
else //protect
var/datum/objective/protect/O = new /datum/objective/protect()
@@ -74,23 +74,16 @@
O.target = M
O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm."
objectives += O
if(4) //debrain/capture
if(!possible_targets.len) continue
var/selected = rand(1,possible_targets.len)
var/datum/mind/M = possible_targets[selected]
var/is_bad_guy = possible_targets[M]
possible_targets.Cut(selected,selected+1)
if(is_bad_guy ^ helping_station) //debrain (good-ninja + bad-guy or bad-ninja + good-guy)
var/datum/objective/debrain/O = new /datum/objective/debrain()
if(4) //flavor
if(helping_station)
var/datum/objective/flavor/ninja_helping/O = new /datum/objective/flavor/ninja_helping
O.owner = owner
O.target = M
O.explanation_text = "Steal the brain of [M.current.real_name]."
O.forge_objective()
objectives += O
else //capture
var/datum/objective/capture/O = new /datum/objective/capture()
else
var/datum/objective/flavor/ninja_syndie/O = new /datum/objective/flavor/ninja_helping
O.owner = owner
O.gen_amount_goal()
O.forge_objective()
objectives += O
else
break
+2 -2
View File
@@ -7,10 +7,10 @@
/datum/antagonist/nukeop/clownop/on_gain()
. = ..()
ADD_TRAIT(owner, TRAIT_CLOWN_MENTALITY, NUKEOP_ANTAGONIST)
ADD_TRAIT(owner, TRAIT_CLOWN_MENTALITY, CLOWNOP_TRAIT)
/datum/antagonist/nukeop/clownop/on_removal()
REMOVE_TRAIT(owner, TRAIT_CLOWN_MENTALITY, NUKEOP_ANTAGONIST)
REMOVE_TRAIT(owner, TRAIT_CLOWN_MENTALITY, CLOWNOP_TRAIT)
return ..()
/datum/antagonist/nukeop/leader/clownop
@@ -2,6 +2,7 @@
name = "Survivalist"
show_in_antagpanel = FALSE
show_name_in_check_antagonists = TRUE
blacklisted_quirks = list(/datum/quirk/nonviolent) // mutes are allowed
var/greet_message = ""
/datum/antagonist/survivalist/proc/forge_objectives()
@@ -19,20 +20,8 @@
owner.announce_objectives()
/datum/antagonist/survivalist/guns
greet_message = "Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, by any means necessary. Kill anyone who gets in your way."
/datum/antagonist/survivalist/guns/forge_objectives()
var/datum/objective/steal_five_of_type/summon_guns/guns = new
guns.owner = owner
objectives += guns
..()
greet_message = "Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, and don't let anyone take them!"
/datum/antagonist/survivalist/magic
name = "Amateur Magician"
greet_message = "Grow your newfound talent! Grab as many magical artefacts as possible, by any means necessary. Kill anyone who gets in your way."
/datum/antagonist/survivalist/magic/forge_objectives()
var/datum/objective/steal_five_of_type/summon_magic/magic = new
magic.owner = owner
objectives += magic
..()
greet_message = "This magic stuff is... so powerful. You want more. More! They want your power. They can't have it! Don't let them have it!"
@@ -77,19 +77,23 @@
var/is_hijacker = FALSE
var/datum/game_mode/dynamic/mode
var/is_dynamic = FALSE
var/hijack_prob = 0
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
if(mode.storyteller.flags & NO_ASSASSIN)
is_hijacker = FALSE
if(mode.threat >= CONFIG_GET(number/dynamic_hijack_cost))
hijack_prob = CLAMP(mode.threat_level-50,0,20)
if(GLOB.joined_player_list.len>=GLOB.dynamic_high_pop_limit)
is_hijacker = (prob(10) && mode.threat_level > CONFIG_GET(number/dynamic_hijack_high_population_requirement))
is_hijacker = (prob(hijack_prob) && mode.threat_level > CONFIG_GET(number/dynamic_hijack_high_population_requirement))
else
var/indice_pop = min(10,round(GLOB.joined_player_list.len/mode.pop_per_requirement)+1)
is_hijacker = (prob(10) && (mode.threat_level >= CONFIG_GET(number_list/dynamic_hijack_requirements)[indice_pop]))
is_hijacker = (prob(hijack_prob) && (mode.threat_level >= CONFIG_GET(number_list/dynamic_hijack_requirements)[indice_pop]))
if(mode.storyteller.flags & NO_ASSASSIN)
is_hijacker = FALSE
else if (GLOB.joined_player_list.len >= 30) // Less murderboning on lowpop thanks
hijack_prob = 10
is_hijacker = prob(10)
var/martyr_chance = prob(20)
var/martyr_chance = prob(hijack_prob*2)
var/objective_count = is_hijacker //Hijacking counts towards number of objectives
if(!SSticker.mode.exchange_blue && SSticker.mode.traitors.len >= 8) //Set up an exchange if there are enough traitors
if(!SSticker.mode.exchange_red)
@@ -170,7 +174,7 @@
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
assassin_prob = mode.threat_level*(2/3)
assassin_prob = max(0,mode.threat_level-20)
if(prob(assassin_prob))
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost)
@@ -187,22 +191,37 @@
maroon_objective.owner = owner
maroon_objective.find_target()
add_objective(maroon_objective)
else
else if(prob(max(0,assassin_prob-20)))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
kill_objective.find_target()
add_objective(kill_objective)
else
var/datum/objective/assassinate/once/kill_objective = new
kill_objective.owner = owner
kill_objective.find_target()
add_objective(kill_objective)
else
if(prob(15) && !(locate(/datum/objective/download) in objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
var/datum/objective/download/download_objective = new
download_objective.owner = owner
download_objective.gen_amount_goal()
add_objective(download_objective)
else
else if(prob(40)) // cum. not counting download: 40%.
var/datum/objective/steal/steal_objective = new
steal_objective.owner = owner
steal_objective.find_target()
add_objective(steal_objective)
else if(prob(100/3)) // cum. not counting download: 20%.
var/datum/objective/sabotage/sabotage_objective = new
sabotage_objective.owner = owner
sabotage_objective.find_target()
add_objective(sabotage_objective)
else // cum. not counting download: 40%
var/datum/objective/flavor/traitor/flavor_objective = new
flavor_objective.owner = owner
flavor_objective.forge_objective()
add_objective(flavor_objective)
/datum/antagonist/traitor/proc/forge_single_AI_objective()
.=1
@@ -369,11 +388,17 @@
if(objectives.len)//If the traitor had no objectives, don't need to process this.
var/count = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'>Success!</span>"
if(objective.completable)
var/completion = objective.check_completion()
if(completion >= 1)
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
else if(completion <= 0)
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
traitorwin = FALSE
else
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
else
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
traitorwin = FALSE
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text]"
count++
if(uplink_true)
@@ -35,7 +35,7 @@
var/objectives_complete = TRUE
if(objectives.len)
for(var/datum/objective/objective in objectives)
if(!objective.check_completion())
if(objective.completable && !objective.check_completion())
objectives_complete = FALSE
break
+13 -6
View File
@@ -61,9 +61,9 @@
owner.current.forceMove(pick(GLOB.wizardstart))
/datum/antagonist/wizard/proc/create_objectives()
var/datum/objective/new_objective = new("Cause as much creative mayhem as you can aboard the station! The more outlandish your methods of achieving this, the better! Make sure there's a decent amount of crew alive to tell of your tale.")
new_objective.completed = TRUE //So they can greentext without admin intervention.
var/datum/objective/flavor/wizard/new_objective = new
new_objective.owner = owner
new_objective.forge_objective()
objectives += new_objective
if (!(locate(/datum/objective/escape) in objectives))
@@ -94,6 +94,7 @@
to_chat(owner, "<span class='boldannounce'>You are the Space Wizard!</span>")
to_chat(owner, "<B>The Space Wizards Federation has given you the following tasks:</B>")
owner.announce_objectives()
to_chat(owner, "<B>These are merely guidelines! The federation are your masters, but you forge your own path!</B>")
to_chat(owner, "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.")
to_chat(owner, "The spellbook is bound to you, and others cannot use it.")
to_chat(owner, "In your pockets you will find a teleport scroll. Use it as needed.")
@@ -265,11 +266,17 @@
var/count = 1
var/wizardwin = 1
for(var/datum/objective/objective in objectives)
if(objective.check_completion())
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'>Success!</span>"
if(objective.completable)
var/completion = objective.check_completion()
if(completion >= 1)
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</span>"
else if(completion <= 0)
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
wizardwin = FALSE
else
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
else
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
wizardwin = 0
parts += "<B>Objective #[count]</B>: [objective.explanation_text]"
count++
if(wizardwin)
+7 -7
View File
@@ -81,8 +81,8 @@
desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproff armor, a few union suits and some warm hats!"
contraband = TRUE
cost = 5750 // Its basicly sec suits, good boots/gloves
contains = list(/obj/item/clothing/suit/security/officer/russian,
/obj/item/clothing/suit/security/officer/russian,
contains = list(/obj/item/clothing/suit/armor/navyblue/russian,
/obj/item/clothing/suit/armor/navyblue/russian,
/obj/item/clothing/shoes/combat,
/obj/item/clothing/shoes/combat,
/obj/item/clothing/head/ushanka,
@@ -104,7 +104,7 @@
contraband = TRUE
access = FALSE
cost = 5500 //
contains = list(/obj/item/clothing/suit/security/officer/russian,
contains = list(/obj/item/clothing/suit/armor/navyblue/russian,
/obj/item/clothing/shoes/combat,
/obj/item/clothing/head/ushanka,
/obj/item/clothing/suit/armor/bulletproof,
@@ -141,15 +141,15 @@
cost = 3250
contains = list(/obj/item/clothing/under/rank/security/navyblue,
/obj/item/clothing/under/rank/security/navyblue,
/obj/item/clothing/suit/security/officer,
/obj/item/clothing/suit/security/officer,
/obj/item/clothing/suit/armor/navyblue,
/obj/item/clothing/suit/armor/navyblue,
/obj/item/clothing/head/beret/sec/navyofficer,
/obj/item/clothing/head/beret/sec/navyofficer,
/obj/item/clothing/under/rank/warden/navyblue,
/obj/item/clothing/suit/security/warden,
/obj/item/clothing/suit/armor/vest/warden/navyblue,
/obj/item/clothing/head/beret/sec/navywarden,
/obj/item/clothing/under/rank/head_of_security/navyblue,
/obj/item/clothing/suit/security/hos,
/obj/item/clothing/suit/armor/hos/navyblue,
/obj/item/clothing/head/beret/sec/navyhos)
crate_name = "security clothing crate"
+44 -1
View File
@@ -488,4 +488,47 @@
if(client && client.prefs.uses_glasses_colour && glasses_equipped)
add_client_colour(G.glass_colour_type)
else
remove_client_colour(G.glass_colour_type)
remove_client_colour(G.glass_colour_type)
/obj/item/clothing/glasses/debug
name = "debug glasses"
desc = "Medical, security and diagnostic hud. Alt click to toggle xray."
icon_state = "nvgmeson"
item_state = "nvgmeson"
flags_cover = GLASSESCOVERSEYES
darkness_view = 8
flash_protect = 2
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
glass_colour_type = FALSE
clothing_flags = SCAN_REAGENTS
vision_flags = SEE_TURFS
var/list/hudlist = list(DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC_ADVANCED, DATA_HUD_SECURITY_ADVANCED)
var/xray = FALSE
/obj/item/clothing/glasses/debug/equipped(mob/user, slot)
. = ..()
if(slot != ITEM_SLOT_EYES)
return
if(ishuman(user))
for(var/hud in hudlist)
var/datum/atom_hud/H = GLOB.huds[hud]
H.add_hud_to(user)
/obj/item/clothing/glasses/debug/dropped(mob/user)
. = ..()
if(ishuman(user))
for(var/hud in hudlist)
var/datum/atom_hud/H = GLOB.huds[hud]
H.remove_hud_from(user)
/obj/item/clothing/glasses/debug/AltClick(mob/user)
. = ..()
if(ishuman(user))
if(xray)
vision_flags -= SEE_MOBS|SEE_OBJS
else
vision_flags += SEE_MOBS|SEE_OBJS
xray = !xray
var/mob/living/carbon/human/H = user
H.update_sight()
+2
View File
@@ -11,6 +11,8 @@
var/transfer_blood = 0
strip_delay = 20
equip_delay_other = 40
var/strip_mod = 1 //how much they alter stripping items time by, higher is quicker
var/strip_silence = FALSE //if it shows a warning when stripping
/obj/item/clothing/gloves/ComponentInitialize()
. = ..()
+1
View File
@@ -5,6 +5,7 @@
item_state = "boxing"
equip_delay_other = 60
species_exception = list(/datum/species/golem) // now you too can be a golem boxing champion
strip_mod = 0.5
/obj/item/clothing/gloves/boxing/green
icon_state = "boxinggreen"
+2
View File
@@ -41,6 +41,7 @@
permeability_coefficient = 1
resistance_flags = NONE
transfer_prints = TRUE
strip_mod = 0.8
/obj/item/clothing/gloves/cut/family
desc = "The old gloves your great grandfather stole from Engineering, many moons ago. They've seen some tough times recently."
@@ -76,6 +77,7 @@
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
resistance_flags = NONE
var/can_be_cut = 1
strip_mod = 1.2
/obj/item/clothing/gloves/color/black/hos
item_color = "hosred" //Exists for washing machines. Is not different from black gloves in any way.
@@ -10,6 +10,7 @@
equip_delay_other = 20
cold_protection = HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
strip_mod = 0.9
/obj/item/clothing/gloves/botanic_leather
name = "botanist's leather gloves"
@@ -23,6 +24,7 @@
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
resistance_flags = NONE
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 30)
strip_mod = 0.9
/obj/item/clothing/gloves/combat
name = "combat gloves"
@@ -38,6 +40,7 @@
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
resistance_flags = NONE
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 50)
strip_mod = 1.5
/obj/item/clothing/gloves/bracer
@@ -103,3 +106,15 @@
/obj/item/clothing/gloves/rapid/hug/attack_self(mob/user)
return FALSE
/obj/item/clothing/gloves/thief
name = "black gloves"
desc = "Gloves made with completely frictionless, insulated cloth, easier to steal from people with."
icon_state = "thief"
item_state = "blackgloves"
siemens_coefficient = 0
permeability_coefficient = 0.05
strip_delay = 80
transfer_prints = FALSE
strip_mod = 5
strip_silence = TRUE
+6
View File
@@ -39,6 +39,12 @@
/obj/item/clothing/mask/gas/welding/attack_self(mob/user)
weldingvisortoggle(user)
/obj/item/clothing/mask/gas/welding/up
/obj/item/clothing/mask/gas/welding/up/Initialize()
..()
visor_toggling()
// ********************************************************************
+22 -9
View File
@@ -427,14 +427,27 @@
/datum/outfit/debug //Debug objs plus hardsuit
name = "Debug outfit"
uniform = /obj/item/clothing/under/patriotsuit
suit = /obj/item/clothing/suit/space/hardsuit/syndi/elite
shoes = /obj/item/clothing/shoes/magboots/advance
suit_store = /obj/item/tank/internals/oxygen
mask = /obj/item/clothing/mask/gas/welding
belt = /obj/item/storage/belt/utility/chief/full
gloves = /obj/item/clothing/gloves/combat
id = /obj/item/card/id/ert
glasses = /obj/item/clothing/glasses/meson/night
suit = /obj/item/clothing/suit/space/hardsuit/syndi/elite/debug
glasses = /obj/item/clothing/glasses/debug
ears = /obj/item/radio/headset/headset_cent/commander
mask = /obj/item/clothing/mask/gas/welding/up
gloves = /obj/item/clothing/gloves/combat
belt = /obj/item/storage/belt/utility/chief/full
l_pocket = /obj/item/gun/magic/wand/resurrection/debug
r_pocket = /obj/item/gun/magic/wand/death/debug
shoes = /obj/item/clothing/shoes/magboots/advance/debug
id = /obj/item/card/id/debug
suit_store = /obj/item/tank/internals/oxygen
back = /obj/item/storage/backpack/holding
backpack_contents = list(/obj/item/card/emag=1, /obj/item/flashlight/emp/debug=1, /obj/item/construction/rcd/combat=1, /obj/item/gun/magic/wand/resurrection/debug=1, /obj/item/melee/transforming/energy/axe=1)
box = /obj/item/storage/box/debugtools
internals_slot = ITEM_SLOT_SUITSTORE
backpack_contents = list(
/obj/item/melee/transforming/energy/axe=1,\
/obj/item/storage/part_replacer/bluespace/tier4=1,\
/obj/item/debug/human_spawner=1,\
)
/datum/outfit/debug/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
var/obj/item/card/id/W = H.wear_id
W.registered_name = H.real_name
W.update_label()
+8 -2
View File
@@ -30,8 +30,9 @@
magpulse = !magpulse
icon_state = "[magboot_state][magpulse]"
to_chat(user, "<span class='notice'>You [magpulse ? "enable" : "disable"] the mag-pulse traction system.</span>")
user.update_inv_shoes() //so our mob-overlays update
user.update_gravity(user.has_gravity())
if(user)
user.update_inv_shoes() //so our mob-overlays update
user.update_gravity(user.has_gravity())
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
@@ -52,6 +53,11 @@
slowdown_active = SHOES_SLOWDOWN
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
/obj/item/clothing/shoes/magboots/advance/debug
/obj/item/clothing/shoes/magboots/advance/debug/Initialize()
attack_self(src)
/obj/item/clothing/shoes/magboots/syndie
desc = "Reverse-engineered magnetic boots that have a heavy magnetic pull. Property of Gorlex Marauders."
name = "blood-red magboots"
+10 -1
View File
@@ -269,7 +269,7 @@
item_state = "syndie_helm"
item_color = "syndi"
armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 90)
on = TRUE
on = FALSE
var/obj/item/clothing/suit/space/hardsuit/syndi/linkedsuit = null
actions_types = list(/datum/action/item_action/toggle_helmet_mode)
visor_flags_inv = HIDEMASK|HIDEEYES|HIDEFACE|HIDEFACIALHAIR
@@ -367,6 +367,12 @@
on = FALSE
resistance_flags = FIRE_PROOF | ACID_PROOF
/obj/item/clothing/head/helmet/space/hardsuit/syndi/elite/debug
/obj/item/clothing/head/helmet/space/hardsuit/syndi/elite/debug/Initialize()
. = ..()
soundloop.volume = 0
/obj/item/clothing/suit/space/hardsuit/syndi/elite
name = "elite syndicate hardsuit"
desc = "An elite version of the syndicate hardsuit, with improved armour and fireproofing. It is in travel mode."
@@ -380,6 +386,9 @@
resistance_flags = FIRE_PROOF | ACID_PROOF
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC|STYLE_PAW_TAURIC
/obj/item/clothing/suit/space/hardsuit/syndi/elite/debug
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi/elite/debug
slowdown = 0
//The Owl Hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/syndi/owl
+24 -1
View File
@@ -15,6 +15,13 @@
if(!allowed)
allowed = GLOB.security_vest_allowed
/obj/item/clothing/suit/armor/navyblue
name = "security officer's jacket"
desc = "This jacket is for those special occasions when a security officer isn't required to wear their armor."
icon_state = "officerbluejacket"
item_state = "officerbluejacket"
body_parts_covered = CHEST|ARMS
/obj/item/clothing/suit/armor/vest
name = "armor vest"
desc = "A slim Type I armored vest that provides decent protection against most types of damage."
@@ -52,8 +59,17 @@
heat_protection = CHEST|GROIN|LEGS|ARMS
strip_delay = 80
/obj/item/clothing/suit/armor/hos/navyblue
name = "head of security's jacket"
desc = "This piece of clothing was specifically designed for asserting superior authority."
icon_state = "hosbluejacket"
item_state = "hosbluejacket"
body_parts_covered = CHEST|ARMS
cold_protection = CHEST|ARMS
heat_protection = CHEST|ARMS
/obj/item/clothing/suit/armor/hos/trenchcoat
name = "armored trenchoat"
name = "armored trenchcoat"
desc = "A trenchcoat enhanced with a special lightweight kevlar. The epitome of tactical plainclothes."
icon_state = "hostrench"
item_state = "hostrench"
@@ -78,6 +94,13 @@
desc = "A red jacket with silver rank pips and body armor strapped on top."
icon_state = "warden_jacket"
/obj/item/clothing/suit/armor/vest/warden/navyblue
name = "warden's jacket"
desc = "Perfectly suited for the warden that wants to leave an impression of style on those who visit the brig."
icon_state = "wardenbluejacket"
item_state = "wardenbluejacket"
body_parts_covered = CHEST|ARMS
/obj/item/clothing/suit/armor/vest/leather
name = "security overcoat"
desc = "Lightly armored leather overcoat meant as casual wear for high-ranking officers. Bears the crest of Nanotrasen Security."
-22
View File
@@ -155,28 +155,6 @@
blood_overlay_type = "armor" //it's the less thing that I can put here
body_parts_covered = NONE
//Security
/obj/item/clothing/suit/security/officer
name = "security officer's jacket"
desc = "This jacket is for those special occasions when a security officer isn't required to wear their armor."
icon_state = "officerbluejacket"
item_state = "officerbluejacket"
body_parts_covered = CHEST|ARMS
/obj/item/clothing/suit/security/warden
name = "warden's jacket"
desc = "Perfectly suited for the warden that wants to leave an impression of style on those who visit the brig."
icon_state = "wardenbluejacket"
item_state = "wardenbluejacket"
body_parts_covered = CHEST|ARMS
/obj/item/clothing/suit/security/hos
name = "head of security's jacket"
desc = "This piece of clothing was specifically designed for asserting superior authority."
icon_state = "hosbluejacket"
item_state = "hosbluejacket"
body_parts_covered = CHEST|ARMS
//Surgeon
/obj/item/clothing/suit/apron/surgical
name = "surgical apron"
+1 -1
View File
@@ -317,7 +317,7 @@
flags_cover = HEADCOVERSEYES
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
/obj/item/clothing/suit/security/officer/russian
/obj/item/clothing/suit/armor/navyblue/russian
name = "\improper Russian officer's jacket"
desc = "This jacket is for those special occasions when a russian officer isn't required to wear their armor."
icon_state = "officertanjacket"
+1 -1
View File
@@ -22,7 +22,7 @@
/datum/round_event/meteor_wave/setup()
announceWhen = 1
startWhen = rand(60, 90) //Yeah for SOME REASON this is measured in seconds and not deciseconds???
startWhen = rand(90, 180) // Apparently it is by 2 seconds, so 90 is actually 180 seconds, and 180 is 360 seconds. So this is 3-6 minutes
if(GLOB.singularity_counter)
startWhen *= 1 - min(GLOB.singularity_counter * SINGULO_BEACON_DISTURBANCE, SINGULO_BEACON_MAX_DISTURBANCE)
endWhen = startWhen + 60
+5
View File
@@ -177,6 +177,7 @@
shuttleId = "pirateship"
icon_screen = "syndishuttle"
icon_keyboard = "syndie_key"
resistance_flags = INDESTRUCTIBLE
light_color = LIGHT_COLOR_RED
possible_destinations = "pirateship_away;pirateship_home;pirateship_custom"
@@ -184,6 +185,7 @@
name = "pirate shuttle navigation computer"
desc = "Used to designate a precise transit location for the pirate shuttle."
shuttleId = "pirateship"
resistance_flags = INDESTRUCTIBLE
lock_override = CAMERA_LOCK_STATION
shuttlePortId = "pirateship_custom"
x_offset = 9
@@ -226,6 +228,7 @@
desc = "This sophisticated machine scans the nearby space for items of value."
icon = 'icons/obj/machines/research.dmi'
icon_state = "tdoppler"
resistance_flags = INDESTRUCTIBLE
density = TRUE
var/cooldown = 300
var/next_use = 0
@@ -259,6 +262,7 @@
name = "cargo hold pad"
icon = 'icons/obj/telescience.dmi'
icon_state = "lpad-idle-o"
resistance_flags = INDESTRUCTIBLE
var/idle_state = "lpad-idle-o"
var/warmup_state = "lpad-idle"
var/sending_state = "lpad-beam"
@@ -272,6 +276,7 @@
/obj/machinery/computer/piratepad_control
name = "cargo hold control terminal"
resistance_flags = INDESTRUCTIBLE
var/status_report = "Idle"
var/obj/machinery/piratepad/pad
var/warmup_time = 100
+4 -3
View File
@@ -71,9 +71,10 @@
reagents_add = list(/datum/reagent/consumable/nutriment = 0.05)
rarity = 30
/obj/item/seeds/poppy/lily/trumpet/Initialize()
..()
unset_mutability(/datum/plant_gene/reagent/polypyr, PLANT_GENE_EXTRACTABLE)
/obj/item/seeds/poppy/lily/trumpet/Initialize(mapload, nogenes = FALSE)
. = ..()
if(!nogenes)
unset_mutability(/datum/plant_gene/reagent/polypyr, PLANT_GENE_EXTRACTABLE)
/obj/item/reagent_containers/food/snacks/grown/trumpet
seed = /obj/item/seeds/poppy/lily/trumpet
+4 -3
View File
@@ -82,9 +82,10 @@
mutatelist = list()
reagents_add = list(/datum/reagent/consumable/nutriment = 0.05, /datum/reagent/medicine/silibinin = 0.1)
/obj/item/seeds/galaxythistle/Initialize()
..()
unset_mutability(/datum/plant_gene/trait/invasive, PLANT_GENE_REMOVABLE)
/obj/item/seeds/galaxythistle/Initialize(mapload, nogenes = FALSE)
. = ..()
if(!nogenes)
unset_mutability(/datum/plant_gene/trait/invasive, PLANT_GENE_REMOVABLE)
/obj/item/reagent_containers/food/snacks/grown/galaxythistle
seed = /obj/item/seeds/galaxythistle
+5 -4
View File
@@ -217,10 +217,11 @@
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
reagents_add = list(/datum/reagent/consumable/nutriment = 0.1)
/obj/item/seeds/chanterelle/jupitercup/Initialize()
..()
unset_mutability(/datum/plant_gene/reagent/liquidelectricity, PLANT_GENE_EXTRACTABLE)
unset_mutability(/datum/plant_gene/trait/plant_type/carnivory, PLANT_GENE_REMOVABLE)
/obj/item/seeds/chanterelle/jupitercup/Initialize(mapload, nogenes = FALSE)
. = ..()
if(!nogenes)
unset_mutability(/datum/plant_gene/reagent/liquidelectricity, PLANT_GENE_EXTRACTABLE)
unset_mutability(/datum/plant_gene/trait/plant_type/carnivory, PLANT_GENE_REMOVABLE)
/obj/item/reagent_containers/food/snacks/grown/mushroom/jupitercup
seed = /obj/item/seeds/chanterelle/jupitercup
+3 -1
View File
@@ -18,7 +18,9 @@
return !istype(S, /obj/item/seeds/sample) // Samples can't accept new genes
/datum/plant_gene/proc/Copy()
return new type
var/datum/plant_gene/G = new type
G.mutability_flags = mutability_flags
return G
/datum/plant_gene/proc/apply_vars(obj/item/seeds/S) // currently used for fire resist, can prob. be further refactored
return
+1 -1
View File
@@ -37,7 +37,7 @@
var/weed_rate = 1 //If the chance below passes, then this many weeds sprout during growth
var/weed_chance = 5 //Percentage chance per tray update to grow weeds
/obj/item/seeds/Initialize(loc, nogenes = 0)
/obj/item/seeds/Initialize(mapload, nogenes = 0)
. = ..()
pixel_x = rand(-8, 8)
pixel_y = rand(-8, 8)
+1
View File
@@ -17,6 +17,7 @@
display_order = JOB_DISPLAY_ORDER_MIME
/datum/job/mime/after_spawn(mob/living/carbon/human/H, mob/M)
. = ..()
H.apply_pref_name("mime", M.client)
/datum/outfit/job/mime
+2 -2
View File
@@ -559,7 +559,7 @@
health = round(maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute, DAMAGE_PRECISION)
staminaloss = round(total_stamina, DAMAGE_PRECISION)
update_stat()
if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD) && stat == DEAD )
if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD*2) && stat == DEAD )
become_husk("burn")
med_hud_set_health()
if(stat == SOFT_CRIT)
@@ -986,4 +986,4 @@
if(H.clothing_flags & SCAN_REAGENTS)
return TRUE
if(isclothing(wear_mask) && (wear_mask.clothing_flags & SCAN_REAGENTS))
return TRUE
return TRUE
@@ -274,7 +274,7 @@
return
if(health >= 0 && !(HAS_TRAIT(src, TRAIT_FAKEDEATH)))
var/friendly_check = FALSE
if(lying)
if(buckled)
to_chat(M, "<span class='warning'>You need to unbuckle [src] first to do that!")
@@ -289,39 +289,35 @@
playsound(src, 'sound/items/Nose_boop.ogg', 50, 0)
else if(check_zone(M.zone_selected) == "head")
var/mob/living/carbon/human/H = src
var/datum/species/pref_species = H.dna.species
var/datum/species/S
if(ishuman(src))
S = dna.species
M.visible_message("<span class='notice'>[M] gives [H] a pat on the head to make [p_them()] feel better!</span>", \
"<span class='notice'>You give [H] a pat on the head to make [p_them()] feel better!</span>")
M.visible_message("<span class='notice'>[M] gives [src] a pat on the head to make [p_them()] feel better!</span>", \
"<span class='notice'>You give [src] a pat on the head to make [p_them()] feel better!</span>")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat)
if(HAS_TRAIT(M, TRAIT_FRIENDLY))
var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
if (mood.sanity >= SANITY_GREAT)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "friendly_hug", /datum/mood_event/besthug, M)
else if (mood.sanity >= SANITY_DISTURBED)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "friendly_hug", /datum/mood_event/betterhug, M)
if(H.dna.species.can_wag_tail(H))
if("tail_human" in pref_species.default_features)
if(H.dna.features["tail_human"] == "None")
friendly_check = TRUE
if(S?.can_wag_tail(src))
if("tail_human" in S.default_features)
if(dna.features["tail_human"] == "None")
return
else
if(!H.dna.species.is_wagging_tail())
H.emote("wag")
if(!dna.species.is_wagging_tail())
emote("wag")
if("tail_lizard" in pref_species.default_features)
if(H.dna.features["tail_lizard"] == "None")
if("tail_lizard" in S.default_features)
if(dna.features["tail_lizard"] == "None")
return
else
if(!H.dna.species.is_wagging_tail())
H.emote("wag")
if(!dna.species.is_wagging_tail())
emote("wag")
if("mam_tail" in pref_species.default_features)
if(H.dna.features["mam_tail"] == "None")
if("mam_tail" in S.default_features)
if(dna.features["mam_tail"] == "None")
return
else
if(!H.dna.species.is_wagging_tail())
H.emote("wag")
if(!dna.species.is_wagging_tail())
emote("wag")
else
return
@@ -335,8 +331,11 @@
M.visible_message("<span class='notice'>[M] hugs [src] to make [p_them()] feel better!</span>", \
"<span class='notice'>You hug [src] to make [p_them()] feel better!</span>")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/hug)
if(HAS_TRAIT(M, TRAIT_FRIENDLY))
var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
friendly_check = TRUE
if(friendly_check && HAS_TRAIT(M, TRAIT_FRIENDLY))
var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
if(mood)
if (mood.sanity >= SANITY_GREAT)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "friendly_hug", /datum/mood_event/besthug, M)
else if (mood.sanity >= SANITY_DISTURBED)
+1 -4
View File
@@ -16,10 +16,6 @@
. += "[t_He] [t_is] wearing [wear_mask.get_examine_string(user)] on [t_his] face."
if (wear_neck)
. += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
if(can_be_held)
. += "[t_He] looks small enough to be picked up with <b>Alt+Click</b>!\n"
for(var/obj/item/I in held_items)
if(!(I.item_flags & ABSTRACT))
@@ -116,4 +112,5 @@
. += "[t_He] look[p_s()] very happy."
if(MOOD_LEVEL_HAPPY4 to INFINITY)
. += "[t_He] look[p_s()] ecstatic."
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
. += "*---------*</span>"
@@ -396,6 +396,7 @@
var/temp_flavor = print_flavor_text_2()
if(temp_flavor)
. += temp_flavor
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
. += "*---------*</span>"
/mob/living/proc/status_effect_examines(pronoun_replacement) //You can include this in any mob's examine() to show the examine texts of status effects!
@@ -1,45 +0,0 @@
/mob/living/carbon/human/proc/examine_nutrition()
var/message = ""
var/nutrition_examine = round(nutrition)
var/t_He = "It" //capitalised for use at the start of each line.
var/t_His = "Its"
var/t_his = "its"
var/t_is = "is"
var/t_has = "has"
switch(gender)
if(MALE)
t_He = "He"
t_his = "his"
t_His = "His"
if(FEMALE)
t_He = "She"
t_his = "her"
t_His = "Her"
if(PLURAL)
t_He = "They"
t_his = "their"
t_His = "Their"
t_is = "are"
t_has = "have"
if(NEUTER)
t_He = "It"
t_his = "its"
t_His = "Its"
switch(nutrition_examine)
if(0 to 49)
message = "<span class='warning'>[t_He] [t_is] starving! You can hear [t_his] stomach snarling from across the room!</span>\n"
if(50 to 99)
message = "<span class='warning'>[t_He] [t_is] extremely hungry. A deep growl occasionally rumbles from [t_his] empty stomach.</span>\n"
if(100 to 499)
return message //Well that's pretty normal, really.
if(500 to 864) // Fat.
message = "[t_He] [t_has] a stuffed belly, bloated fat and round from eating too much.\n"
if(1200 to 1934) // One person fully digested.
message = "<span class='warning'>[t_He] [t_is] sporting a large, round, sagging stomach. It's contains at least their body weight worth of glorping slush.</span>\n"
if(1935 to 3004) // Two people.
message = "<span class='warning'>[t_He] [t_is] engorged with a huge stomach that sags and wobbles as they move. [t_He] must have consumed at least twice their body weight. It looks incredibly soft.</span>\n"
if(3005 to 4074) // Three people.
message = "<span class='warning'>[t_His] stomach is firmly packed with digesting slop. [t_He] must have eaten at least a few times worth their body weight! It looks hard for them to stand, and [t_his] gut jiggles when they move.</span>\n"
if(4075 to 10000) // Four or more people.
message = "<span class='warning'>[t_He] [t_is] so absolutely stuffed that you aren't sure how it's possible to move. [t_He] can't seem to swell any bigger. The surface of [t_his] belly looks sorely strained!</span>\n"
return message
@@ -132,14 +132,14 @@
return INITIALIZE_HINT_QDEL
owner = new_owner
START_PROCESSING(SSobj, src)
RegisterSignal(owner, COMSIG_MOB_EXAMINATE, .proc/examinate_check)
RegisterSignal(owner, COMSIG_CLICK_SHIFT, .proc/examinate_check)
RegisterSignal(src, COMSIG_ATOM_HEARER_IN_VIEW, .proc/include_owner)
RegisterSignal(owner, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head)
RegisterSignal(owner, COMSIG_LIVING_FULLY_HEAL, .proc/retrieve_head)
/obj/item/dullahan_relay/proc/examinate_check(mob/source, atom/A)
if(source.client.eye == src && ((A in view(source.client.view, src)) || (isturf(A) && source.sight & SEE_TURFS) || (ismob(A) && source.sight & SEE_MOBS) || (isobj(A) && source.sight & SEE_OBJS)))
return COMPONENT_ALLOW_EXAMINE
/obj/item/dullahan_relay/proc/examinate_check(atom/source, mob/user)
if(user.client.eye == src)
return COMPONENT_ALLOW_EXAMINATE
/obj/item/dullahan_relay/proc/include_owner(datum/source, list/processing_list, list/hearers)
if(!QDELETED(owner))
@@ -182,10 +182,10 @@ There are several things that need to be remembered:
if(!gloves && bloody_hands)
var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER, color = blood_DNA_to_color())
if(get_num_arms() < 2)
if(has_left_hand())
if(get_num_arms(FALSE) < 2)
if(has_left_hand(FALSE))
bloody_overlay.icon_state = "bloodyhands_left"
else if(has_right_hand())
else if(has_right_hand(FALSE))
bloody_overlay.icon_state = "bloodyhands_right"
overlays_standing[GLOVES_LAYER] = bloody_overlay
@@ -265,7 +265,7 @@ There are several things that need to be remembered:
/mob/living/carbon/human/update_inv_shoes()
remove_overlay(SHOES_LAYER)
if(get_num_legs() <2)
if(get_num_legs(FALSE) <2)
return
if(client && hud_used)
@@ -15,7 +15,6 @@
bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
/obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
hud_type = /datum/hud/monkey
can_be_held = "monkey"
/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
verbs += /mob/living/proc/mob_sleep
@@ -42,14 +41,15 @@
create_dna(src)
dna.initialize_dna(random_blood_type())
/mob/living/carbon/monkey/ComponentInitialize()
. = ..()
AddElement(/datum/element/mob_holder, "monkey", null, null, null, SLOT_HEAD)
/mob/living/carbon/monkey/Destroy()
SSmobs.cubemonkeys -= src
return ..()
/mob/living/carbon/monkey/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "monkey", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
return holder
/mob/living/carbon/monkey/create_internal_organs()
internal_organs += new /obj/item/organ/appendix
internal_organs += new /obj/item/organ/lungs
-130
View File
@@ -1,130 +0,0 @@
//Generic system for picking up mobs.
//Currently works for head and hands.
/obj/item/clothing/head/mob_holder
name = "bugged mob"
desc = "Yell at coderbrush."
icon = null
icon_state = ""
var/mob/living/held_mob
var/can_head = FALSE
w_class = WEIGHT_CLASS_BULKY
/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/M, _worn_state, alt_worn, lh_icon, rh_icon, _can_head_override = FALSE)
. = ..()
if(M)
M.setDir(SOUTH)
held_mob = M
M.forceMove(src)
appearance = M.appearance
name = M.name
desc = M.desc
if(_can_head_override)
can_head = _can_head_override
if(alt_worn)
alternate_worn_icon = alt_worn
if(_worn_state)
item_state = _worn_state
icon_state = _worn_state
if(lh_icon)
lefthand_file = lh_icon
if(rh_icon)
righthand_file = rh_icon
if(!can_head)
slot_flags = NONE
/obj/item/clothing/head/mob_holder/Destroy()
if(held_mob)
release()
return ..()
/obj/item/clothing/head/mob_holder/dropped()
..()
if(isturf(loc))//don't release on soft-drops
release()
/obj/item/clothing/head/mob_holder/proc/release()
if(isliving(loc))
var/mob/living/L = loc
L.dropItemToGround(src)
if(held_mob)
var/mob/living/m = held_mob
m.forceMove(get_turf(m))
m.reset_perspective()
m.setDir(SOUTH)
held_mob = null
qdel(src)
/obj/item/clothing/head/mob_holder/relaymove(mob/user)
return
/obj/item/clothing/head/mob_holder/container_resist()
if(isliving(loc))
var/mob/living/L = loc
visible_message("<span class='warning'>[src] escapes [L]!</span>")
release()
/mob/living/proc/mob_pickup(mob/living/L)
var/obj/item/clothing/head/mob_holder/holder = generate_mob_holder()
if(!holder)
return
drop_all_held_items()
L.put_in_hands(holder)
return
/mob/living/proc/mob_try_pickup(mob/living/user)
if(!ishuman(user) || !src.Adjacent(user) || user.incapacitated() || !can_be_held)
return FALSE
if(user.get_active_held_item())
to_chat(user, "<span class='warning'>Your hands are full!</span>")
return FALSE
if(buckled)
to_chat(user, "<span class='warning'>[src] is buckled to something!</span>")
return FALSE
if(src == user)
to_chat(user, "<span class='warning'>You can't pick yourself up.</span>")
return FALSE
visible_message("<span class='warning'>[user] starts picking up [src].</span>", \
"<span class='userdanger'>[user] starts picking you up!</span>")
if(!do_after(user, 20, target = src))
return FALSE
if(user.get_active_held_item()||buckled)
return FALSE
visible_message("<span class='warning'>[user] picks up [src]!</span>", \
"<span class='userdanger'>[user] picks you up!</span>")
to_chat(user, "<span class='notice'>You pick [src] up.</span>")
mob_pickup(user)
return TRUE
/mob/living/AltClick(mob/user)
. = ..()
if(mob_try_pickup(user))
return TRUE
// I didn't define these for mobs, because you shouldn't be able to breathe out of mobs and using their loc isn't always the logical thing to do.
/obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env)
var/atom/location = loc
if(!loc)
return //null
var/turf/T = get_turf(loc)
while(location != T)
location = location.loc
if(ismob(location))
return location.loc.assume_air(env)
return loc.assume_air(env)
/obj/item/clothing/head/mob_holder/remove_air(amount)
var/atom/location = loc
if(!loc)
return //null
var/turf/T = get_turf(loc)
while(location != T)
location = location.loc
if(ismob(location))
return location.loc.remove_air(amount)
return loc.remove_air(amount)
+19 -10
View File
@@ -40,11 +40,6 @@
QDEL_LIST(diseases)
return ..()
/mob/living/proc/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
return holder
/mob/living/onZImpact(turf/T, levels)
if(!isgroundlessturf(T))
ZImpactDamage(T, levels)
@@ -763,10 +758,22 @@
if(HAS_TRAIT(what, TRAIT_NODROP))
to_chat(src, "<span class='warning'>You can't remove \the [what.name], it appears to be stuck!</span>")
return
who.visible_message("<span class='danger'>[src] tries to remove [who]'s [what.name].</span>", \
var/strip_mod = 1
var/strip_silence = FALSE
if (ishuman(src)) //carbon doesn't actually wear gloves
var/mob/living/carbon/C = src
var/obj/item/clothing/gloves/g = C.gloves
if (istype(g))
strip_mod = g.strip_mod
strip_silence = g.strip_silence
if (!strip_silence)
who.visible_message("<span class='danger'>[src] tries to remove [who]'s [what.name].</span>", \
"<span class='userdanger'>[src] tries to remove [who]'s [what.name].</span>")
what.add_fingerprint(src)
if(do_mob(src, who, what.strip_delay, ignorehelditem = TRUE))
what.add_fingerprint(src)
else
to_chat(src,"<span class='notice'>You try to remove [who]'s [what.name].</span>")
what.add_fingerprint(src)
if(do_mob(src, who, round(what.strip_delay / strip_mod), ignorehelditem = TRUE))
if(what && Adjacent(who))
if(islist(where))
var/list/L = where
@@ -1087,6 +1094,10 @@
fall(forced = 1)
canmove = !(ko || recoveringstam || pinned || IsStun() || IsFrozen() || chokehold || buckled || (!has_legs && !ignore_legs && !has_arms)) //Cit change - makes it plausible to move while resting, adds pinning and stamina crit
density = !lying
if(resting)
ENABLE_BITFIELD(movement_type, CRAWLING)
else
DISABLE_BITFIELD(movement_type, CRAWLING)
if(lying)
if(layer == initial(layer)) //to avoid special cases like hiding larvas.
layer = LYING_MOB_LAYER //so mob lying always appear behind standing mobs
@@ -1172,8 +1183,6 @@
return
if(!over.Adjacent(src) || (user != src) || !canUseTopic(over))
return
if(can_be_held)
mob_try_pickup(over)
/mob/living/proc/get_static_viruses() //used when creating blood and other infective objects
if(!LAZYLEN(diseases))
@@ -101,8 +101,6 @@
var/list/obj/effect/proc_holder/abilities = list()
var/can_be_held = FALSE //whether this can be picked up and held.
var/radiation = 0 //If the mob is irradiated.
var/ventcrawl_layer = PIPING_LAYER_DEFAULT
var/losebreath = 0
+2 -1
View File
@@ -103,7 +103,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
else if(message_mode || saymode)
message = copytext_char(message, 3)
message = trim_left(message)
if(!message)
return
if(message_mode == MODE_ADMIN)
if(client)
client.cmd_admin_say(message)
+3
View File
@@ -7,4 +7,7 @@
var/datum/antagonist/bloodsucker/V = mind.has_antag_datum(/datum/antagonist/bloodsucker)
if(V)
mind.remove_antag_datum(V)
var/datum/antagonist/gang/G = mind.has_antag_datum(/datum/antagonist/gang)
if(G)
mind.remove_antag_datum(G)
..()
+1 -4
View File
@@ -11,7 +11,7 @@
health = 500
maxHealth = 500
layer = BELOW_MOB_LAYER
can_be_held = TRUE
var/datum/element/mob_holder/current_mob_holder //because only a few of their chassis can be actually held.
var/network = "ss13"
var/obj/machinery/camera/current = null
@@ -64,9 +64,6 @@
var/list/possible_chassis //initialized in initialize.
var/list/dynamic_chassis_icons //ditto.
var/list/chassis_pixel_offsets_x //stupid dogborgs
var/static/item_head_icon = 'icons/mob/pai_item_head.dmi'
var/static/item_lh_icon = 'icons/mob/pai_item_lh.dmi'
var/static/item_rh_icon = 'icons/mob/pai_item_rh.dmi'
var/emitterhealth = 20
var/emittermaxhealth = 20
@@ -96,6 +96,12 @@
dynamic_chassis = choice
resist_a_rest(FALSE, TRUE)
update_icon()
if(possible_chassis[chassis])
current_mob_holder = AddElement(/datum/element/mob_holder, chassis, 'icons/mob/pai_item_head.dmi', 'icons/mob/pai_item_rh.dmi', 'icons/mob/pai_item_lh.dmi', SLOT_HEAD)
else
current_mob_holder?.Detach(src)
current_mob_holder = null
return
to_chat(src, "<span class='boldnotice'>You switch your holochassis projection composite to [chassis]</span>")
/mob/living/silicon/pai/lay_down()
@@ -117,19 +123,6 @@
set_light(0)
to_chat(src, "<span class='notice'>You disable your integrated light.</span>")
/mob/living/silicon/pai/mob_pickup(mob/living/L)
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, chassis, item_head_icon, item_lh_icon, item_rh_icon)
if(!L.put_in_hands(holder))
qdel(holder)
else
L.visible_message("<span class='warning'>[L] scoops up [src]!</span>")
/mob/living/silicon/pai/mob_try_pickup(mob/living/user)
if(!possible_chassis[chassis])
to_chat(user, "<span class='warning'>[src]'s current form isn't able to be carried!</span>")
return FALSE
return ..()
/mob/living/silicon/pai/verb/toggle_chassis_sit()
set name = "Toggle Chassis Sit"
set category = "IC"
@@ -191,7 +191,7 @@
else if(istype(I, /obj/item/gun/energy))
var/obj/item/gun/energy/EG = I
if(EG.cell?.charge < EG.cell.maxcharge)
var/obj/item/ammo_casing/energy/S = EG.ammo_type[EG.select]
var/obj/item/ammo_casing/energy/S = EG.ammo_type[EG.current_firemode_index]
EG.cell.give(S.e_cost * coeff)
if(!EG.chambered)
EG.recharge_newshot(TRUE)
@@ -143,7 +143,7 @@
/datum/outfit/russiancorpse/officer
name = "Russian Officer Corpse"
uniform = /obj/item/clothing/under/rank/security/navyblue/russian
suit = /obj/item/clothing/suit/security/officer/russian
suit = /obj/item/clothing/suit/armor/navyblue/russian
shoes = /obj/item/clothing/shoes/combat
ears = /obj/item/radio/headset
head = /obj/item/clothing/head/ushanka
@@ -207,7 +207,7 @@
/obj/effect/mob_spawn/human/corpse/bee_terrorist
name = "BLF Operative"
outfit = /datum/outfit/bee_terrorist
/datum/outfit/bee_terrorist
name = "BLF Operative"
uniform = /obj/item/clothing/under/color/yellow
@@ -31,7 +31,7 @@
var/mob/living/simple_animal/mouse/movement_target
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "cat"
can_be_held = "cat2"
var/held_icon = "cat2"
do_footstep = TRUE
/mob/living/simple_animal/pet/cat/Initialize()
@@ -41,6 +41,7 @@
/mob/living/simple_animal/pet/cat/ComponentInitialize()
. = ..()
AddElement(/datum/element/wuv, "purrs!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "hisses!", EMOTE_AUDIBLE)
AddElement(/datum/element/mob_holder, held_icon)
/mob/living/simple_animal/pet/cat/update_canmove()
..()
@@ -60,6 +61,7 @@
icon_state = "spacecat"
icon_living = "spacecat"
icon_dead = "spacecat_dead"
held_icon = "spacecat"
unsuitable_atmos_damage = 0
minbodytemp = TCMB
maxbodytemp = T0C + 40
@@ -71,6 +73,7 @@
icon_state = "original"
icon_living = "original"
icon_dead = "original_dead"
held_icon = "original"
collar_type = null
unique_pet = TRUE
@@ -84,7 +87,7 @@
pass_flags = PASSMOB
mob_size = MOB_SIZE_SMALL
collar_type = "kitten"
can_be_held = "cat"
held_icon = "cat"
//RUNTIME IS ALIVE! SQUEEEEEEEE~
/mob/living/simple_animal/pet/cat/Runtime
@@ -249,7 +252,7 @@
attacked_sound = 'sound/items/eatfood.ogg'
deathmessage = "loses its false life and collapses!"
death_sound = "bodyfall"
can_be_held = "cak"
held_icon = "cak"
/mob/living/simple_animal/pet/cat/cak/CheckParts(list/parts)
..()
@@ -13,13 +13,14 @@
see_in_dark = 5
speak_chance = 1
turns_per_move = 10
var/held_icon = "corgi"
do_footstep = TRUE
can_be_held = TRUE
/mob/living/simple_animal/pet/dog/ComponentInitialize()
. = ..()
AddElement(/datum/element/wuv, "yaps_happily!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "growls!", EMOTE_AUDIBLE)
AddElement(/datum/element/mob_holder, held_icon)
//Corgis and pugs are now under one dog subtype
@@ -34,13 +35,11 @@
childtype = list(/mob/living/simple_animal/pet/dog/corgi/puppy = 95, /mob/living/simple_animal/pet/dog/corgi/puppy/void = 5)
animal_species = /mob/living/simple_animal/pet/dog
gold_core_spawnable = FRIENDLY_SPAWN
can_be_held = TRUE
collar_type = "corgi"
var/obj/item/inventory_head
var/obj/item/inventory_back
var/shaved = FALSE
var/nofur = FALSE //Corgis that have risen past the material plane of existence.
can_be_held = "corgi"
/mob/living/simple_animal/pet/dog/corgi/Destroy()
QDEL_NULL(inventory_head)
@@ -69,7 +68,7 @@
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/pug = 3)
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "pug"
can_be_held = "pug"
held_icon = "pug"
/mob/living/simple_animal/pet/dog/corgi/exoticcorgi
name = "Exotic Corgi"
@@ -156,13 +155,6 @@
..()
update_corgi_fluff()
/mob/living/simple_animal/pet/dog/corgi/mob_pickup(mob/living/L)
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "corgi", null, 'icons/mob/pets_held_lh.dmi', 'icons/mob/pets_held_rh.dmi', FALSE)
if(!L.put_in_hands(holder))
qdel(holder)
else
L.visible_message("<span class='warning'>[L] scoops up [src]!</span>")
/mob/living/simple_animal/pet/dog/corgi/Topic(href, href_list)
if(!(iscarbon(usr) || iscyborg(usr)) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
usr << browse(null, "window=mob[REF(src)]")
@@ -371,7 +363,10 @@
icon_dead = "old_corgi_dead"
desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
turns_per_move = 20
can_be_held = "old_corgi"
var/datum/element/mob_holder/ele = SSdcs.GetElement(/datum/element/mob_holder, held_icon)
if(ele)
ele.Detach(src)
AddElement(/datum/element/mob_holder, "old_corgi")
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
@@ -594,7 +589,7 @@
unsuitable_atmos_damage = 0
minbodytemp = TCMB
maxbodytemp = T0C + 40
can_be_held = "void_puppy"
held_icon = "void_puppy"
/mob/living/simple_animal/pet/dog/corgi/puppy/void/Process_Spacemove(movement_dir = 0)
return 1 //Void puppies can navigate space.
@@ -616,7 +611,7 @@
response_harm = "kicks"
var/turns_since_scan = 0
var/puppies = 0
can_be_held = "lisa"
held_icon = "lisa"
//Lisa already has a cute bow!
/mob/living/simple_animal/pet/dog/corgi/Lisa/Topic(href, href_list)
@@ -51,7 +51,7 @@
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
see_in_dark = 7
blood_volume = 0
can_be_held = TRUE
var/can_be_held = TRUE //mob holder element.
held_items = list(null, null)
var/staticChoice = "static"
var/list/staticChoices = list("static", "blank", "letter", "animal")
@@ -101,6 +101,11 @@
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.add_to_hud(src)
/mob/living/simple_animal/drone/ComponentInitialize()
. = ..()
if(can_be_held)
//icon/item state is defined in mob_holder/drone_worn_icon()
AddElement(/datum/element/mob_holder, null, 'icons/mob/head.dmi', 'icons/mob/inhands/clothing_righthand.dmi', 'icons/mob/inhands/clothing_lefthand.dmi', TRUE, /datum/element/mob_holder.proc/drone_worn_icon)
/mob/living/simple_animal/drone/med_hud_set_health()
var/image/holder = hud_list[DIAG_HUD]
@@ -283,7 +288,3 @@
var/obj/item/clothing/H = head
if(H.clothing_flags & SCAN_REAGENTS)
return TRUE
/mob/living/simple_animal/drone/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "[visualAppearence]_hat", null, null, null, TRUE)
return holder
@@ -29,12 +29,6 @@
if("Nothing")
return
//picky up the drone c:
/mob/living/simple_animal/drone/attack_hand(mob/user)
if(user.a_intent != INTENT_HELP)
return ..() // TODO: convert picking up mobs into an element or component.
mob_try_pickup(user)
/mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user)
var/mob/dead/observer/G = get_ghost()
if(!client && (!G || !G.client))
@@ -18,9 +18,12 @@
response_disarm = "gently pushes aside"
response_harm = "kicks"
gold_core_spawnable = FRIENDLY_SPAWN
can_be_held = "fox"
do_footstep = TRUE
/mob/living/simple_animal/pet/fox/ComponentInitialize()
. = ..()
AddElement(/datum/element/mob_holder, "fox")
//Captain fox
/mob/living/simple_animal/pet/fox/Renault
name = "Renault"
@@ -23,7 +23,10 @@
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
var/static/list/edibles = typecacheof(list(/mob/living/simple_animal/butterfly, /mob/living/simple_animal/cockroach)) //list of atoms, however turfs won't affect AI, but will affect consumption.
can_be_held = "lizard" //you can hold lizards now.
/mob/living/simple_animal/hostile/lizard/ComponentInitialize()
. = ..()
AddElement(/datum/element/mob_holder, "lizard", null, null, null, SLOT_HEAD) //you can hold lizards now.
/mob/living/simple_animal/hostile/lizard/CanAttack(atom/the_target)//Can we actually attack a possible target?
if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
@@ -40,7 +43,3 @@
return TRUE
else
return ..()
/mob/living/simple_animal/hostile/lizard/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "lizard", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
return holder
@@ -26,17 +26,16 @@
var/body_color //brown, gray and white, leave blank for random
gold_core_spawnable = FRIENDLY_SPAWN
var/chew_probability = 1
can_be_held = TRUE
/mob/living/simple_animal/mouse/Initialize()
. = ..()
AddComponent(/datum/component/squeak, list('sound/effects/mousesqueek.ogg'=1), 100)
if(!body_color)
body_color = pick( list("brown","gray","white") )
body_color = pick(list("brown","gray","white"))
AddElement(/datum/element/mob_holder, "mouse_[body_color]")
icon_state = "mouse_[body_color]"
icon_living = "mouse_[body_color]"
icon_dead = "mouse_[body_color]_dead"
can_be_held = "mouse_[body_color]"
/mob/living/simple_animal/mouse/proc/splat()
src.health = 0
@@ -89,17 +88,14 @@
/mob/living/simple_animal/mouse/white
body_color = "white"
icon_state = "mouse_white"
can_be_held = "mouse_white"
/mob/living/simple_animal/mouse/gray
body_color = "gray"
icon_state = "mouse_gray"
can_be_held = "mouse_gray"
/mob/living/simple_animal/mouse/brown
body_color = "brown"
icon_state = "mouse_brown"
can_be_held = "mouse_brown"
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_animal/mouse/brown/Tom
@@ -124,7 +120,3 @@
/obj/item/reagent_containers/food/snacks/deadmouse/on_grind()
reagents.clear_reagents()
/mob/living/simple_animal/mouse/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
holder.w_class = WEIGHT_CLASS_TINY
return holder
@@ -22,9 +22,11 @@
maxHealth = 50
speed = 10
glide_size = 2
can_be_held = "sloth" //finally oranges can be held
do_footstep = TRUE
/mob/living/simple_animal/pet/fox/ComponentInitialize()
. = ..()
AddElement(/datum/element/mob_holder, "sloth") //finally oranges can be held
//Cargo Sloth
/mob/living/simple_animal/sloth/paperwork
@@ -432,6 +432,7 @@ Difficulty: Very Hard
H.dropItemToGround(W)
var/datum/job/clown/C = new /datum/job/clown()
C.equip(H)
C.after_spawn(H, H, TRUE)
qdel(C)
affected_targets.Add(H)
@@ -197,8 +197,6 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca
return 0
return ..()
/mob/living/simple_animal/hostile/mimic/copy/ranged
var/obj/item/gun/TrueGun = null
var/obj/item/gun/magic/Zapstick
@@ -229,14 +227,13 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca
casingtype = initial(M.ammo_type)
if(istype(G, /obj/item/gun/energy))
Zapgun = G
var/selectfiresetting = Zapgun.select
var/obj/item/ammo_casing/energy/E = Zapgun.ammo_type[selectfiresetting]
var/obj/item/ammo_casing/energy/E = Zapgun.ammo_type[Zapgun.current_firemode_index]
projectiletype = initial(E.projectile_type)
/mob/living/simple_animal/hostile/mimic/copy/ranged/OpenFire(the_target)
if(Zapgun)
if(Zapgun.cell)
var/obj/item/ammo_casing/energy/shot = Zapgun.ammo_type[Zapgun.select]
var/obj/item/ammo_casing/energy/shot = Zapgun.ammo_type[Zapgun.current_firemode_index]
if(Zapgun.cell.charge >= shot.e_cost)
Zapgun.cell.use(shot.e_cost)
Zapgun.update_icon()
@@ -131,7 +131,7 @@
/obj/item/projectile/temp/basilisk/magmawing/on_hit(atom/target, blocked = FALSE)
. = ..()
if(.)
if(. && isliving(target))
var/mob/living/L = target
if (istype(L))
L.adjust_fire_stacks(0.1)
@@ -144,7 +144,7 @@
/obj/item/projectile/temp/basilisk/icewing/on_hit(atom/target, blocked = FALSE)
. = ..()
if(.)
if(. && isliving(target))
var/mob/living/L = target
L.apply_status_effect(/datum/status_effect/freon/watcher)
@@ -62,8 +62,9 @@
/mob/living/simple_animal/hostile/asteroid/elite/herald/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
. = ..()
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
if(.)
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
/datum/action/innate/elite_attack/herald_trishot
name = "Triple Shot"
button_icon_state = "herald_trishot"
+4 -6
View File
@@ -321,20 +321,18 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
set name = "Examine"
set category = "IC"
if(!client)
return
if(!(SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A) & COMPONENT_ALLOW_EXAMINE) && ((client.eye != src && client.eye != loc) || (isturf(A) && !(sight & SEE_TURFS) && !(A in view(client ? client.view : world.view, src)))))
//cameras & co don't allow users to examine far away things, also shift-click catcher may issue examinate() calls for out-of-sight turfs
if(isturf(A) && !(sight & SEE_TURFS) && !(A in view(client ? client.view : world.view, src)))
// shift-click catcher may issue examinate() calls for out-of-sight turfs
return
if(is_blind(src))
to_chat(src, "<span class='notice'>Something is there but you can't see it.</span>")
to_chat(src, "<span class='warning'>Something is there but you can't see it!</span>")
return
face_atom(A)
var/list/result = A.examine(src)
to_chat(src, result.Join("\n"))
SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A)
//same as above
//note: ghosts can point, this is intended
@@ -12,4 +12,4 @@
/obj/item/ammo_casing/energy/plasma/weak
projectile_type = /obj/item/projectile/plasma/weak
e_cost = 100
e_cost = 100
@@ -5,6 +5,10 @@
e_cost = 200
harmful = FALSE
/obj/item/ammo_casing/energy/electrode/security
projectile_type = /obj/item/projectile/energy/electrode/security
e_cost = 100
/obj/item/ammo_casing/energy/electrode/spec
e_cost = 100
@@ -13,6 +17,7 @@
e_cost = 100
/obj/item/ammo_casing/energy/electrode/hos
projectile_type = /obj/item/projectile/energy/electrode/security/hos
e_cost = 200
/obj/item/ammo_casing/energy/electrode/old
@@ -27,4 +32,4 @@
click_cooldown_override = 3.5
/obj/item/ammo_casing/energy/disabler/secborg
e_cost = 50
e_cost = 50
@@ -13,7 +13,7 @@
name = "magpistol magazine (non-lethal disabler)"
icon_state = "smallmagmag"
ammo_type = /obj/item/ammo_casing/caseless/magnetic/weak/disabler
max_ammo = 15
max_ammo = 16
/obj/item/ammo_box/magazine/mmag/small/lethal
name = "magpistol magazine (lethal)"
+85 -70
View File
@@ -28,10 +28,19 @@
trigger_guard = TRIGGER_GUARD_NORMAL //trigger guard on the weapon, hulks can't fire them with their big meaty fingers
var/sawn_desc = null //description change if weapon is sawn-off
var/sawn_off = FALSE
var/burst_size = 1 //how large a burst is
var/fire_delay = 0 //rate of fire for burst firing and semi auto
var/firing_burst = 0 //Prevent the weapon from firing again while already firing
var/semicd = 0 //cooldown handler
/// Weapon is burst fire if this is above 1
var/burst_size = 1
/// The time between shots in burst.
var/burst_shot_delay = 3
/// The time between firing actions, this means between bursts if this is burst weapon. The reason this is 0 is because you are still, by default, limited by clickdelay.
var/fire_delay = 0
/// Last world.time this was fired
var/last_fire = 0
/// Currently firing, whether or not it's a burst or not.
var/firing = FALSE
/// Used in gun-in-mouth execution/suicide and similar, while TRUE nothing should work on this like firing or modification and so on and so forth.
var/busy_action = FALSE
var/weapon_weight = WEAPON_LIGHT //currently only used for inaccuracy
var/spread = 0 //Spread induced by the gun itself.
var/burst_spread = 0 //Spread induced by the gun itself during burst fire per iteration. Only checked if spread is 0.
@@ -77,10 +86,14 @@
azoom = new (src)
/obj/item/gun/Destroy()
QDEL_NULL(pin)
QDEL_NULL(gun_light)
QDEL_NULL(bayonet)
QDEL_NULL(chambered)
if(pin)
QDEL_NULL(pin)
if(gun_light)
QDEL_NULL(gun_light)
if(bayonet)
QDEL_NULL(bayonet)
if(chambered)
QDEL_NULL(chambered)
return ..()
/obj/item/gun/CheckParts(list/parts_list)
@@ -117,13 +130,12 @@
to_chat(user, "<span class='danger'>*click*</span>")
playsound(src, "gun_dry_fire", 30, 1)
/obj/item/gun/proc/shoot_live_shot(mob/living/user as mob|obj, pointblank = 0, mob/pbtarget = null, message = 1)
if(recoil)
shake_camera(user, recoil + 1, recoil)
if(isliving(user)) //CIT CHANGE - makes gun recoil cause staminaloss
user.adjustStaminaLossBuffered(getstamcost(user)*(firing_burst && burst_size >= 2 ? 1/burst_size : 1)) //CIT CHANGE - ditto
user.adjustStaminaLossBuffered(getstamcost(user)*(firing && burst_size >= 2 ? 1/burst_size : 1)) //CIT CHANGE - ditto
if(suppressed)
playsound(user, fire_sound, 10, 1)
@@ -143,9 +155,12 @@
/obj/item/gun/afterattack(atom/target, mob/living/user, flag, params)
. = ..()
process_afterattack(target, user, flag, params)
/obj/item/gun/proc/process_afterattack(atom/target, mob/living/user, flag, params)
if(!target)
return
if(firing_burst)
if(firing)
return
if(flag) //It's adjacent, is the user, or is on the user's person
if(target in user.contents) //can't shoot stuff inside us.
@@ -169,7 +184,6 @@
handle_suicide(user, target, params)
return
//Exclude lasertag guns from the TRAIT_CLUMSY check.
if(clumsy_check)
if(istype(user))
@@ -201,8 +215,6 @@
process_fire(target, user, TRUE, params, null, bonus_spread)
/obj/item/gun/can_trigger_gun(mob/living/user)
. = ..()
if(!.)
@@ -227,54 +239,29 @@
/obj/item/gun/proc/recharge_newshot()
return
/obj/item/gun/proc/process_burst(mob/living/user, atom/target, message = TRUE, params=null, zone_override = "", sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0)
if(!user || !firing_burst)
firing_burst = FALSE
return FALSE
if(!issilicon(user))
if(iteration > 1 && !(user.is_holding(src))) //for burst firing
firing_burst = FALSE
return FALSE
if(chambered && chambered.BB)
if(HAS_TRAIT(user, TRAIT_PACIFISM)) // If the user has the pacifist trait, then they won't be able to fire [src] if the round chambered inside of [src] is lethal.
if(chambered.harmful) // Is the bullet chambered harmful?
to_chat(user, "<span class='notice'> [src] is lethally chambered! You don't want to risk harming anyone...</span>")
return
if(randomspread)
sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread), 1)
else //Smart spread
sprd = round((((rand_spr/burst_size) * iteration) - (0.5 + (rand_spr * 0.25))) * (randomized_gun_spread + randomized_bonus_spread), 1)
before_firing(target,user)
if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, sprd, src))
shoot_with_empty_chamber(user)
firing_burst = FALSE
return FALSE
else
if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot
shoot_live_shot(user, 1, target, message)
else
shoot_live_shot(user, 0, target, message)
if (iteration >= burst_size)
firing_burst = FALSE
else
shoot_with_empty_chamber(user)
firing_burst = FALSE
return FALSE
process_chamber()
update_icon()
return TRUE
/obj/item/gun/proc/on_cooldown()
return busy_action || firing || ((last_fire + fire_delay) > world.time)
/obj/item/gun/proc/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
add_fingerprint(user)
if(semicd)
if(on_cooldown())
return
firing = TRUE
. = do_fire(target, user, message, params, zone_override, bonus_spread)
firing = FALSE
last_fire = world.time
if(user)
user.update_inv_hands()
SEND_SIGNAL(user, COMSIG_LIVING_GUN_PROCESS_FIRE, target, params, zone_override)
/obj/item/gun/proc/do_fire(atom/target, mob/living/user, message = TRUE, params, zone_override = "", bonus_spread = 0)
var/sprd = 0
var/randomized_gun_spread = 0
var/rand_spr = rand()
if(spread)
randomized_gun_spread = rand(0, spread)
randomized_gun_spread = rand(0, spread)
else if(burst_size > 1 && burst_spread)
randomized_gun_spread = rand(0, burst_spread)
if(HAS_TRAIT(user, TRAIT_POOR_AIM)) //nice shootin' tex
@@ -282,9 +269,12 @@
var/randomized_bonus_spread = rand(0, bonus_spread)
if(burst_size > 1)
firing_burst = TRUE
for(var/i = 1 to burst_size)
addtimer(CALLBACK(src, .proc/process_burst, user, target, message, params, zone_override, sprd, randomized_gun_spread, randomized_bonus_spread, rand_spr, i), fire_delay * (i - 1))
do_burst_shot(user, target, message, params, zone_override, sprd, randomized_gun_spread, randomized_bonus_spread, rand_spr, 1)
for(var/i in 2 to burst_size)
sleep(burst_shot_delay)
if(QDELETED(src))
break
do_burst_shot(user, target, message, params, zone_override, sprd, randomized_gun_spread, randomized_bonus_spread, rand_spr, i)
else
if(chambered)
sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread))
@@ -302,21 +292,46 @@
return
process_chamber()
update_icon()
semicd = TRUE
addtimer(CALLBACK(src, .proc/reset_semicd), fire_delay)
if(user)
user.update_inv_hands()
SEND_SIGNAL(user, COMSIG_LIVING_GUN_PROCESS_FIRE, target, params, zone_override)
SSblackbox.record_feedback("tally", "gun_fired", 1, type)
return TRUE
/obj/item/gun/update_icon()
..()
/obj/item/gun/proc/reset_semicd()
semicd = FALSE
/obj/item/gun/proc/do_burst_shot(mob/living/user, atom/target, message = TRUE, params=null, zone_override = "", sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0)
if(!user || !firing)
firing = FALSE
return FALSE
if(!issilicon(user))
if(iteration > 1 && !(user.is_holding(src))) //for burst firing
firing = FALSE
return FALSE
if(chambered && chambered.BB)
if(HAS_TRAIT(user, TRAIT_PACIFISM)) // If the user has the pacifist trait, then they won't be able to fire [src] if the round chambered inside of [src] is lethal.
if(chambered.harmful) // Is the bullet chambered harmful?
to_chat(user, "<span class='notice'> [src] is lethally chambered! You don't want to risk harming anyone...</span>")
return
if(randomspread)
sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread), 1)
else //Smart spread
sprd = round((((rand_spr/burst_size) * iteration) - (0.5 + (rand_spr * 0.25))) * (randomized_gun_spread + randomized_bonus_spread), 1)
before_firing(target,user)
if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, sprd, src))
shoot_with_empty_chamber(user)
firing = FALSE
return FALSE
else
if(get_dist(user, target) <= 1) //Making sure whether the target is in vicinity for the pointblank shot
shoot_live_shot(user, 1, target, message)
else
shoot_live_shot(user, 0, target, message)
if (iteration >= burst_size)
firing = FALSE
else
shoot_with_empty_chamber(user)
firing = FALSE
return FALSE
process_chamber()
update_icon()
return TRUE
/obj/item/gun/attack(mob/M as mob, mob/user)
if(user.a_intent == INTENT_HARM) //Flogging
@@ -437,7 +452,7 @@
if(!ishuman(user) || !ishuman(target))
return
if(semicd)
if(on_cooldown())
return
if(user == target)
@@ -447,7 +462,7 @@
target.visible_message("<span class='warning'>[user] points [src] at [target]'s head, ready to pull the trigger...</span>", \
"<span class='userdanger'>[user] points [src] at your head, ready to pull the trigger...</span>")
semicd = TRUE
busy_action = TRUE
if(!bypass_timer && (!do_mob(user, target, 120) || user.zone_selected != BODY_ZONE_PRECISE_MOUTH))
if(user)
@@ -455,10 +470,10 @@
user.visible_message("<span class='notice'>[user] decided not to shoot.</span>")
else if(target && target.Adjacent(user))
target.visible_message("<span class='notice'>[user] has decided to spare [target]</span>", "<span class='notice'>[user] has decided to spare your life!</span>")
semicd = FALSE
busy_action = FALSE
return
semicd = FALSE
busy_action = FALSE
target.visible_message("<span class='warning'>[user] pulls the trigger!</span>", "<span class='userdanger'>[user] pulls the trigger!</span>")
@@ -5,7 +5,7 @@
var/automatic_burst_overlay = TRUE
can_suppress = TRUE
burst_size = 3
fire_delay = 2
burst_shot_delay = 2
actions_types = list(/datum/action/item_action/toggle_firemode)
/obj/item/gun/ballistic/automatic/proto
@@ -77,11 +77,9 @@
/obj/item/gun/ballistic/automatic/proc/enable_burst()
burst_size = initial(burst_size)
fire_delay = initial(fire_delay)
/obj/item/gun/ballistic/automatic/proc/disable_burst()
burst_size = 1
fire_delay = 0
/obj/item/gun/ballistic/automatic/can_shoot()
return get_ammo()
@@ -100,7 +98,7 @@
item_state = "c20r"
mag_type = /obj/item/ammo_box/magazine/smgm45
fire_sound = 'sound/weapons/gunshot_smg.ogg'
fire_delay = 2
burst_shot_delay = 2
burst_size = 2
pin = /obj/item/firing_pin/implant/pindicate
can_bayonet = TRUE
@@ -130,7 +128,7 @@
mag_type = /obj/item/ammo_box/magazine/wt550m9
can_suppress = FALSE
burst_size = 2
fire_delay = 1
burst_shot_delay = 1
can_bayonet = TRUE
knife_x_offset = 25
knife_y_offset = 12
@@ -165,7 +163,7 @@
can_suppress = FALSE
var/obj/item/gun/ballistic/revolver/grenadelauncher/underbarrel
burst_size = 3
fire_delay = 2
burst_shot_delay = 2
pin = /obj/item/firing_pin/implant/pindicate
/obj/item/gun/ballistic/automatic/m90/Initialize()
@@ -212,7 +210,6 @@
if(0)
select = 1
burst_size = initial(burst_size)
fire_delay = initial(fire_delay)
to_chat(user, "<span class='notice'>You switch to [burst_size]-rnd burst.</span>")
if(1)
select = 2
@@ -220,7 +217,6 @@
if(2)
select = 0
burst_size = 1
fire_delay = 0
to_chat(user, "<span class='notice'>You switch to semi-auto.</span>")
playsound(user, 'sound/weapons/empty.ogg', 100, 1)
update_icon()
@@ -237,7 +233,7 @@
fire_sound = 'sound/weapons/gunshot_smg.ogg'
can_suppress = FALSE
burst_size = 4
fire_delay = 1
burst_shot_delay = 1
/obj/item/gun/ballistic/automatic/ar
name = "\improper NT-ARG 'Boarder'"
@@ -249,7 +245,7 @@
fire_sound = 'sound/weapons/gunshot_smg.ogg'
can_suppress = FALSE
burst_size = 3
fire_delay = 1
burst_shot_delay = 1
// Bulldog shotgun //
@@ -264,7 +260,6 @@
fire_sound = 'sound/weapons/gunshot.ogg'
can_suppress = FALSE
burst_size = 1
fire_delay = 0
pin = /obj/item/firing_pin/implant/pindicate
actions_types = list()
@@ -301,7 +296,7 @@
var/cover_open = FALSE
can_suppress = FALSE
burst_size = 3
fire_delay = 1
burst_shot_delay = 1
spread = 7
pin = /obj/item/firing_pin/implant/pindicate
@@ -421,7 +416,7 @@
mag_type = /obj/item/ammo_box/magazine/recharge
fire_delay = 2
can_suppress = FALSE
burst_size = 0
burst_size = 1
actions_types = list()
fire_sound = 'sound/weapons/laser.ogg'
casing_ejector = FALSE
+138 -40
View File
@@ -1,3 +1,16 @@
/*
* Energy guns that draw from a cell to fire.
*
* This is a bit weird but this is how it currently works:
* When switching shots, it clears the chamber, and loads the correct energy ammo casing if there is enough energy to fire it.
* If there's no projectile in the casing, it creates it now.
* Otherwise the chamber stays null.
* After firing, it actually deducts the energy and then clears the chamber and does the above again.
* It detects if a successful fire is done by checking if the chambered energy ammo casing still has its projectile intact.
*
* It might be good in the future to move away from ammo casinsgs and instead use a datum-firemode system, but that would make handling firing,
* which the casing does as of now, a little interesting to implement.
*/
/obj/item/gun/energy
icon_state = "energy"
name = "energy gun"
@@ -7,8 +20,10 @@
var/obj/item/stock_parts/cell/cell //What type of power cell this uses
var/cell_type = /obj/item/stock_parts/cell
var/modifystate = 0
var/list/ammo_type = list(/obj/item/ammo_casing/energy)
var/select = 1 //The state of the select fire switch. Determines from the ammo_type list what kind of shot is fired next.
/// = TRUE/FALSE decides if the user can switch to it of their own accord
var/list/ammo_type = list(/obj/item/ammo_casing/energy = TRUE)
/// The index of the ammo_types/firemodes which we're using right now
var/current_firemode_index = 1
var/can_charge = 1 //Can it be charged in a recharger?
var/automatic_charge_overlays = TRUE //Do we handle overlays with base update_icon()?
var/charge_sections = 4
@@ -21,6 +36,9 @@
var/use_cyborg_cell = FALSE //whether the gun drains the cyborg user's cell instead, not to be confused with EGUN_SELFCHARGE_BORG
var/dead_cell = FALSE //set to true so the gun is given an empty cell
/// SET THIS TO TRUE IF YOU OVERRIDE altafterattack() or ANY right click action! If this is FALSE, the gun will show in examine its default right click behavior, which is to switch modes.
var/right_click_overridden = FALSE
/obj/item/gun/energy/emp_act(severity)
. = ..()
if(!(. & EMP_PROTECT_CONTENTS))
@@ -46,22 +64,18 @@
START_PROCESSING(SSobj, src)
update_icon()
/obj/item/gun/energy/proc/update_ammo_types()
var/obj/item/ammo_casing/energy/shot
for (var/i = 1, i <= ammo_type.len, i++)
var/shottype = ammo_type[i]
shot = new shottype(src)
ammo_type[i] = shot
shot = ammo_type[select]
fire_sound = shot.fire_sound
fire_delay = shot.delay
/obj/item/gun/energy/Destroy()
QDEL_NULL(cell)
QDEL_LIST(ammo_type)
STOP_PROCESSING(SSobj, src)
if(flags_1 & INITIALIZED_1)
QDEL_NULL(cell)
QDEL_LIST(ammo_type)
STOP_PROCESSING(SSobj, src)
return ..()
/obj/item/gun/energy/examine(mob/user)
. = ..()
if(!right_click_overridden)
. += "<span class='notice'>Right click in combat mode to switch modes.</span>"
/obj/item/gun/energy/process()
if(selfcharge && cell?.charge < cell.maxcharge)
charge_tick++
@@ -82,13 +96,14 @@
recharge_newshot(TRUE)
update_icon()
/obj/item/gun/energy/attack_self(mob/living/user as mob)
if(ammo_type.len > 1)
// ATTACK SELF IGNORING PARENT RETURN VALUE
/obj/item/gun/energy/attack_self(mob/living/user)
. = ..()
if(can_select_fire(user))
select_fire(user)
update_icon()
/obj/item/gun/energy/can_shoot()
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index]
return !QDELETED(cell) ? (cell.charge >= shot.e_cost) : FALSE
/obj/item/gun/energy/recharge_newshot(no_cyborg_drain)
@@ -98,11 +113,11 @@
if(iscyborg(loc))
var/mob/living/silicon/robot/R = loc
if(R.cell)
var/obj/item/ammo_casing/energy/shot = ammo_type[select] //Necessary to find cost of shot
var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index] //Necessary to find cost of shot
if(R.cell.use(shot.e_cost)) //Take power from the borg...
cell.give(shot.e_cost) //... to recharge the shot
if(!chambered)
var/obj/item/ammo_casing/energy/AC = ammo_type[select]
var/obj/item/ammo_casing/energy/AC = ammo_type[current_firemode_index]
if(cell.charge >= AC.e_cost) //if there's enough power in the cell cell...
chambered = AC //...prepare a new shot based on the current ammo type selected
if(!chambered.BB)
@@ -115,29 +130,104 @@
chambered = null //either way, released the prepared shot
recharge_newshot() //try to charge a new shot
/obj/item/gun/energy/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/energy/do_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
if(!chambered && can_shoot())
process_chamber() // If the gun was drained and then recharged, load a new shot.
return ..()
/obj/item/gun/energy/process_burst(mob/living/user, atom/target, message = TRUE, params = null, zone_override="", sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0)
/obj/item/gun/energy/do_burst_shot(mob/living/user, atom/target, message = TRUE, params = null, zone_override="", sprd = 0, randomized_gun_spread = 0, randomized_bonus_spread = 0, rand_spr = 0, iteration = 0)
if(!chambered && can_shoot())
process_chamber() // Ditto.
return ..()
/obj/item/gun/energy/proc/select_fire(mob/living/user)
select++
if (select > ammo_type.len)
select = 1
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
fire_sound = shot.fire_sound
fire_delay = shot.delay
if (shot.select_name)
to_chat(user, "<span class='notice'>[src] is now set to [shot.select_name].</span>")
chambered = null
recharge_newshot(TRUE)
// Firemodes/Ammotypes
/obj/item/gun/energy/proc/update_ammo_types()
var/obj/item/ammo_casing/energy/C
for(var/i in 1 to length(ammo_type))
var/v = ammo_type[i]
var/user_can_select = ammo_type[v]
if(istype(v, /obj/item/ammo_casing/energy)) //already set
ammo_type[v] = isnull(user_can_select)? TRUE : user_can_select
else
C = new v //if you put non energycasing/type stuff in here you deserve the runtime
ammo_type[i] = C
ammo_type[C] = isnull(user_can_select)? TRUE : user_can_select
set_firemode_index(initial(current_firemode_index))
/obj/item/gun/energy/proc/set_firemode_index(index, mob/user_for_feedback)
chambered = null //unchamber whatever we have chambered
if(index > length(ammo_type))
index = 1
else if(index < 1)
index = length(ammo_type)
var/obj/item/ammo_casing/energy/C = ammo_type[index] //energy weapons should not have no casings, if it does you deserve the runtime.
current_firemode_index = index
fire_sound = C.fire_sound
fire_delay = C.delay
if(user_for_feedback)
to_chat(user_for_feedback, "<span class='notice'>[src] is now set to [C.select_name || C].</span>")
post_set_firemode()
update_icon(TRUE)
return
/obj/item/gun/energy/proc/post_set_firemode(recharge_newshot = TRUE)
if(recharge_newshot)
recharge_newshot(TRUE)
/obj/item/gun/energy/proc/set_firemode_to_next(mob/user_for_feedback)
return set_firemode_index(++current_firemode_index, user_for_feedback)
/obj/item/gun/energy/proc/set_firemode_to_prev(mob/user_for_feedback)
return set_firemode_index(--current_firemode_index, user_for_feedback)
/obj/item/gun/energy/proc/get_firemode_index(casing_type)
var/obj/item/ammo_casing/energy/E = locate(casing_type) in ammo_type
if(E)
return ammo_type.Find(E)
/obj/item/gun/energy/proc/set_firemode_to_type(casing_type)
var/index = get_firemode_index(casing_type)
if(index)
set_firemode_index(index)
/// This is the proc used in general for when a user switches firemodes. Just goes to next firemode by default.
/obj/item/gun/energy/proc/select_fire(mob/living/user)
return user_set_firemode_to_next(user)
/obj/item/gun/energy/proc/can_select_fire(mob/living/user)
return TRUE
#define INCREMENT_OR_WRAP(i) i = (i >= length(ammo_type))? 1 : (i + 1)
#define DECREMENT_OR_WRAP(i) i = (i <= 1)? length(ammo_type) : (i - 1)
#define IS_VALID_INDEX(i) (ammo_type[ammo_type[i]])
/obj/item/gun/energy/proc/user_set_firemode_to_next(mob/user_for_feedback)
var/current_index = current_firemode_index
var/new_index = current_index
INCREMENT_OR_WRAP(new_index)
if(!IS_VALID_INDEX(new_index))
var/initial_index = new_index
while(!IS_VALID_INDEX(new_index) && (new_index != initial_index))
new_index = INCREMENT_OR_WRAP(new_index)
if(initial_index == new_index) //cycled through without finding another
new_index = current_index
set_firemode_index(new_index, user_for_feedback)
/obj/item/gun/energy/proc/user_set_firemode_to_prev(mob/user_for_feedback)
var/current_index = current_firemode_index
var/new_index = current_index
DECREMENT_OR_WRAP(new_index)
if(!IS_VALID_INDEX(new_index))
var/initial_index = new_index
while(!IS_VALID_INDEX(new_index) && (new_index != initial_index))
new_index = DECREMENT_OR_WRAP(new_index)
if(initial_index == new_index) //cycled through without finding another
new_index = current_index
set_firemode_index(new_index, user_for_feedback)
#undef INCREMENT_OR_WRAP
#undef DECREMENT_OR_WRAP
#undef IS_VALID_INDEX
/obj/item/gun/energy/update_icon(force_update)
if(QDELETED(src))
@@ -157,7 +247,7 @@
if(!initial(item_state))
itemState = icon_state
if (modifystate)
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index]
add_overlay("[icon_state]_[shot.select_name]")
iconState += "_[shot.select_name]"
if(itemState)
@@ -176,6 +266,9 @@
if(itemState)
itemState += "[ratio]"
item_state = itemState
if(ismob(loc)) //forces inhands to update
var/mob/M = loc
M.update_inv_hands()
/obj/item/gun/energy/suicide_act(mob/living/user)
if (istype(user) && can_shoot() && can_trigger_gun(user) && user.get_bodypart(BODY_ZONE_HEAD))
@@ -185,7 +278,7 @@
user.visible_message("<span class='suicide'>[user] melts [user.p_their()] face off with [src]!</span>")
playsound(loc, fire_sound, 50, 1, -1)
playsound(src, 'sound/weapons/dink.ogg', 30, 1)
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index]
cell.use(shot.e_cost)
update_icon()
return(FIRELOSS)
@@ -207,13 +300,12 @@
STOP_PROCESSING(SSobj, src)
. = ..()
/obj/item/gun/energy/ignition_effect(atom/A, mob/living/user)
if(!can_shoot() || !ammo_type[select])
if(!can_shoot() || !ammo_type[current_firemode_index])
shoot_with_empty_chamber()
. = ""
else
var/obj/item/ammo_casing/energy/E = ammo_type[select]
var/obj/item/ammo_casing/energy/E = ammo_type[current_firemode_index]
var/obj/item/projectile/energy/BB = E.BB
if(!BB)
. = ""
@@ -235,3 +327,9 @@
playsound(user, BB.hitsound, 50, 1)
cell.use(E.e_cost)
. = "<span class='danger'>[user] casually lights their [A.name] with [src]. Damn.</span>"
/obj/item/gun/energy/altafterattack(atom/target, mob/user, proximity_flags, params)
if(!right_click_overridden)
select_fire(user)
return TRUE
return ..()
@@ -97,7 +97,7 @@
pin = null
can_charge = 0
ammo_x_offset = 1
ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser)
ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser)
selfcharge = EGUN_SELFCHARGE
var/fail_tick = 0
var/fail_chance = 0
@@ -113,18 +113,21 @@
..()
/obj/item/gun/energy/e_gun/nuclear/proc/failcheck()
if(prob(fail_chance) && isliving(loc))
var/mob/living/M = loc
if(prob(fail_chance))
switch(fail_tick)
if(0 to 200)
fail_tick += (2*(fail_chance))
M.rad_act(400)
to_chat(M, "<span class='userdanger'>Your [name] feels warmer.</span>")
radiation_pulse(src, 50)
var/mob/M = (ismob(loc) && loc) || (ismob(loc.loc) && loc.loc) //thank you short circuiting. if you powergame and nest these guns deeply you get to suffer no-warning radiation death.
if(M)
to_chat(M, "<span class='userdanger'>Your [name] feels warmer.</span>")
if(201 to INFINITY)
SSobj.processing.Remove(src)
M.rad_act(800)
crit_fail = 1
to_chat(M, "<span class='userdanger'>Your [name]'s reactor overloads!</span>")
radiation_pulse(src, 200)
crit_fail = TRUE
var/mob/M = (ismob(loc) && loc) || (ismob(loc.loc) && loc.loc)
if(M)
to_chat(M, "<span class='userdanger'>Your [name]'s reactor overloads!</span>")
/obj/item/gun/energy/e_gun/nuclear/emp_act(severity)
. = ..()
@@ -202,7 +202,7 @@
if(!ishuman(user) || !ishuman(target))
return
if(semicd)
if(on_cooldown())
return
if(user == target)
@@ -212,7 +212,7 @@
target.visible_message("<span class='warning'>[user] points [src] at [target]'s head, ready to pull the trigger...</span>", \
"<span class='userdanger'>[user] points [src] at your head, ready to pull the trigger...</span>")
semicd = TRUE
busy_action = TRUE
if(!bypass_timer && (!do_mob(user, target, 120) || user.zone_selected != BODY_ZONE_PRECISE_MOUTH))
if(user)
@@ -220,10 +220,10 @@
user.visible_message("<span class='notice'>[user] decided not to shoot.</span>")
else if(target && target.Adjacent(user))
target.visible_message("<span class='notice'>[user] has decided to spare [target]</span>", "<span class='notice'>[user] has decided to spare your life!</span>")
semicd = FALSE
busy_action = FALSE
return
semicd = FALSE
busy_action = FALSE
target.visible_message("<span class='warning'>[user] pulls the trigger!</span>", "<span class='userdanger'>[user] pulls the trigger!</span>")
@@ -36,7 +36,7 @@
/obj/item/gun/energy/decloner/update_icon()
..()
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index]
if(!QDELETED(cell) && (cell.charge > shot.e_cost))
add_overlay("decloner_spin")
@@ -185,7 +185,7 @@
var/atmos_link = FALSE
/obj/item/gun/energy/wormhole_projector/update_icon()
icon_state = "[initial(icon_state)][select]"
icon_state = "[initial(icon_state)][current_firemode_index]"
item_state = icon_state
/obj/item/gun/energy/wormhole_projector/update_ammo_types()
@@ -320,7 +320,7 @@
/obj/item/gun/energy/emitter/update_icon()
..()
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index]
if(!QDELETED(cell) && (cell.charge > shot.e_cost))
add_overlay("emitter_carbine_empty")
else
+15 -2
View File
@@ -18,10 +18,23 @@
/obj/item/gun/energy/e_gun/advtaser
name = "hybrid taser"
desc = "A dual-mode taser designed to fire both short-range high-power electrodes and long-range disabler beams."
desc = "A dual-mode taser designed to fire both short-range high-power electrodes and long-range disabler beams. <span class='boldnotice'>Right click in combat mode to fire a taser shot with a cooldown.</span>"
icon_state = "advtaser"
ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/electrode)
ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/electrode/security = FALSE)
ammo_x_offset = 2
// Not enough guns have altfire systems like this yet for this to be a universal framework.
var/last_altfire = 0
var/altfire_delay = 15
/obj/item/gun/energy/e_gun/advtaser/altafterattack(atom/target, mob/user, proximity_flag, params)
. = TRUE
if(last_altfire + altfire_delay > world.time)
return
var/current_index = current_firemode_index
set_firemode_to_type(/obj/item/ammo_casing/energy/electrode)
process_afterattack(target, user, proximity_flag, params)
set_firemode_index(current_index)
last_altfire = world.time
/obj/item/gun/energy/e_gun/advtaser/cyborg
name = "cyborg taser"
@@ -73,6 +73,12 @@
user.adjustOxyLoss(500)
charges--
/obj/item/gun/magic/wand/death/debug
desc = "In some obscure circles, this is known as the 'cloning tester's friend'."
max_charges = 500
variable_charges = FALSE
can_charge = TRUE
recharge_rate = 1
/////////////////////////////////////
//WAND OF HEALING
@@ -43,6 +43,7 @@
var/lastangle = 0
var/aiming_lastangle = 0
var/last_aimbeam = 0
var/mob/current_user = null
var/list/obj/effect/projectile/tracer/current_tracers
@@ -186,8 +187,9 @@
/obj/item/gun/energy/beam_rifle/proc/aiming_beam(force_update = FALSE)
var/diff = abs(aiming_lastangle - lastangle)
check_user()
if(diff < AIMING_BEAM_ANGLE_CHANGE_THRESHOLD && !force_update)
if(!check_user())
return
if(((diff < AIMING_BEAM_ANGLE_CHANGE_THRESHOLD) || ((last_aimbeam + 1) > world.time)) && !force_update)
return
aiming_lastangle = lastangle
var/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/P = new
@@ -208,6 +210,7 @@
targloc = get_turf_in_angle(lastangle, curloc, 10)
P.preparePixelProjectile(targloc, current_user, current_user.client.mouseParams, 0)
P.fire(lastangle)
last_aimbeam = world.time
/obj/item/gun/energy/beam_rifle/process()
if(!aiming)
@@ -296,27 +299,17 @@
if(istype(object, /obj/screen) && !istype(object, /obj/screen/click_catcher))
return
process_aim()
if(aiming_time_left <= aiming_time_fire_threshold && check_user())
if(aiming_time_left <= aiming_time_fire_threshold && check_user() && ((lastfire + delay) <= world.time))
sync_ammo()
afterattack(M.client.mouseObject, M, FALSE, M.client.mouseParams, passthrough = TRUE)
do_fire(M.client.mouseObject, M, FALSE, M.client.mouseParams, M.zone_selected)
stop_aiming()
QDEL_LIST(current_tracers)
return ..()
/obj/item/gun/energy/beam_rifle/afterattack(atom/target, mob/living/user, flag, params, passthrough = FALSE)
if(flag) //It's adjacent, is the user, or is on the user's person
if(target in user.contents) //can't shoot stuff inside us.
return
if(!ismob(target) || user.a_intent == INTENT_HARM) //melee attack
return
if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected)
return
if(!passthrough && (aiming_time > aiming_time_fire_threshold))
return
if(lastfire > world.time + delay)
return
lastfire = world.time
/obj/item/gun/energy/beam_rifle/do_fire(atom/target, mob/living/user, message = TRUE, params, zone_override = "", bonus_spread = 0)
. = ..()
if(.)
lastfire = world.time
stop_aiming()
/obj/item/gun/energy/beam_rifle/proc/sync_ammo()
@@ -2,11 +2,11 @@
name = "electrode"
icon_state = "spark"
color = "#FFFF00"
nodamage = 1
nodamage = TRUE
knockdown = 60
knockdown_stamoverride = 36
knockdown_stam_max = 50
stutter = 5
stutter = 10
jitter = 20
hitsound = 'sound/weapons/taserhit.ogg'
range = 7
@@ -14,6 +14,7 @@
muzzle_type = /obj/effect/projectile/muzzle/stun
impact_type = /obj/effect/projectile/impact/stun
var/tase_duration = 50
var/strong_tase = TRUE
/obj/item/projectile/energy/electrode/on_hit(atom/target, blocked = FALSE)
. = ..()
@@ -26,10 +27,24 @@
C.IgniteMob()
if(C.dna && C.dna.check_mutation(HULK))
C.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk")
else if((C.status_flags & CANKNOCKDOWN) && !HAS_TRAIT(C, TRAIT_STUNIMMUNE))
C.apply_status_effect(STATUS_EFFECT_TASED, tase_duration)
else if(tase_duration && (C.status_flags & CANKNOCKDOWN) && !HAS_TRAIT(C, TRAIT_STUNIMMUNE))
C.apply_status_effect(strong_tase? STATUS_EFFECT_TASED : STATUS_EFFECT_TASED_WEAK, tase_duration)
addtimer(CALLBACK(C, /mob/living/carbon.proc/do_jitter_animation, jitter), 5)
/obj/item/projectile/energy/electrode/on_range() //to ensure the bolt sparks when it reaches the end of its range if it didn't hit a target yet
do_sparks(1, TRUE, src)
..()
/obj/item/projectile/energy/electrode/security
tase_duration = 30
knockdown = 0
stamina = 10
knockdown_stamoverride = 0
knockdown_stam_max = 0
strong_tase = FALSE
range = 12
/obj/item/projectile/energy/electrode/security/hos
knockdown = 100
knockdown_stamoverride = 30
knockdown_stam_max = null
@@ -216,6 +216,14 @@
..()
. = 1
/datum/reagent/medicine/rezadone/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
. = ..()
if(iscarbon(M))
var/mob/living/carbon/patient = M
if(reac_volume >= 5 && HAS_TRAIT_FROM(patient, TRAIT_HUSK, "burn") && patient.getFireLoss() < THRESHOLD_UNHUSK) //One carp yields 12u rezadone.
patient.cure_husk("burn")
patient.visible_message("<span class='nicegreen'>[patient]'s body rapidly absorbs moisture from the enviroment, taking on a more healthy appearance.")
/datum/reagent/medicine/spaceacillin
name = "Spaceacillin"
description = "Spaceacillin will prevent a patient from conventionally spreading any diseases they are currently infected with."
@@ -436,6 +444,10 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
if(show_message)
to_chat(M, "<span class='danger'>You feel your burns and bruises healing! It stings like hell!</span>")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine)
//Has to be at less than THRESHOLD_UNHUSK burn damage and have 100 synthflesh before unhusking. Corpses dont metabolize.
if(HAS_TRAIT_FROM(M, TRAIT_HUSK, "burn") && M.getFireLoss() < THRESHOLD_UNHUSK && M.reagents.has_reagent(/datum/reagent/medicine/synthflesh, 100))
M.cure_husk("burn")
M.visible_message("<span class='nicegreen'>Most of [M]'s burnt off or charred flesh has been restored.")
..()
/datum/reagent/medicine/synthflesh/overdose_start(mob/living/M)
@@ -982,7 +994,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
/datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L)
..()
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.5, blacklisted_movetypes=(FLYING|FLOATING))
/datum/reagent/medicine/stimulants/on_mob_end_metabolize(mob/living/L)
L.remove_movespeed_modifier(type)
@@ -423,18 +423,21 @@
else
unload_hypo(vial,user)
/obj/item/hypospray/mkii/verb/modes()
set name = "Toggle Application Mode"
set category = "Object"
set src in usr
var/mob/M = usr
switch(mode)
if(HYPO_SPRAY)
mode = HYPO_INJECT
to_chat(M, "[src] is now set to inject contents on application.")
if(HYPO_INJECT)
mode = HYPO_SPRAY
to_chat(M, "[src] is now set to spray contents on application.")
/obj/item/hypospray/mkii/AltClick(mob/living/user)
. = ..()
if(user.canUseTopic(src, FALSE))
switch(mode)
if(HYPO_SPRAY)
mode = HYPO_INJECT
to_chat(user, "[src] is now set to inject contents on application.")
if(HYPO_INJECT)
mode = HYPO_SPRAY
to_chat(user, "[src] is now set to spray contents on application.")
return TRUE
/obj/item/hypospray/mkii/examine(mob/user)
. = ..()
. += "<span class='notice'><b>Alt-Click</b> it to toggle its mode from spraying to injecting and vice versa.</span>"
#undef HYPO_SPRAY
#undef HYPO_INJECT
@@ -250,10 +250,10 @@
name = "Plant Data Disk"
desc = "A disk for storing plant genetic data."
id = "diskplantgene"
build_type = PROTOLATHE
build_type = PROTOLATHE | AUTOLATHE
materials = list(MAT_METAL=200, MAT_GLASS=100)
build_path = /obj/item/disk/plantgene
category = list("Electronics")
category = list("Electronics","Imported")
departmental_flags = DEPARTMENTAL_FLAG_SERVICE
/datum/design/roastingstick
+4
View File
@@ -60,6 +60,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
new /obj/item/stock_parts/manipulator(src)
new /obj/item/stock_parts/micro_laser(src)
new /obj/item/stock_parts/matter_bin(src)
new /obj/item/stock_parts/cell/high(src)
/obj/item/storage/part_replacer/bluespace/tier2
@@ -70,6 +71,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
new /obj/item/stock_parts/manipulator/nano(src)
new /obj/item/stock_parts/micro_laser/high(src)
new /obj/item/stock_parts/matter_bin/adv(src)
new /obj/item/stock_parts/cell/super(src)
/obj/item/storage/part_replacer/bluespace/tier3
@@ -80,6 +82,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
new /obj/item/stock_parts/manipulator/pico(src)
new /obj/item/stock_parts/micro_laser/ultra(src)
new /obj/item/stock_parts/matter_bin/super(src)
new /obj/item/stock_parts/cell/hyper(src)
/obj/item/storage/part_replacer/bluespace/tier4
@@ -90,6 +93,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
new /obj/item/stock_parts/manipulator/femto(src)
new /obj/item/stock_parts/micro_laser/quadultra(src)
new /obj/item/stock_parts/matter_bin/bluespace(src)
new /obj/item/stock_parts/cell/bluespace(src)
/obj/item/storage/part_replacer/cargo //used in a cargo crate
@@ -102,6 +102,12 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE)
var/gun_type = pick(GLOB.summoned_guns)
var/obj/item/gun/G = new gun_type(get_turf(H))
G.unlock()
var/datum/antagonist/survivalist/guns/our_antag_datum = H.mind.has_antag_datum(/datum/antagonist/survivalist/guns)
if(our_antag_datum)
var/datum/objective/hoard/O = new()
O.owner = H
O.set_target(G)
our_antag_datum.objectives += O
playsound(get_turf(H),'sound/magic/summon_guns.ogg', 50, 1)
var/in_hand = H.put_in_hands(G) // not always successful
@@ -128,6 +134,13 @@ GLOBAL_VAR_INIT(summon_magic_triggered, FALSE)
var/obj/item/M = new magic_type(get_turf(H))
playsound(get_turf(H),'sound/magic/summon_magic.ogg', 50, 1)
var/datum/antagonist/survivalist/magic/our_antag_datum = H.mind.has_antag_datum(/datum/antagonist/survivalist/magic)
if(istype(our_antag_datum))
var/datum/objective/hoard/O = new()
O.owner = H
O.set_target(M)
our_antag_datum.objectives += O
var/in_hand = H.put_in_hands(M)
to_chat(H, "<span class='warning'>\A [M] appears [in_hand ? "in your hand" : "at your feet"]!</span>")
+12 -3
View File
@@ -248,6 +248,7 @@
mutations = list(BLINDMUT)
duration = 300
sound = 'sound/magic/blind.ogg'
/obj/effect/proc_holder/spell/aoe_turf/repulse
name = "Repulse"
desc = "This spell throws everything around the user away."
@@ -266,15 +267,22 @@
action_icon_state = "repulse"
/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets,mob/user = usr, stun_amt = 50)
var/list/mobs = list()
var/list/objs = list()
var/list/thrownatoms = list()
var/atom/throwtarget
var/distfromcaster
playMagSound()
for(var/turf/T in targets) //Done this way so things don't get thrown all around hilariously.
for(var/atom/movable/AM in T)
thrownatoms += AM
for(var/mob/M in T)
mobs += M
for(var/obj/O in T)
objs += O
thrownatoms = mobs + objs //mobs first
var/safety = 50
for(var/am in thrownatoms)
if(!safety)
break
var/atom/movable/AM = am
if(AM == user || AM.anchored)
continue
@@ -299,6 +307,7 @@
M.Knockdown(stun_amt, override_hardstun = stun_amt * 0.2)
to_chat(M, "<span class='userdanger'>You're thrown back by [user]!</span>")
AM.throw_at(throwtarget, ((CLAMP((maxthrow - (CLAMP(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time.
safety--
/obj/effect/proc_holder/spell/aoe_turf/repulse/xeno //i fixed conflicts only to find out that this is in the WIZARD file instead of the xeno file?!
name = "Tail Sweep"
+1 -1
View File
@@ -51,7 +51,7 @@
clear_eye_trauma()
. = ..()
var/mob/living/carbon/C = .
if(C)
if(!QDELETED(C))
if(ishuman(C) && eye_color)
var/mob/living/carbon/human/H = C
H.eye_color = old_eye_color
+19
View File
@@ -57,3 +57,22 @@
/obj/item/pen/uplink/Initialize(mapload, owner, tc_amount = 20)
. = ..()
AddComponent(/datum/component/uplink, owner, TRUE, FALSE, null, tc_amount)
/obj/item/uplink/debug
name = "debug uplink"
/obj/item/uplink/debug/Initialize(mapload, owner, tc_amount = 9000)
. = ..()
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.name = "debug uplink"
hidden_uplink.debug = TRUE
/obj/item/uplink/nuclear/debug
name = "debug nuclear uplink"
/obj/item/uplink/nuclear/debug/Initialize(mapload, owner, tc_amount = 9000)
. = ..()
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
hidden_uplink.name = "debug nuclear uplink"
hidden_uplink.debug = TRUE
@@ -78,3 +78,9 @@
cost = 30
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
exclude_modes = list()
/datum/uplink_item/suits/thiefgloves
name = "Thieving Gloves"
desc = "A pair of gloves that are insulated and frictionless, allowing you to steal easily from anyone you see."
item = /obj/item/clothing/gloves/thief
cost = 4
-1
View File
@@ -20,7 +20,6 @@
/obj/item/clothing/under/rank/security/grey = 5,
/obj/item/clothing/under/pants/khaki = 5)
premium = list(/obj/item/clothing/under/rank/security/navyblue = 5,
/obj/item/clothing/suit/security/officer = 5,
/obj/item/clothing/head/beret/sec/navyofficer = 5)
refill_canister = /obj/item/vending_refill/wardrobe/sec_wardrobe
-3
View File
@@ -533,9 +533,6 @@
//Yes, it's ""safe"" to drop items here
/obj/belly/AllowDrop()
return TRUE
/*
/obj/belly/onDropInto(var/atom/movable/AM)
return null */
//Handle a mob struggling
// Called from /mob/living/carbon/relaymove()
-17
View File
@@ -71,14 +71,6 @@
/////////////
// Some special treatment
/////////////
/*
//PDAs need to lose their ID to not take it with them, so we can get a digested ID
/obj/item/pda/digest_act(var/atom/movable/item_storage = null)
if(id)
id = null
. = ..()
*/
/obj/item/reagent_containers/food/digest_act(var/atom/movable/item_storage = null)
if(isbelly(item_storage))
@@ -92,15 +84,6 @@
. = ..()
/*
/obj/item/holder/digest_act(var/atom/movable/item_storage = null)
for(var/mob/living/M in contents)
if(item_storage)
M.forceMove(item_storage)
held_mob = null
. = ..() */
/obj/item/organ/digest_act(var/atom/movable/item_storage = null)
if((. = ..()))
. += 70 //Organs give a little more
-6
View File
@@ -404,10 +404,4 @@
taste_message += "they haven't bothered to set their flavor text"
else
taste_message += "a plain old normal [src]"
/* if(ishuman(src))
var/mob/living/carbon/human/H = src
if(H.touching.reagent_list.len) //Just the first one otherwise I'll go insane.
var/datum/reagent/R = H.touching.reagent_list[1]
taste_message += " You also get the flavor of [R.taste_description] from something on them"*/
return taste_message
-30
View File
@@ -30,33 +30,3 @@
H.visible_message("<span class='danger'>[H] contracts strangely, spewing out contents on the floor!</span>", \
"<span class='userdanger'>You spew out everything inside you on the floor!</span>")
return BULLET_ACT_HIT
////////////////////////// Anti-Noms Drugs //////////////////////////
/*
/datum/reagent/medicine/ickypak
name = "Ickypak"
description = "A foul-smelling green liquid, for inducing muscle contractions to expel accidentally ingested things."
reagent_state = LIQUID
color = "#0E900E"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
/datum/reagent/medicine/ickypak/on_mob_life(var/mob/living/M, method=INGEST)
if(prob(10))
M.visible_message("<span class='danger'>[M] retches!</span>", \
"<span class='userdanger'>You don't feel good...</span>")
for(var/I in M.vore_organs)
var/datum/belly/B = M.vore_organs[I]
for(var/atom/movable/A in B.internal_contents)
if(prob(55))
playsound(M, 'sound/effects/splat.ogg', 50, 1)
B.release_specific_contents(A)
M.visible_message("<span class='danger'>[M] contracts strangely, spewing out something!</span>", \
"<span class='userdanger'>You spew out something from inside you!</span>")
return ..()
/datum/chemical_reaction/ickypak
name = "Ickypak"
id = /datum/reagent/medicine/ickypak
results = list(/datum/reagent/medicine/ickypak = 2)
required_reagents = list(/datum/reagent/chlorine = 2 , /datum/reagent/oil = 1) */
@@ -1,63 +0,0 @@
//
// Gravity Pull effect which draws in movable objects to its center.
// In this case, "number" refers to the range. directions is ignored.
//
/datum/effect/effect/system/grav_pull
var/pull_radius = 3
var/pull_anchored = 0
var/break_windows = 0
/datum/effect/effect/system/grav_pull/set_up(range, num, loca)
pull_radius = range
number = num
if(istype(loca, /turf/))
location = loca
else
location = get_turf(loca)
/datum/effect/effect/system/grav_pull/start()
spawn(0)
if(holder)
src.location = get_turf(holder)
for(var/i=0, i < number, i++)
do_pull()
sleep(25)
/datum/effect/effect/system/grav_pull/proc/do_pull()
//following is adapted from supermatter and singulo code
if(defer_powernet_rebuild != 2)
defer_powernet_rebuild = 1
// Let's just make this one loop.
for(var/atom/X in orange(pull_radius, location))
// Movable atoms only
if(istype(X, /atom/movable))
if(istype(X, /obj/effect/overlay)) continue
if(X && !istype(X, /mob/living/carbon/human))
if(break_windows && istype(X, /obj/structure/window)) //shatter windows
var/obj/structure/window/W = X
W.ex_act(2.0)
if(istype(X, /obj))
var/obj/O = X
if(O.anchored)
if (!pull_anchored) continue // Don't pull anchored stuff unless configured
step_towards(X, location) // step just once if anchored
continue
step_towards(X, location) // Step twice
step_towards(X, location)
else if(istype(X,/mob/living/carbon/human))
var/mob/living/carbon/human/H = X
if(istype(H.shoes,/obj/item/clothing/shoes/magboots))
var/obj/item/clothing/shoes/magboots/M = H.shoes
if(M.magpulse)
step_towards(H, location) //step just once with magboots
continue
step_towards(H, location) //step twice
step_towards(H, location)
if(defer_powernet_rebuild != 2)
defer_powernet_rebuild = 0
return
@@ -1,34 +0,0 @@
// Micro Holders - Extends /obj/item/holder
/obj/item/holder/micro
name = "micro"
desc = "Another crewmember, small enough to fit in your hand."
icon_state = "micro"
slot_flags = SLOT_FEET | SLOT_HEAD | SLOT_ID
w_class = 2
item_icons = null // Override value from parent. We don't have magic sprites.
pixel_y = 0 // Override value from parent.
/obj/item/holder/micro/examine(var/mob/user)
. = list()
for(var/mob/living/M in contents)
. += M.examine(user)
/obj/item/holder/MouseDrop(mob/M as mob)
..()
if(M != usr) return
if(usr == src) return
if(!Adjacent(usr)) return
if(istype(M,/mob/living/silicon/ai)) return
for(var/mob/living/carbon/human/O in contents)
O.show_inv(usr)
/obj/item/holder/micro/attack_self(var/mob/living/user)
for(var/mob/living/carbon/human/M in contents)
M.help_shake_act(user)
/obj/item/holder/micro/update_state()
// If any items have been dropped by contained mob, drop them to floor.
for(var/obj/O in contents)
O.forceMove(get_turf(src))
..()
-207
View File
@@ -1,207 +0,0 @@
/*
//these aren't defines so they can stay in this file
GLOBAL_VAR_CONST(SIZESCALE_HUGE, 2)
GLOBAL_VAR_CONST(SIZESCALE_BIG, 1.5)
GLOBAL_VAR_CONST(SIZESCALE_NORMAL, 1)
GLOBAL_VAR_CONST(SIZESCALE_SMALL, 0.85)
GLOBAL_VAR_CONST(SIZESCALE_TINY, 0.60)
GLOBAL_VAR_CONST(SIZESCALE_A_HUGEBIG, (GLOB.SIZESCALE_HUGE + GLOB.SIZESCALE_BIG) / 2)
GLOBAL_VAR_CONST(SIZESCALE_A_BIGNORMAL, (GLOB.SIZESCALE_BIG + GLOB.SIZESCALE_NORMAL) / 2)
GLOBAL_VAR_CONST(SIZESCALE_A_NORMALSMALL,(GLOB.SIZESCALE_NORMAL + GLOB.SIZESCALE_SMALL) / 2)
GLOBAL_VAR_CONST(SIZESCALE_A_SMALLTINY,(GLOB.SIZESCALE_SMALL + GLOB.SIZESCALE_TINY) / 2)
*/
// Adding needed defines to /mob/living
// Note: Polaris had this on /mob/living/carbon/human We need it higher up for animals and stuff.
/mob/living
var/size_multiplier = 1 //multiplier for the mob's icon size
// Define holder_type on types we want to be scoop-able
//mob/living/carbon/human
// holder_type = /obj/item/holder/micro
/**
* Scale up the size of a mob's icon by the size_multiplier.
* NOTE: mob/living/carbon/human/update_transform() has a more complicated system and
* is already applying this transform. BUT, it does not call ..()
* as long as that is true, we should be fine. If that changes we need to
* re-evaluate.
*/
/mob/living/update_transform()
ASSERT(!iscarbon(src))
var/matrix/M = matrix()
M.Scale(size_multiplier)
M.Translate(0, 16*(size_multiplier-1))
src.transform = M
/**
* Get the effective size of a mob.
* Currently this is based only on size_multiplier for micro/macro stuff,
* but in the future we may also incorporate the "mob_size", so that
* a macro mouse is still only effectively "normal" or a micro dragon is still large etc.
*/
/mob/living/proc/get_effective_size()
return src.size_multiplier
/**
* Resizes the mob immediately to the desired mod, animating it growing/shrinking.
* It can be used by anything that calls it.
*/
/mob/living/proc/sizescale(var/new_size)
var/matrix/sizescale = matrix() // Defines the matrix to change the player's size
sizescale.Scale(new_size) //Change the size of the matrix
if(new_size >= SIZESCALE_NORMAL)
sizescale.Translate(0, -1 * (1 - new_size) * 16) //Move the player up in the tile so their feet align with the bottom
animate(src, transform = sizescale, time = 5) //Animate the player resizing
size_multiplier = new_size //Change size_multiplier so that other items can interact with them
/*
* Verb proc for a command that lets players change their size OOCly.
* Ace was here! Redid this a little so we'd use math for shrinking characters. This is the old code.
/mob/living/proc/set_size()
set name = "Set Character Size"
set category = "Vore"
var/nagmessage = "DO NOT ABUSE THESE COMMANDS. They are not here for you to play with. \
We were originally going to remove them but kept them for popular demand. \
Do not abuse their existence outside of ERP scenes where they apply, \
or reverting OOCly unwanted changes like someone lolshooting the crew with a shrink ray. -Ace"
var/size_name = input(nagmessage, "Pick a Size") in player_sizes_list
if (size_name && player_sizes_list[size_name])
src.sizescale(player_sizes_list[size_name])
message_admins("[key_name(src)] used the sizescale command in-game to be [size_name]. \
([src ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>" : "null"])")
/** Add the set_size() proc to usable verbs. */
/hook/living_new/proc/sizescale_setup(mob/living/M)
M.verbs += /mob/living/proc/set_size
return 1
* Attempt to scoop up this mob up into M's hands, if the size difference is large enough.
* @return false if normal code should continue, 1 to prevent normal code.
/mob/living/proc/attempt_to_scoop(var/mob/living/carbon/human/M)
if(!istype(M))
return 0;
if(M.buckled)
usr << "<span class='notice'>You have to unbuckle \the [M] before you pick them up.</span>"
return 0
if(M.get_effective_size() - src.get_effective_size() >= 0.75)
var/obj/item/holder/m_holder = get_scooped(M)
if (m_holder)
return 1
else
return 0; // Unable to scoop, let other code run
*/
/*
* Handle bumping into someone with helping intent.
* Called from /mob/living/Bump() in the 'brohugs all around' section.
* @return false if normal code should continue, 1 to prevent normal code.
* // TODO - can the now_pushing = 0 be moved up? What does it do anyway?
*/
/mob/living/proc/handle_micro_bump_helping(var/mob/living/tmob)
if(src.get_effective_size() <= SIZESCALE_A_SMALLTINY && tmob.get_effective_size() <= SIZESCALE_A_SMALLTINY)
// Both small! Go ahead and
now_pushing = 0
src.forceMove(tmob.loc)
return 1
if(abs(src.get_effective_size() - tmob.get_effective_size()) >= 0.20)
now_pushing = 0
src.forceMove(tmob.loc)
if(src.get_effective_size() > tmob.get_effective_size())
/* var/mob/living/carbon/human/tmob = src
if(istype(tmob) && istype(tmob.tail_style, /datum/sprite_accessory/tail/taur/naga))
src << "You carefully slither around [tmob]."
M << "[src]'s huge tail slithers past beside you!"
else
*/
src.forceMove(tmob.loc)
src << "You carefully step over [tmob]."
tmob << "[src] steps over you carefully!"
if(tmob.get_effective_size() > src.get_effective_size())
/* var/mob/living/carbon/human/M = M
if(istype(M) && istype(M.tail_style, /datum/sprite_accessory/tail/taur/naga))
src << "You jump over [M]'s thick tail."
M << "[src] bounds over your tail."
else
*/
src.forceMove(tmob.loc)
src << "You run between [tmob]'s legs."
tmob << "[src] runs between your legs."
return 1
/**
* Handle bumping into someone without mutual help intent.
* Called from /mob/living/Bump()
* NW was here, adding even more options for stomping!
*
* @return false if normal code should continue, 1 to prevent normal code.
*/
/mob/living/proc/handle_micro_bump_other(var/mob/living/tmob)
ASSERT(isliving(tmob)) // Baby don't hurt me
if(src.a_intent == "disarm" && src.canmove && !src.buckled)
// If bigger than them by at least 0.75, move onto them and print message.
if((src.get_effective_size() - tmob.get_effective_size()) >= 0.20)
now_pushing = 0
src.forceMove(tmob.loc)
tmob.Stun(4)
/*
var/mob/living/carbon/human/H = src
if(istype(H) && istype(H.tail_style, /datum/sprite_accessory/tail/taur/naga))
src << "You carefully squish [tmob] under your tail!"
tmob << "[src] pins you under their tail!"
else
*/
src << "You pin [tmob] beneath your foot!"
tmob << "[src] pins you beneath their foot!"
return 1
if(src.a_intent == "harm" && src.canmove && !src.buckled)
if((src.get_effective_size() - tmob.get_effective_size()) >= 0.20)
now_pushing = 0
src.forceMove(tmob.loc)
tmob.adjustStaminaLoss(35)
tmob.adjustBruteLoss(5)
/* var/mob/living/carbon/human/M = src
if(istype(M) && istype(M.tail_style, /datum/sprite_accessory/tail/taur/naga))
src << "You steamroller over [tmob] with your heavy tail!"
tmob << "[src] ploughs you down mercilessly with their heavy tail!"
else
*/
src << "You bring your foot down heavily upon [tmob]!"
tmob << "[src] steps carelessly on your body!"
return 1
// until I figure out grabbing micros with the godawful pull code...
if(src.a_intent == "grab" && src.canmove && !src.buckled)
if((src.get_effective_size() - tmob.get_effective_size()) >= 0.20)
now_pushing = 0
tmob.adjustStaminaLoss(15)
src.forceMove(tmob.loc)
src << "You press [tmob] beneath your foot!"
tmob << "[src] presses you beneath their foot!"
/*
var/mob/living/carbon/human/M = src
if(istype(M) && !M.shoes)
// User is a human (capable of scooping) and not wearing shoes! Scoop into foot slot!
equip_to_slot_if_possible(tmob.get_scooped(M), slot_shoes, 0, 1)
if(istype(M.tail_style, /datum/sprite_accessory/tail/taur/naga))
src << "You wrap up [tmob] with your powerful tail!"
tmob << "[src] binds you with their powerful tail!"
else
src << "You clench your toes around [tmob]'s body!"
tmob << "[src] grabs your body with their toes!"
else if(istype(M) && istype(M.tail_style, /datum/sprite_accessory/tail/taur/naga))
src << "You carefully squish [tmob] under your tail!"
tmob << "[src] pins you under their tail!"
else
src << "You pin [tmob] beneath your foot!"
tmob << "[src] pins you beneath their foot!"
return 1
*/
-110
View File
@@ -1,110 +0,0 @@
////////////////////////////
/// shrinking serum ///
////////////////////////////
/datum/reagent/medicine/macrocillin
name = "Macrocillin"
description = "Glowing yellow liquid."
reagent_state = LIQUID
color = "#FFFF00" // rgb: 255, 255, 0
overdose_threshold = 20
/datum/reagent/medicine/macrocillin/on_mob_life(mob/living/M, method=INGEST)
for(var/size in list(SIZESCALE_SMALL, SIZESCALE_NORMAL, SIZESCALE_BIG, SIZESCALE_HUGE))
if(M.size_multiplier < size)
M.sizescale(size)
M << "<font color='green'>You grow!</font>"
break
if(M.reagents.has_reagent(/datum/reagent/medicine/macrocillin))
M.reagents.remove_reagent(/datum/reagent/medicine/macrocillin, 20)
..()
/datum/reagent/medicine/microcillin
name = "Microcillin"
description = "Murky purple liquid."
reagent_state = LIQUID
color = "#800080"
overdose_threshold = 20
/datum/reagent/microcillin/on_mob_life(mob/living/M, method=INGEST)
for(var/size in list(SIZESCALE_BIG, SIZESCALE_NORMAL, SIZESCALE_SMALL, SIZESCALE_TINY))
if(M.size_multiplier > size)
M.sizescale(size)
M << "<span class='alert'>You shrink!</span>"
break;
if(M.reagents.has_reagent(/datum/reagent/medicine/microcillin))
M.reagents.remove_reagent(/datum/reagent/medicine/microcillin, 20)
..()
/datum/reagent/medicine/normalcillin
name = "Normalcillin"
description = "Translucent cyan liquid."
reagent_state = LIQUID
color = "#00FFFF"
overdose_threshold = 20
/datum/reagent/medicine/normalcillin/on_mob_life(mob/living/M, method=INGEST)
if(M.size_multiplier > SIZESCALE_BIG)
M.sizescale(SIZESCALE_BIG)
M << "<span class='alert'>You shrink!</span>"
else if(M.size_multiplier > SIZESCALE_NORMAL)
M.sizescale(SIZESCALE_NORMAL)
M << "<span class='alert'>You shrink!</span>"
else if(M.size_multiplier < SIZESCALE_NORMAL)
M.sizescale(SIZESCALE_NORMAL)
M << "<font color='green'>You grow!</font>"
else if(M.size_multiplier < SIZESCALE_SMALL)
M.sizescale(SIZESCALE_SMALL)
M << "<font color='green'>You grow!</font>"
if(M.reagents.has_reagent(/datum/reagent/medicine/normalcillin))
M.reagents.remove_reagent(/datum/reagent/medicine/normalcillin, 20)
..()
/datum/reagent/medicine/sizeoxadone
name = "Sizeoxadone"
description = "A volatile liquid used as a precursor to size-altering chemicals. Causes dizziness if taken unprocessed."
reagent_state = LIQUID
color = "#1E90FF"
overdose_threshold = 30
metabolization_rate = 0.8 * REAGENTS_METABOLISM
/datum/reagent/sizeoxadone/on_mob_life(var/mob/living/carbon/M, var/removed)
if(M.hallucination < volume && prob(20))
M.hallucination += 5
if(!M.confused) M.confused = 1
M.confused = max(M.confused, 20)
return
/datum/reagent/medicine/sizeoxadone/overdose_process(mob/living/M)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1)
M.adjustToxLoss(1)
..()
. = 1
////////////////////////// Anti-Noms Drugs //////////////////////////
/datum/reagent/medicine/ickypak
name = "Ickypak"
description = "A foul-smelling green liquid, for inducing muscle contractions to expel accidentally ingested things."
reagent_state = LIQUID
color = "#0E900E"
metabolization_rate = 0.25 * REAGENTS_METABOLISM
/datum/reagent/medicine/ickypak/on_mob_life(var/mob/living/M, method=INGEST)
..()
if(M.hallucination < volume && prob(20))
M.hallucination += 5
M.adjustToxLoss(-5)
for(var/I in M.vore_organs)
var/datum/belly/B = M.vore_organs[I]
for(var/atom/movable/A in B.internal_contents)
if(prob(55))
playsound(M, 'sound/effects/splat.ogg', 50, 1)
B.release_vore_contents(A)
..()
. = 1
-173
View File
@@ -1,173 +0,0 @@
//
// Size Gun
//
/*
/obj/item/gun/energy/sizegun
name = "shrink ray"
desc = "A highly advanced ray gun with two settings: Shrink and Grow. Warning: Do not insert into mouth."
icon = 'icons/obj/gun_vr.dmi'
icon_state = "sizegun-shrink100" // Someone can probably do better. -Ace
item_state = null //so the human update icon uses the icon_state instead
fire_sound = 'sound/weapons/wave.ogg'
charge_cost = 100
projectile_type = /obj/item/projectile/beam/shrinklaser
modifystate = "sizegun-shrink"
selfcharge = EGUN_SELFCHARGE
firemodes = list(
list(mode_name = "grow",
projectile_type = /obj/item/projectile/beam/growlaser,
modifystate = "sizegun-grow",
fire_sound = 'sound/weapons/pulse3.ogg'
),
list(mode_name = "shrink",
projectile_type = /obj/item/projectile/beam/shrinklaser,
modifystate = "sizegun-shrink",
fire_sound = 'sound/weapons/wave.ogg'
))
//
// Beams for size gun
//
// tracers TBD
/obj/item/projectile/beam/shrinklaser
name = "shrink beam"
icon_state = "xray"
nodamage = 1
damage = 0
check_armour = "laser"
muzzle_type = /obj/effect/projectile/xray/muzzle
tracer_type = /obj/effect/projectile/xray/tracer
impact_type = /obj/effect/projectile/xray/impact
/obj/item/projectile/beam/shrinklaser/on_hit(var/atom/target, var/blocked = 0)
. = ..()
if(isliving(target))
var/mob/living/M = target
switch(M.size_multiplier)
if(SIZESCALE_HUGE to INFINITY)
M.sizescale(SIZESCALE_BIG)
if(SIZESCALE_BIG to SIZESCALE_HUGE)
M.sizescale(SIZESCALE_NORMAL)
if(SIZESCALE_NORMAL to SIZESCALE_BIG)
M.sizescale(SIZESCALE_SMALL)
if((0 - INFINITY) to SIZESCALE_NORMAL)
M.sizescale(SIZESCALE_TINY)
M.update_transform()
return BULLET_ACT_HIT
/obj/item/projectile/beam/growlaser
name = "growth beam"
icon_state = "bluelaser"
nodamage = 1
damage = 0
check_armour = "laser"
muzzle_type = /obj/effect/projectile/laser_blue/muzzle
tracer_type = /obj/effect/projectile/laser_blue/tracer
impact_type = /obj/effect/projectile/laser_blue/impact
/obj/item/projectile/beam/growlaser/on_hit(var/atom/target, var/blocked = 0)
. = ..()
if(isliving(target))
var/mob/living/M = target
switch(M.size_multiplier)
if(SIZESCALE_BIG to SIZESCALE_HUGE)
M.sizescale(SIZESCALE_HUGE)
if(SIZESCALE_NORMAL to SIZESCALE_BIG)
M.sizescale(SIZESCALE_BIG)
if(SIZESCALE_SMALL to SIZESCALE_NORMAL)
M.sizescale(SIZESCALE_NORMAL)
if((0 - INFINITY) to SIZESCALE_TINY)
M.sizescale(SIZESCALE_SMALL)
M.update_transform()
return BULLET_ACT_HIT
*/
datum/design/sizeray
name = "Size Ray"
desc = "Abuse bluespace tech to alter living matter scale."
id = "sizeray"
build_type = PROTOLATHE
materials = list(MAT_METAL = 1000, MAT_GLASS = 1000, MAT_DIAMOND = 2500, MAT_URANIUM = 2500, MAT_TITANIUM = 1000)
build_path = /obj/item/gun/energy/laser/sizeray
category = list("Weapons")
/obj/item/projectile/sizeray
name = "sizeray beam"
icon_state = "omnilaser"
hitsound = null
damage = 0
damage_type = STAMINA
flag = "laser"
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
/obj/item/projectile/sizeray/shrinkray
icon_state="bluelaser"
/obj/item/projectile/sizeray/growthray
icon_state="laser"
/obj/item/projectile/sizeray/shrinkray/on_hit(var/atom/target, var/blocked = 0)
. = ..()
if(isliving(target))
var/mob/living/M = target
switch(M.size_multiplier)
if(SIZESCALE_HUGE to INFINITY)
M.sizescale(SIZESCALE_BIG)
if(SIZESCALE_BIG to SIZESCALE_HUGE)
M.sizescale(SIZESCALE_NORMAL)
if(SIZESCALE_NORMAL to SIZESCALE_BIG)
M.sizescale(SIZESCALE_SMALL)
if((0 - INFINITY) to SIZESCALE_NORMAL)
M.sizescale(SIZESCALE_TINY)
M.update_transform()
return BULLET_ACT_
/obj/item/projectile/sizeray/growthray/on_hit(var/atom/target, var/blocked = 0)
. = ..()
if(isliving(target))
var/mob/living/M = target
switch(M.size_multiplier)
if(SIZESCALE_BIG to SIZESCALE_HUGE)
M.sizescale(SIZESCALE_HUGE)
if(SIZESCALE_NORMAL to SIZESCALE_BIG)
M.sizescale(SIZESCALE_BIG)
if(SIZESCALE_SMALL to SIZESCALE_NORMAL)
M.sizescale(SIZESCALE_NORMAL)
if((0 - INFINITY) to SIZESCALE_TINY)
M.sizescale(SIZESCALE_SMALL)
M.update_transform()
return BULLET_ACT_HIT
/obj/item/ammo_casing/energy/laser/growthray
projectile_type = /obj/item/projectile/sizeray/growthray
select_name = "Growth"
/obj/item/ammo_casing/energy/laser/shrinkray
projectile_type = /obj/item/projectile/sizeray/shrinkray
select_name = "Shrink"
//Gun here
/obj/item/gun/energy/laser/sizeray
name = "size ray"
icon_state = "bluetag"
desc = "Size manipulator using bluespace breakthroughs."
item_state = null //so the human update icon uses the icon_state instead.
ammo_type = list(/obj/item/ammo_casing/energy/laser/shrinkray, /obj/item/ammo_casing/energy/laser/growthray)
selfcharge = EGUN_SELFCHARGE
charge_delay = 5
ammo_x_offset = 2
clumsy_check = 1
attackby(obj/item/W, mob/user)
if(W==src)
if(icon_state=="bluetag")
icon_state="redtag"
ammo_type = list(/obj/item/ammo_casing/energy/laser/growthray)
else
icon_state="bluetag"
ammo_type = list(/obj/item/ammo_casing/energy/laser/shrinkray)
return ..()