Merge branch 'Citadel-Station-13:master' into master
@@ -24,3 +24,11 @@
|
||||
#define POLICYCONFIG_ON_PYROCLASTIC_SENTIENT "PYROCLASTIC_SLIME"
|
||||
/// Displayed to pAIs on spawn
|
||||
#define POLICYCONFIG_PAI "PAI_SPAWN"
|
||||
/// displayed to lavaland elites on spawn, overriding the default if set
|
||||
#define POLICYCONFIG_ELITE_SPAWN "ELITE_FAUNA_SPAWN"
|
||||
/// displayed to lavaland elites on sentience potion, overriding the default if set
|
||||
#define POLICYCONFIG_ELITE_SENTIENCE "ELITE_FAUNA_SENTIENCE"
|
||||
/// displayed to lavaland elites on winning the fight, overriding the default if set
|
||||
#define POLICYCONFIG_ELITE_WIN "ELITE_FAUNA_WIN"
|
||||
/// displayed to prisoners on spawn, overriding the default if set
|
||||
#define POLICYCONFIG_JOB_PRISONER "JOB_PRISONER"
|
||||
|
||||
@@ -12,3 +12,16 @@ GLOBAL_LIST_INIT(typecache_stack, typecacheof(/obj/item/stack))
|
||||
GLOBAL_LIST_INIT(typecache_machine_or_structure, typecacheof(list(/obj/machinery, /obj/structure)))
|
||||
|
||||
GLOBAL_LIST_INIT(freezing_objects, typecacheof(list(/obj/structure/closet/crate/freezer, /obj/structure/closet/secure_closet/freezer, /obj/structure/bodycontainer, /obj/item/autosurgeon, /obj/machinery/smartfridge/organ))) //list of all cold objects, that freeze organs when inside
|
||||
|
||||
GLOBAL_LIST_EMPTY(typecaches)
|
||||
|
||||
/**
|
||||
* Makes a typecache of a single typecache
|
||||
*
|
||||
* Obviously in BYOND we don't have the efficiency around here to have proper enforcement so
|
||||
* If you use this you better know what you're doing. The list you get back is globally cached and if it's modified, you might break multiple things.
|
||||
*/
|
||||
/proc/single_path_typecache_immutable(path)
|
||||
if(!GLOB.typecaches[path])
|
||||
GLOB.typecaches[path] = typecacheof(path)
|
||||
return GLOB.typecaches[path]
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/datum/action/item_action/initialize_ninja_suit
|
||||
name = "Toggle ninja suit"
|
||||
|
||||
/datum/action/item_action/ninjasmoke
|
||||
name = "Smoke Bomb"
|
||||
desc = "Blind your enemies momentarily with a well-placed smoke bomb."
|
||||
button_icon_state = "smoke"
|
||||
icon_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
|
||||
/datum/action/item_action/ninjaboost
|
||||
name = "Adrenaline Boost"
|
||||
desc = "Inject a secret chemical that will counteract all movement-impairing effect."
|
||||
button_icon_state = "repulse"
|
||||
icon_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
required_mobility_flags = NONE
|
||||
|
||||
/datum/action/item_action/ninjapulse
|
||||
name = "EM Burst (25E)"
|
||||
desc = "Disable any nearby technology with an electro-magnetic pulse."
|
||||
button_icon_state = "emp"
|
||||
icon_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
|
||||
/datum/action/item_action/ninjastar
|
||||
name = "Create Throwing Stars (1E)"
|
||||
desc = "Creates some throwing stars"
|
||||
button_icon_state = "throwingstar"
|
||||
icon_icon = 'icons/obj/items_and_weapons.dmi'
|
||||
|
||||
/datum/action/item_action/ninjanet
|
||||
name = "Energy Net (20E)"
|
||||
desc = "Captures a fallen opponent in a net of energy. Will teleport them to a holding facility after 30 seconds."
|
||||
button_icon_state = "energynet"
|
||||
icon_icon = 'icons/effects/effects.dmi'
|
||||
|
||||
/datum/action/item_action/ninja_sword_recall
|
||||
name = "Recall Energy Katana (Variable Cost)"
|
||||
desc = "Teleports the Energy Katana linked to this suit to its wearer, cost based on distance."
|
||||
button_icon_state = "energy_katana"
|
||||
icon_icon = 'icons/obj/items_and_weapons.dmi'
|
||||
|
||||
/datum/action/item_action/ninja_stealth
|
||||
name = "Toggle Stealth"
|
||||
desc = "Toggles stealth mode on and off."
|
||||
button_icon_state = "ninja_cloak"
|
||||
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
|
||||
|
||||
/datum/action/item_action/toggle_glove
|
||||
name = "Toggle interaction"
|
||||
desc = "Switch between normal interaction and drain mode."
|
||||
button_icon_state = "s-ninjan"
|
||||
icon_icon = 'icons/obj/clothing/gloves.dmi'
|
||||
@@ -8,6 +8,7 @@
|
||||
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
|
||||
ambientsounds = RUINS
|
||||
sound_environment = SOUND_ENVIRONMENT_STONEROOM
|
||||
var/valid_territory = FALSE // hey so what if we did not allow things like cult summons to appear on ruins
|
||||
|
||||
|
||||
/area/ruin/unpowered
|
||||
|
||||
@@ -669,7 +669,6 @@
|
||||
var/mob/living/carbon/human/Ninja = create_space_ninja(spawn_loc)
|
||||
Mind.transfer_to(Ninja)
|
||||
var/datum/antagonist/ninja/ninjadatum = new
|
||||
ninjadatum.helping_station = pick(TRUE,FALSE)
|
||||
Mind.add_antag_datum(ninjadatum)
|
||||
|
||||
if(Ninja.mind != Mind) //something has gone wrong!
|
||||
|
||||
@@ -582,3 +582,14 @@ Class Procs:
|
||||
|
||||
/obj/machinery/rust_heretic_act()
|
||||
take_damage(500, BRUTE, "melee", 1)
|
||||
|
||||
/**
|
||||
* Alerts the AI that a hack is in progress.
|
||||
*
|
||||
* Sends all AIs a message that a hack is occurring. Specifically used for space ninja tampering as this proc was originally in the ninja files.
|
||||
* However, the proc may also be used elsewhere.
|
||||
*/
|
||||
/obj/machinery/proc/AI_notify_hack()
|
||||
var/alertstr = "<span class='userdanger'>Network Alert: Hacking attempt detected[get_area(src)?" in [get_area_name(src, TRUE)]":". Unable to pinpoint location"].</span>"
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.player_list)
|
||||
to_chat(AI, alertstr)
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
/obj/item/dice/d100
|
||||
)
|
||||
|
||||
/obj/item/storage/dice/ComponentInitialize()
|
||||
. = ..()
|
||||
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
|
||||
STR.can_hold = single_path_typecache_immutable(/obj/item/dice)
|
||||
|
||||
/obj/item/storage/dice/PopulateContents()
|
||||
new /obj/item/dice/d4(src)
|
||||
new /obj/item/dice/d6(src)
|
||||
|
||||
@@ -615,9 +615,9 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
name = "throwing star"
|
||||
desc = "An ancient weapon still used to this day, due to its ease of lodging itself into its victim's body parts."
|
||||
icon_state = "throwingstar"
|
||||
item_state = "eshield0"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
||||
item_state = "throwingstar"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
force = 2
|
||||
throwforce = 10 //10 + 2 (WEIGHT_CLASS_SMALL) * 4 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = 18 damage on hit due to guaranteed embedding
|
||||
throw_speed = 4
|
||||
@@ -630,8 +630,10 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/obj/item/throwing_star/stamina
|
||||
name = "shock throwing star"
|
||||
name = "energy throwing star"
|
||||
desc = "An aerodynamic disc designed to cause excruciating pain when stuck inside fleeing targets, hopefully without causing fatal harm."
|
||||
icon_state = "energystar"
|
||||
item_state = "energystar"
|
||||
throwforce = 5
|
||||
embedding = list("pain_chance" = 5, "embed_chance" = 100, "fall_chance" = 0, "jostle_chance" = 10, "pain_stam_pct" = 0.8, "jostle_pain_mult" = 3)
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
//returns the damage value of the attack after processing the obj's various armor protections
|
||||
/obj/proc/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir, armour_penetration = 0)
|
||||
if(damage_flag == MELEE && damage_amount < damage_deflection)
|
||||
if(damage_flag == "melee" && damage_amount < damage_deflection) // TODO: Refactor armor datums and types entirely jfc
|
||||
return 0
|
||||
switch(damage_type)
|
||||
if(BRUTE)
|
||||
|
||||
@@ -266,8 +266,8 @@
|
||||
return TRUE
|
||||
|
||||
/datum/admins/proc/makeSpaceNinja()
|
||||
new /datum/round_event/ghost_role/ninja()
|
||||
return 1
|
||||
new /datum/round_event/ghost_role/space_ninja()
|
||||
return TRUE
|
||||
|
||||
// DEATH SQUADS
|
||||
/datum/admins/proc/makeDeathsquad()
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
/datum/antagonist/ninja
|
||||
name = "Ninja"
|
||||
antagpanel_category = "Ninja"
|
||||
job_rank = ROLE_NINJA
|
||||
show_name_in_check_antagonists = TRUE
|
||||
show_to_ghosts = TRUE
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
threat = 8
|
||||
var/helping_station = FALSE
|
||||
var/give_objectives = TRUE
|
||||
var/give_equipment = TRUE
|
||||
|
||||
/datum/antagonist/ninja/threat()
|
||||
return helping_station ? -(..()) : ..()
|
||||
|
||||
/datum/antagonist/ninja/apply_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
update_ninja_icons_added(M)
|
||||
|
||||
/datum/antagonist/ninja/remove_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
update_ninja_icons_removed(M)
|
||||
|
||||
/datum/antagonist/ninja/proc/equip_space_ninja(mob/living/carbon/human/H = owner.current)
|
||||
return H.equipOutfit(/datum/outfit/ninja)
|
||||
|
||||
/datum/antagonist/ninja/proc/addMemories()
|
||||
antag_memory += "I am an elite mercenary assassin of the mighty Spider Clan. A <font color='red'><B>SPACE NINJA</B></font>!<br>"
|
||||
antag_memory += "Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by clicking the initialize UI button, to use abilities like stealth)!<br>"
|
||||
antag_memory += "Officially, [helping_station?"Nanotrasen":"The Syndicate"] are my employer.<br>"
|
||||
|
||||
/datum/antagonist/ninja/proc/addObjectives(quantity = 6)
|
||||
var/list/possible_targets = list()
|
||||
for(var/datum/mind/M in SSticker.minds)
|
||||
if(M.current && M.current.stat != DEAD)
|
||||
if(ishuman(M.current))
|
||||
if(M.special_role)
|
||||
possible_targets[M] = 0 //bad-guy
|
||||
else if(M.assigned_role in GLOB.command_positions)
|
||||
possible_targets[M] = 1 //good-guy
|
||||
|
||||
var/list/possible_objectives = list(1,2,3,4)
|
||||
|
||||
while(objectives.len < quantity)
|
||||
switch(pick_n_take(possible_objectives))
|
||||
if(1) //research
|
||||
var/datum/objective/download/O = new /datum/objective/download()
|
||||
O.owner = owner
|
||||
O.gen_amount_goal()
|
||||
objectives += O
|
||||
|
||||
if(2) //steal
|
||||
var/datum/objective/steal/special/O = new /datum/objective/steal/special()
|
||||
O.owner = owner
|
||||
O.find_target()
|
||||
objectives += O
|
||||
|
||||
if(3) //protect/kill
|
||||
if(!possible_targets.len) continue
|
||||
var/index = rand(1,possible_targets.len)
|
||||
var/datum/mind/M = possible_targets[index]
|
||||
var/is_bad_guy = possible_targets[M]
|
||||
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/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]. 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()
|
||||
O.owner = owner
|
||||
O.target = M
|
||||
O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm."
|
||||
objectives += O
|
||||
if(4) //flavor
|
||||
var/datum/objective/flavor/O = helping_station ? new /datum/objective/flavor/ninja_helping : new /datum/objective/flavor/ninja_syndie
|
||||
O.owner = owner
|
||||
O.forge_objective()
|
||||
objectives += O
|
||||
else
|
||||
break
|
||||
var/datum/objective/O = new /datum/objective/survive()
|
||||
O.owner = owner
|
||||
objectives += O
|
||||
|
||||
/proc/remove_ninja(mob/living/L)
|
||||
if(!L || !L.mind)
|
||||
return FALSE
|
||||
var/datum/antagonist/datum = L.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
datum.on_removal()
|
||||
return TRUE
|
||||
|
||||
/proc/is_ninja(mob/living/M)
|
||||
return M && M.mind && M.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
|
||||
|
||||
/datum/antagonist/ninja/greet()
|
||||
SEND_SOUND(owner.current, sound('sound/effects/ninja_greeting.ogg'))
|
||||
to_chat(owner.current, "I am an elite mercenary assassin of the mighty Spider Clan. A <font color='red'><B>SPACE NINJA</B></font>!")
|
||||
to_chat(owner.current, "Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by right clicking on it, to use abilities like stealth)!")
|
||||
to_chat(owner.current, "Officially, [helping_station?"Nanotrasen":"The Syndicate"] are my employer.")
|
||||
owner.announce_objectives()
|
||||
return
|
||||
|
||||
/datum/antagonist/ninja/on_gain()
|
||||
if(give_objectives)
|
||||
addObjectives()
|
||||
addMemories()
|
||||
if(give_equipment)
|
||||
equip_space_ninja(owner.current)
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/ninja/admin_add(datum/mind/new_owner,mob/admin)
|
||||
var/adj
|
||||
switch(input("What kind of ninja?", "Ninja") as null|anything in list("Random","Syndicate","Nanotrasen","No objectives"))
|
||||
if("Random")
|
||||
helping_station = pick(TRUE,FALSE)
|
||||
adj = ""
|
||||
if("Syndicate")
|
||||
helping_station = FALSE
|
||||
adj = "syndie"
|
||||
if("Nanotrasen")
|
||||
helping_station = TRUE
|
||||
adj = "friendly"
|
||||
if("No objectives")
|
||||
give_objectives = FALSE
|
||||
adj = "objectiveless"
|
||||
else
|
||||
return
|
||||
new_owner.assigned_role = ROLE_NINJA
|
||||
new_owner.special_role = ROLE_NINJA
|
||||
new_owner.add_antag_datum(src)
|
||||
message_admins("[key_name_admin(admin)] has [adj] ninja'ed [new_owner.current].")
|
||||
log_admin("[key_name(admin)] has [adj] ninja'ed [new_owner.current].")
|
||||
|
||||
/datum/antagonist/ninja/proc/update_ninja_icons_added(var/mob/living/carbon/human/ninja)
|
||||
var/datum/atom_hud/antag/ninjahud = GLOB.huds[ANTAG_HUD_NINJA]
|
||||
ninjahud.join_hud(ninja)
|
||||
set_antag_hud(ninja, "ninja")
|
||||
|
||||
/datum/antagonist/ninja/proc/update_ninja_icons_removed(var/mob/living/carbon/human/ninja)
|
||||
var/datum/atom_hud/antag/ninjahud = GLOB.huds[ANTAG_HUD_NINJA]
|
||||
ninjahud.leave_hud(ninja)
|
||||
set_antag_hud(ninja, null)
|
||||
@@ -68,6 +68,11 @@
|
||||
desc = "An integrated tracking device, jury-rigged to search for living Syndicate operatives."
|
||||
flags_1 = NONE
|
||||
|
||||
/obj/item/pinpointer/spider_cyborg // Cyborg pinpointers just look for a random space ninja.
|
||||
name = "cyborg spider clan pinpointer"
|
||||
desc = "An integrated tracking device, jury-rigged to search for living Spider Clan members."
|
||||
flags_1 = NONE
|
||||
|
||||
|
||||
/obj/item/pinpointer/syndicate_cyborg/Initialize()
|
||||
. = ..()
|
||||
@@ -85,3 +90,20 @@
|
||||
if(closest_operative)
|
||||
target = closest_operative
|
||||
..()
|
||||
|
||||
/obj/item/pinpointer/spider_cyborg/Initialize()
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, CYBORG_ITEM_TRAIT)
|
||||
|
||||
/obj/item/pinpointer/spider_cyborg/scan_for_target()
|
||||
target = null
|
||||
var/list/possible_targets = list()
|
||||
var/turf/here = get_turf(src)
|
||||
for(var/V in get_antag_minds(/datum/antagonist/ninja))
|
||||
var/datum/mind/M = V
|
||||
if(ishuman(M.current) && M.current.stat != DEAD)
|
||||
possible_targets |= M.current
|
||||
var/mob/living/closest_weeaboo = get_closest_atom(/mob/living/carbon/human, possible_targets, here)
|
||||
if(closest_weeaboo)
|
||||
target = closest_weeaboo
|
||||
..()
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/datum/antagonist/ninja
|
||||
name = "Space Ninja"
|
||||
antagpanel_category = "Space Ninja"
|
||||
job_rank = ROLE_NINJA
|
||||
antag_hud_type = ANTAG_HUD_NINJA
|
||||
antag_hud_name = "space_ninja"
|
||||
show_name_in_check_antagonists = TRUE
|
||||
show_to_ghosts = TRUE
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
///Whether or not this ninja will obtain objectives
|
||||
var/give_objectives = TRUE
|
||||
///Whether or not this ninja receives the standard equipment
|
||||
var/give_equipment = TRUE
|
||||
|
||||
/proc/is_ninja(mob/living/M)
|
||||
return M && M.mind && M.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
|
||||
/datum/antagonist/ninja/apply_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/ninja = mob_override || owner.current
|
||||
add_antag_hud(antag_hud_type, antag_hud_name, ninja)
|
||||
|
||||
/datum/antagonist/ninja/remove_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/ninja = mob_override || owner.current
|
||||
remove_antag_hud(antag_hud_type, ninja)
|
||||
|
||||
/**
|
||||
* Proc that equips the space ninja outfit on a given individual. By default this is the owner of the antagonist datum.
|
||||
*
|
||||
* Proc that equips the space ninja outfit on a given individual. By default this is the owner of the antagonist datum.
|
||||
* Arguments:
|
||||
* * ninja - The human to receive the gear
|
||||
* * Returns a proc call on the given human which will equip them with all the gear.
|
||||
*/
|
||||
/datum/antagonist/ninja/proc/equip_space_ninja(mob/living/carbon/human/ninja = owner.current)
|
||||
return ninja.equipOutfit(/datum/outfit/ninja)
|
||||
|
||||
/**
|
||||
* Proc that adds the proper memories to the antag datum
|
||||
*
|
||||
* Proc that adds the ninja starting memories to the owner of the antagonist datum.
|
||||
*/
|
||||
/datum/antagonist/ninja/proc/addMemories()
|
||||
antag_memory += "I am an elite mercenary of the mighty Spider Clan. A <font color='red'><B>SPACE NINJA</B></font>!<br>"
|
||||
antag_memory += "Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by clicking the initialize UI button, to use abilities like stealth)!<br>"
|
||||
|
||||
/datum/objective/cyborg_hijack
|
||||
explanation_text = "Use your gloves to convert at least one cyborg to aide you in sabotaging the station."
|
||||
|
||||
/datum/objective/door_jack
|
||||
///How many doors that need to be opened using the gloves to pass the objective
|
||||
var/doors_required = 0
|
||||
|
||||
/datum/objective/plant_explosive
|
||||
var/area/detonation_location
|
||||
|
||||
/datum/objective/security_scramble
|
||||
explanation_text = "Use your gloves on a security console to set everyone to arrest at least once. Note that the AI will be alerted once you begin!"
|
||||
|
||||
/datum/objective/terror_message
|
||||
explanation_text = "Use your gloves on a communication console in order to bring another threat to the station. Note that the AI will be alerted once you begin!"
|
||||
|
||||
/**
|
||||
* Proc that adds all the ninja's objectives to the antag datum.
|
||||
*
|
||||
* Proc that adds all the ninja's objectives to the antag datum. Called when the datum is gained.
|
||||
*/
|
||||
/datum/antagonist/ninja/proc/addObjectives()
|
||||
//Cyborg Hijack: Flag set to complete in the DrainAct in ninjaDrainAct.dm
|
||||
var/datum/objective/hijack = new /datum/objective/cyborg_hijack()
|
||||
objectives += hijack
|
||||
|
||||
//Research stealing
|
||||
var/datum/objective/download/research = new /datum/objective/download()
|
||||
research.owner = owner
|
||||
research.gen_amount_goal()
|
||||
objectives += research
|
||||
|
||||
//Door jacks, flag will be set to complete on when the last door is hijacked
|
||||
var/datum/objective/door_jack/doorobjective = new /datum/objective/door_jack()
|
||||
doorobjective.doors_required = rand(15,40)
|
||||
doorobjective.explanation_text = "Use your gloves to doorjack [doorobjective.doors_required] airlocks on the station."
|
||||
objectives += doorobjective
|
||||
|
||||
//Explosive plant, the bomb will register its completion on priming
|
||||
var/datum/objective/plant_explosive/bombobjective = new /datum/objective/plant_explosive()
|
||||
for(var/sanity in 1 to 100) // 100 checks at most.
|
||||
var/area/selected_area = pick(GLOB.sortedAreas)
|
||||
if(!is_station_level(selected_area.z) || !selected_area.area_flags == VALID_TERRITORY)
|
||||
continue
|
||||
bombobjective.detonation_location = selected_area
|
||||
break
|
||||
if(bombobjective.detonation_location)
|
||||
bombobjective.explanation_text = "Detonate your starter bomb in [bombobjective.detonation_location]. Note that the bomb will not work anywhere else!"
|
||||
objectives += bombobjective
|
||||
|
||||
//Security Scramble, set to complete upon using your gloves on a security console
|
||||
var/datum/objective/securityobjective = new /datum/objective/security_scramble()
|
||||
objectives += securityobjective
|
||||
|
||||
//Message of Terror, set to complete upon using your gloves a communication console
|
||||
var/datum/objective/communicationobjective = new /datum/objective/terror_message()
|
||||
objectives += communicationobjective
|
||||
|
||||
//Survival until end
|
||||
var/datum/objective/survival = new /datum/objective/survive()
|
||||
survival.owner = owner
|
||||
objectives += survival
|
||||
|
||||
/datum/antagonist/ninja/greet()
|
||||
SEND_SOUND(owner.current, sound('sound/effects/ninja_greeting.ogg'))
|
||||
to_chat(owner.current, "I am an elite mercenary of the mighty Spider Clan. A <font color='red'><B>SPACE NINJA</B></font>!")
|
||||
to_chat(owner.current, "Surprise is my weapon. Shadows are my armor. Without them, I am nothing. (//initialize your suit by right clicking on it, to use abilities like stealth)!")
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/ninja/on_gain()
|
||||
if(give_objectives)
|
||||
addObjectives()
|
||||
addMemories()
|
||||
if(give_equipment)
|
||||
equip_space_ninja(owner.current)
|
||||
|
||||
owner.current.mind.assigned_role = ROLE_NINJA
|
||||
owner.current.mind.special_role = ROLE_NINJA
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/ninja/admin_add(datum/mind/new_owner,mob/admin)
|
||||
new_owner.assigned_role = ROLE_NINJA
|
||||
new_owner.special_role = ROLE_NINJA
|
||||
new_owner.add_antag_datum(src)
|
||||
message_admins("[key_name_admin(admin)] has ninja'ed [key_name_admin(new_owner)].")
|
||||
log_admin("[key_name(admin)] has ninja'ed [key_name(new_owner)].")
|
||||
@@ -3,8 +3,8 @@
|
||||
desc = "A cheap, Syndicate-branded paper face mask. They'll never see it coming."
|
||||
mob_overlay_icon = 'icons/mob/clothing/mask.dmi'
|
||||
icon = 'icons/obj/clothing/masks.dmi'
|
||||
icon_state = "s-ninja"
|
||||
item_state = "s-ninja"
|
||||
icon_state = "ninjaOLD"
|
||||
item_state = "ninjaOLD"
|
||||
|
||||
/obj/item/clothing/glasses/phantomthief/ComponentInitialize()
|
||||
. = ..()
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/datum/round_event_control/space_ninja
|
||||
name = "Spawn Space Ninja"
|
||||
typepath = /datum/round_event/ghost_role/space_ninja
|
||||
max_occurrences = 1
|
||||
weight = 10
|
||||
earliest_start = 20 MINUTES
|
||||
min_players = 15
|
||||
|
||||
/datum/round_event/ghost_role/space_ninja
|
||||
minimum_required = 1
|
||||
role_name = "Space Ninja"
|
||||
|
||||
/datum/round_event/ghost_role/space_ninja/spawn_role()
|
||||
var/list/spawn_locs = list()
|
||||
for(var/obj/effect/landmark/carpspawn/carp_spawn in GLOB.landmarks_list)
|
||||
if(!isturf(carp_spawn.loc))
|
||||
stack_trace("Carp spawn found not on a turf: [carp_spawn.type] on [isnull(carp_spawn.loc) ? "null" : carp_spawn.loc.type]")
|
||||
continue
|
||||
spawn_locs += carp_spawn.loc
|
||||
if(!spawn_locs.len)
|
||||
message_admins("No valid spawn locations found, aborting...")
|
||||
return MAP_ERROR
|
||||
|
||||
//selecting a candidate player
|
||||
var/list/candidates = get_candidates(ROLE_NINJA, null, ROLE_NINJA)
|
||||
if(!candidates.len)
|
||||
return NOT_ENOUGH_PLAYERS
|
||||
|
||||
var/mob/dead/selected_candidate = pick(candidates)
|
||||
var/key = selected_candidate.key
|
||||
|
||||
//spawn the ninja and assign the candidate
|
||||
var/mob/living/carbon/human/ninja = create_space_ninja(pick(spawn_locs))
|
||||
ninja.key = key
|
||||
ninja.mind.add_antag_datum(/datum/antagonist/ninja)
|
||||
spawned_mobs += ninja
|
||||
message_admins("[ADMIN_LOOKUPFLW(ninja)] has been made into a space ninja by an event.")
|
||||
log_game("[key_name(ninja)] was spawned as a ninja by an event.")
|
||||
|
||||
return SUCCESSFUL_SPAWN
|
||||
|
||||
|
||||
//=======//NINJA CREATION PROCS//=======//
|
||||
|
||||
/proc/create_space_ninja(spawn_loc)
|
||||
var/mob/living/carbon/human/new_ninja = new(spawn_loc)
|
||||
var/datum/preferences/random_human_options = new()//Randomize appearance for the ninja.
|
||||
random_human_options.real_name = "[pick(GLOB.ninja_titles)] [pick(GLOB.ninja_names)]"
|
||||
random_human_options.copy_to(new_ninja)
|
||||
new_ninja.dna.update_dna_identity()
|
||||
return new_ninja
|
||||
@@ -1,4 +1,4 @@
|
||||
datum/job/prisoner
|
||||
/datum/job/prisoner
|
||||
title = "Prisoner"
|
||||
flag = PRISONER
|
||||
department_head = list("The Security Team")
|
||||
@@ -13,6 +13,15 @@ datum/job/prisoner
|
||||
|
||||
display_order = JOB_DISPLAY_ORDER_PRISONER
|
||||
|
||||
/datum/job/prisoner/after_spawn(mob/living/carbon/human/H, mob/M)
|
||||
var/list/policies = CONFIG_GET(keyed_list/policy)
|
||||
var/policy = policies[POLICYCONFIG_JOB_PRISONER]
|
||||
if(policy)
|
||||
var/mob/found = (M?.client && M) || (H?.client && H)
|
||||
to_chat(found, "<br><span class='userdanger'>!!READ THIS!!</span><br><span class='warning'>The following is server-specific policy configuration and overrides anything said above if conflicting.</span>")
|
||||
to_chat(found, "<br><br>")
|
||||
to_chat(found, "<span class='boldnotice'>[policy]</span>")
|
||||
|
||||
/datum/outfit/job/prisoner
|
||||
name = "Prisoner"
|
||||
jobtype = /datum/job/prisoner
|
||||
|
||||
@@ -82,34 +82,6 @@
|
||||
. += ""
|
||||
. += "Chemical Storage: [changeling.chem_charges]/[changeling.chem_storage]"
|
||||
. += "Absorbed DNA: [changeling.absorbedcount]"
|
||||
//NINJACODE
|
||||
if(istype(wear_suit, /obj/item/clothing/suit/space/space_ninja)) //Only display if actually a ninja.
|
||||
var/obj/item/clothing/suit/space/space_ninja/SN = wear_suit
|
||||
. += "SpiderOS Status: [SN.s_initialized ? "Initialized" : "Disabled"]"
|
||||
. += "Current Time: [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]"
|
||||
if(SN.s_initialized)
|
||||
//Suit gear
|
||||
. += "Energy Charge: [round(SN.cell.charge/100)]%"
|
||||
. += "Smoke Bombs: \Roman [SN.s_bombs]"
|
||||
//Ninja status
|
||||
. += "Fingerprints: [md5(dna.uni_identity)]"
|
||||
. += "Unique Identity: [dna.unique_enzymes]"
|
||||
. += "Overall Status: [stat > 1 ? "dead" : "[health]% healthy"]"
|
||||
. += "Nutrition Status: [nutrition]"
|
||||
. += "Oxygen Loss: [getOxyLoss()]"
|
||||
. += "Toxin Levels: [getToxLoss()]"
|
||||
. += "Burn Severity: [getFireLoss()]"
|
||||
. += "Brute Trauma: [getBruteLoss()]"
|
||||
. += "Radiation Levels: [radiation] rad"
|
||||
. += "Body Temperature: [bodytemperature-T0C] degrees C ([bodytemperature*1.8-459.67] degrees F)"
|
||||
|
||||
//Diseases
|
||||
if(length(diseases))
|
||||
. += "Viruses:"
|
||||
for(var/thing in diseases)
|
||||
var/datum/disease/D = thing
|
||||
. += "* [D.name], Type: [D.spread_text], Stage: [D.stage]/[D.max_stages], Possible Cure: [D.cure_text]"
|
||||
|
||||
|
||||
/mob/living/carbon/human/show_inv(mob/user)
|
||||
user.set_machine(src)
|
||||
|
||||
@@ -811,6 +811,32 @@
|
||||
<i>Help the operatives secure the disk at all costs!</i></b>"
|
||||
set_module = /obj/item/robot_module/saboteur
|
||||
|
||||
/mob/living/silicon/robot/modules/syndicate/spider// used for space ninja and their cyborg hacking special objective
|
||||
bubble_icon = "spider"
|
||||
playstyle_string = "<span class='big bold'>You are a Spider Clan assault cyborg!</span><br>\
|
||||
<b>You are armed with powerful offensive tools to aid you in your mission: obey your ninja masters by any means necessary. \
|
||||
Your cyborg LMG will slowly produce ammunition from your power supply, and your pinpointer will find and locate fellow members of the Spider Clan.</b>"
|
||||
set_module = /obj/item/robot_module/syndicate/spider
|
||||
|
||||
/mob/living/silicon/robot/modules/syndicate_medical/spider// ditto
|
||||
bubble_icon = "spider"
|
||||
var/playstyle_string = "<span class='big bold'>You are a Spider Clan medical cyborg!</span><br>\
|
||||
<b>You are armed with powerful medical tools to aid you in your mission: obey your ninja masters by any means necessary. \
|
||||
Your hypospray will produce Restorative Nanites, a wonder-drug that will heal most types of bodily damages, including clone and brain damage. It also produces morphine for offense. \
|
||||
Your defibrillator paddles can revive allies through their hardsuits, or can be used on harm intent to shock enemies! \
|
||||
Your energy saw functions as a circular saw, but can be activated to deal more damage, and your pinpointer will find and locate fellow members of the Spider Clan.</b>"
|
||||
set_module = /obj/item/robot_module/syndicate_medical/spider
|
||||
|
||||
/mob/living/silicon/robot/modules/saboteur/spider// ditto
|
||||
bubble_icon = "spider"
|
||||
var/playstyle_string = "<span class='big bold'>You are a Spider Clan saboteur cyborg!</span><br>\
|
||||
<b>You are armed with robust engineering tools to aid you in your mission: obey your ninja masters by any means necessary. \
|
||||
Your destination tagger will allow you to stealthily traverse the disposal network across the station. \
|
||||
Your welder will can be used to repair yourself or any allied silicon units, while serving as an impromptu melee weapon. \
|
||||
Your cyborg chameleon projector allows you to assume the appearance and registered name of a Nanotrasen engineering borg, and undertake covert actions on the station, \
|
||||
be aware that almost any physical contact or incidental damage will break your camouflage.</b>"
|
||||
set_module = /obj/item/robot_module/saboteur/spider
|
||||
|
||||
/mob/living/silicon/robot/proc/notify_ai(notifytype, oldname, newname)
|
||||
if(!connected_ai)
|
||||
return
|
||||
|
||||
@@ -1034,6 +1034,7 @@
|
||||
/obj/item/extinguisher/mini,
|
||||
/obj/item/crowbar/cyborg,
|
||||
/obj/item/reagent_containers/borghypo/syndicate,
|
||||
/obj/item/gripper/medical,
|
||||
/obj/item/shockpaddles/syndicate,
|
||||
/obj/item/healthanalyzer/advanced,
|
||||
/obj/item/surgical_drapes/advanced,
|
||||
@@ -1147,3 +1148,73 @@
|
||||
max_energy = 30
|
||||
recharge_rate = 1
|
||||
name = "Wrapping Paper Storage"
|
||||
|
||||
/obj/item/robot_module/syndicate/spider// used for space ninja and their cyborg hacking special objective
|
||||
name = "Spider Assault"
|
||||
basic_modules = list(
|
||||
/obj/item/assembly/flash/cyborg,
|
||||
/obj/item/extinguisher/mini,
|
||||
/obj/item/crowbar/cyborg,
|
||||
/obj/item/melee/transforming/energy/sword/cyborg,
|
||||
/obj/item/gun/energy/printer,
|
||||
/obj/item/pinpointer/spider_cyborg)
|
||||
|
||||
cyborg_base_icon = "spider_sec"
|
||||
|
||||
/obj/item/robot_module/syndicate_medical/spider// ditto
|
||||
name = "Spider Medical"
|
||||
basic_modules = list(
|
||||
/obj/item/assembly/flash/cyborg,
|
||||
/obj/item/extinguisher/mini,
|
||||
/obj/item/crowbar/cyborg,
|
||||
/obj/item/reagent_containers/borghypo/syndicate,
|
||||
/obj/item/gripper/medical,
|
||||
/obj/item/shockpaddles/syndicate,
|
||||
/obj/item/healthanalyzer/advanced,
|
||||
/obj/item/surgical_drapes/advanced,
|
||||
/obj/item/retractor,
|
||||
/obj/item/hemostat,
|
||||
/obj/item/cautery,
|
||||
/obj/item/surgicaldrill,
|
||||
/obj/item/scalpel,
|
||||
/obj/item/bonesetter,
|
||||
/obj/item/stack/medical/bone_gel,
|
||||
/obj/item/melee/transforming/energy/sword/cyborg/saw,
|
||||
/obj/item/roller/robo,
|
||||
/obj/item/stack/medical/gauze/cyborg,
|
||||
/obj/item/gun/medbeam,
|
||||
/obj/item/organ_storage,
|
||||
/obj/item/pinpointer/spider_cyborg)
|
||||
|
||||
cyborg_base_icon = "spider_medical"
|
||||
|
||||
/obj/item/robot_module/saboteur/spider// ditto
|
||||
name = "Spider Saboteur"
|
||||
basic_modules = list(
|
||||
/obj/item/assembly/flash/cyborg,
|
||||
/obj/item/borg/sight/thermal,
|
||||
/obj/item/construction/rcd/borg/syndicate,
|
||||
/obj/item/pipe_dispenser,
|
||||
/obj/item/restraints/handcuffs/cable/zipties,
|
||||
/obj/item/extinguisher,
|
||||
/obj/item/weldingtool/largetank/cyborg,
|
||||
/obj/item/screwdriver/nuke,
|
||||
/obj/item/wrench/cyborg,
|
||||
/obj/item/crowbar/cyborg,
|
||||
/obj/item/wirecutters/cyborg,
|
||||
/obj/item/multitool/cyborg,
|
||||
/obj/item/storage/part_replacer/cyborg,
|
||||
/obj/item/holosign_creator/atmos,
|
||||
/obj/item/gripper,
|
||||
/obj/item/lightreplacer/cyborg,
|
||||
/obj/item/stack/sheet/metal/cyborg,
|
||||
/obj/item/stack/sheet/glass/cyborg,
|
||||
/obj/item/stack/sheet/rglass/cyborg,
|
||||
/obj/item/stack/rods/cyborg,
|
||||
/obj/item/stack/tile/plasteel/cyborg,
|
||||
/obj/item/destTagger/borg,
|
||||
/obj/item/stack/cable_coil/cyborg,
|
||||
/obj/item/borg_chameleon,
|
||||
/obj/item/pinpointer/spider_cyborg)
|
||||
|
||||
cyborg_base_icon = "spider_engi"
|
||||
|
||||
@@ -176,6 +176,12 @@ While using this makes the system rely on OnFire, it still gives options for tim
|
||||
elitemind = pick(candidates)
|
||||
elitemind.playsound_local(get_turf(elitemind), 'sound/effects/magic.ogg', 40, 0)
|
||||
to_chat(elitemind, "<b>You have been chosen to play as a Lavaland Elite.\nIn a few seconds, you will be summoned on Lavaland as a monster to fight your activator, in a fight to the death.\nYour attacks can be switched using the buttons on the top left of the HUD, and used by clicking on targets or tiles similar to a gun.\nWhile the opponent might have an upper hand with powerful mining equipment and tools, you have great power normally limited by AI mobs.\nIf you want to win, you'll have to use your powers in creative ways to ensure the kill. It's suggested you try using them all as soon as possible.\nShould you win, you'll receive extra information regarding what to do after. Good luck!</b>")
|
||||
var/list/policies = CONFIG_GET(keyed_list/policy)
|
||||
var/policy = policies[POLICYCONFIG_ELITE_SPAWN]
|
||||
if(policy)
|
||||
to_chat(elitemind, "<br><span class='userdanger'>!!READ THIS!!</span><br><span class='warning'>The following is server-specific policy configuration and overrides anything said above if conflicting.</span>")
|
||||
to_chat(elitemind, "<br><br>")
|
||||
to_chat(elitemind, "<span class='boldnotice'>[policy]</span>")
|
||||
addtimer(CALLBACK(src, .proc/spawn_elite, elitemind), 100)
|
||||
else
|
||||
visible_message("<span class='boldwarning'>The stirring stops, and nothing emerges. Perhaps try again later.</span>")
|
||||
@@ -304,6 +310,12 @@ While using this makes the system rely on OnFire, it still gives options for tim
|
||||
to_chat(mychild, "<span class='boldwarning'>As the life in the activator's eyes fade, the forcefield around you dies out and you feel your power subside.\nDespite this inferno being your home, you feel as if you aren't welcome here anymore.\nWithout any guidance, your purpose is now for you to decide.</span>")
|
||||
to_chat(mychild, "<b>Your max health has been halved, but can now heal by standing on your tumor. Note, it's your only way to heal.\nBear in mind, if anyone interacts with your tumor, you'll be resummoned here to carry out another fight. In such a case, you will regain your full max health.\nAlso, be weary of your fellow inhabitants, they likely won't be happy to see you!</b>")
|
||||
to_chat(mychild, "<span class='big bold'>Note that you are a lavaland monster, and thus not allied to the station. You should not cooperate or act friendly with any station crew unless under extreme circumstances!</span>")
|
||||
var/list/policies = CONFIG_GET(keyed_list/policy)
|
||||
var/policy = policies[POLICYCONFIG_ELITE_WIN]
|
||||
if(policy)
|
||||
to_chat(mychild, "<br><span class='userdanger'>!!READ THIS!!</span><br><span class='warning'>The following is server-specific policy configuration and overrides anything said above if conflicting.</span>")
|
||||
to_chat(mychild, "<br><br>")
|
||||
to_chat(mychild, "<span class='boldnotice'>[policy]</span>")
|
||||
|
||||
/obj/item/tumor_shard
|
||||
name = "tumor shard"
|
||||
@@ -332,6 +344,12 @@ While using this makes the system rely on OnFire, it still gives options for tim
|
||||
E.playsound_local(get_turf(E), 'sound/effects/magic.ogg', 40, 0)
|
||||
to_chat(E, "<span class='userdanger'>You have been revived by [user]. While you can't speak to them, you owe [user] a great debt. Assist [user.p_them()] in achieving [user.p_their()] goals, regardless of risk.</span")
|
||||
to_chat(E, "<span class='big bold'>Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to!</span>")
|
||||
var/list/policies = CONFIG_GET(keyed_list/policy)
|
||||
var/policy = policies[POLICYCONFIG_ELITE_SENTIENCE]
|
||||
if(policy)
|
||||
to_chat(E, "<br><span class='userdanger'>!!READ THIS!!</span><br><span class='warning'>The following is server-specific policy configuration and overrides anything said above if conflicting.</span>")
|
||||
to_chat(E, "<br><br>")
|
||||
to_chat(E, "<span class='boldnotice'>[policy]</span>")
|
||||
E.maxHealth = E.maxHealth * 0.5
|
||||
E.health = E.maxHealth
|
||||
E.desc = "[E.desc] However, this one appears appears less wild in nature, and calmer around people."
|
||||
|
||||
@@ -113,6 +113,7 @@
|
||||
multiplicative_slowdown = CRAWLING_ADD_SLOWDOWN
|
||||
movetypes = CRAWLING
|
||||
flags = IGNORE_NOSLOW
|
||||
priority = 20000
|
||||
|
||||
/datum/movespeed_modifier/mob_config_speedmod
|
||||
variable = TRUE
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
|
||||
/*
|
||||
|
||||
Contents:
|
||||
- Definitions, because the original Ninja code has so much magic.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//ninjacost() specificCheck defines
|
||||
#define N_STEALTH_CANCEL 1
|
||||
#define N_SMOKE_BOMB 2
|
||||
#define N_ADRENALINE 3
|
||||
#define N_ADRENALINE 2
|
||||
|
||||
//ninjaDrainAct() defines for non numerical returns
|
||||
//While not strictly needed, it's nicer than them just returning "twat"
|
||||
//Which was my original intention.
|
||||
|
||||
#define INVALID_DRAIN "INVALID" //This one is if the drain proc needs to cancel, eg missing variables, etc, it's important.
|
||||
|
||||
#define DRAIN_RD_HACK_FAILED "RDHACKFAIL"
|
||||
#define DRAIN_MOB_SHOCK "MOBSHOCK"
|
||||
#define DRAIN_MOB_SHOCK_FAILED "MOBSHOCKFAIL"
|
||||
|
||||
|
||||
//Tells whether or not someone is a space ninja
|
||||
#define IS_SPACE_NINJA(ninja) (ninja.mind && ninja.mind.has_antag_datum(/datum/antagonist/ninja))
|
||||
|
||||
//Defines for the suit's unique abilities
|
||||
#define IS_NINJA_SUIT_INITIALIZATION(action) (istype(action, /datum/action/item_action/initialize_ninja_suit))
|
||||
#define IS_NINJA_SUIT_STATUS(action) (istype(action, /datum/action/item_action/ninjastatus))
|
||||
#define IS_NINJA_SUIT_BOOST(action) (istype(action, /datum/action/item_action/ninjaboost))
|
||||
#define IS_NINJA_SUIT_EMP(action) (istype(action, /datum/action/item_action/ninjapulse))
|
||||
#define IS_NINJA_SUIT_STAR_CREATION(action) (istype(action, /datum/action/item_action/ninjastar))
|
||||
#define IS_NINJA_SUIT_NET_CREATION(action) (istype(action, /datum/action/item_action/ninjanet))
|
||||
#define IS_NINJA_SUIT_SWORD_RECALL(action) (istype(action, /datum/action/item_action/ninja_sword_recall))
|
||||
#define IS_NINJA_SUIT_STEALTH(action) (istype(action, /datum/action/item_action/ninja_stealth))
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
/**
|
||||
* # Energy Katana
|
||||
*
|
||||
* The space ninja's katana.
|
||||
*
|
||||
* The katana that only space ninja spawns with. Comes with 30 force and throwforce, along with a signature special jaunting system.
|
||||
* Upon clicking on a tile with the dash on, the user will teleport to that tile, assuming their target was not dense.
|
||||
* The katana has 3 dashes stored at maximum, and upon using the dash, it will return 20 seconds after it was used.
|
||||
* It also has a special feature where if it is tossed at a space ninja who owns it (determined by the ninja suit), the ninja will catch the katana instead of being hit by it.
|
||||
*
|
||||
*/
|
||||
/obj/item/energy_katana
|
||||
name = "energy katana"
|
||||
desc = "A katana infused with strong energy."
|
||||
@@ -5,16 +16,16 @@
|
||||
item_state = "energy_katana"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
force = 40
|
||||
throwforce = 20
|
||||
force = 30
|
||||
throwforce = 30
|
||||
block_chance = 50
|
||||
armour_penetration = 50
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
block_chance = 50
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
sharpness = SHARP_EDGED
|
||||
obj_flags = UNIQUE_RENAME // here is a shitpost and i cannot wait for ninjas naming their sword very rude things
|
||||
max_integrity = 200
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
@@ -34,13 +45,19 @@
|
||||
|
||||
/obj/item/energy_katana/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(dash_toggled)
|
||||
jaunt.Teleport(user, target)
|
||||
if(proximity_flag && (isobj(target) || issilicon(target)))
|
||||
spark_system.start()
|
||||
playsound(user, "sparks", 50, 1)
|
||||
playsound(user, 'sound/weapons/blade1.ogg', 50, 1)
|
||||
target.emag_act(user)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/obj/item/clothing/suit/space/space_ninja/ninja_suit = H.wear_suit
|
||||
if(!istype(ninja_suit))// do you actually have a ninja suit on
|
||||
to_chat(user, "<span class='warning'><b>ERROR</b>: garments incompatible with carbon material jaunt. Please suit up in compatible garments.</span>")
|
||||
return
|
||||
if(!dash_toggled || Adjacent(target) || target.density)// is where you are going not a wall
|
||||
return
|
||||
if(!ninja_suit.s_coold == 0)// are you not currently on the ability cooldown
|
||||
to_chat(user, "<span class='warning'><b>ERROR</b>: suit is on cooldown.</span>")
|
||||
return
|
||||
jaunt.Teleport(user, target)// okay you can now go my good sir
|
||||
|
||||
/obj/item/energy_katana/pickup(mob/living/user)
|
||||
. = ..()
|
||||
@@ -58,16 +75,30 @@
|
||||
//To throw it at the ninja
|
||||
/obj/item/energy_katana/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
if(ishuman(hit_atom))
|
||||
var/mob/living/carbon/human/H = hit_atom
|
||||
if(istype(H.wear_suit, /obj/item/clothing/suit/space/space_ninja))
|
||||
var/obj/item/clothing/suit/space/space_ninja/SN = H.wear_suit
|
||||
if(SN.energyKatana == src)
|
||||
returnToOwner(H, 0, 1)
|
||||
var/mob/living/carbon/human/hit_human = hit_atom
|
||||
if(istype(hit_human.wear_suit, /obj/item/clothing/suit/space/space_ninja))
|
||||
var/obj/item/clothing/suit/space/space_ninja/ninja_suit = hit_human.wear_suit
|
||||
if(ninja_suit.energyKatana == src)
|
||||
returnToOwner(hit_human, 0, 1)
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/energy_katana/proc/returnToOwner(mob/living/carbon/human/user, doSpark = 1, caught = 0)
|
||||
/obj/item/energy_katana/Destroy()
|
||||
QDEL_NULL(spark_system)
|
||||
QDEL_NULL(jaunt)
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Proc called when the katana is recalled to its space ninja.
|
||||
*
|
||||
* Proc called when space ninja is hit with its suit's katana or the recall ability is used.
|
||||
* Arguments:
|
||||
* * user - To whom the katana is returning to.
|
||||
* * doSpark - whether or not the katana will spark when it returns.
|
||||
* * caught - boolean for whether or not the katana was caught or was teleported back.
|
||||
*/
|
||||
/obj/item/energy_katana/proc/returnToOwner(mob/living/carbon/human/user, doSpark = TRUE, caught = FALSE)
|
||||
if(!istype(user))
|
||||
return
|
||||
forceMove(get_turf(user))
|
||||
@@ -94,13 +125,8 @@
|
||||
if(msg)
|
||||
to_chat(user, "<span class='notice'>[msg]</span>")
|
||||
|
||||
|
||||
/obj/item/energy_katana/Destroy()
|
||||
QDEL_NULL(spark_system)
|
||||
return ..()
|
||||
|
||||
/datum/action/innate/dash/ninja
|
||||
current_charges = 3
|
||||
max_charges = 3
|
||||
charge_rate = 30
|
||||
charge_rate = 200
|
||||
recharge_sound = null
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
//Note to future generations: I didn't write this god-awful code I just ported it to the event system and tried to make it less moon-speaky.
|
||||
//Don't judge me D; ~Carn //Maximum judging occuring - Remie.
|
||||
// Tut tut Remie, let's keep our comments constructive. - coiax
|
||||
|
||||
/*
|
||||
|
||||
Contents:
|
||||
- The Ninja "Random" Event
|
||||
- Ninja creation code
|
||||
*/
|
||||
|
||||
/datum/round_event_control/ninja
|
||||
name = "Space Ninja"
|
||||
typepath = /datum/round_event/ghost_role/ninja
|
||||
max_occurrences = 1
|
||||
earliest_start = 40 MINUTES
|
||||
gamemode_blacklist = list("dynamic")
|
||||
min_players = 15
|
||||
|
||||
/datum/round_event/ghost_role/ninja
|
||||
var/success_spawn = 0
|
||||
role_name = "space ninja"
|
||||
minimum_required = 1
|
||||
|
||||
var/helping_station
|
||||
var/spawn_loc
|
||||
var/give_objectives = TRUE
|
||||
|
||||
/datum/round_event/ghost_role/ninja/setup()
|
||||
helping_station = rand(0,1)
|
||||
|
||||
/datum/round_event/ghost_role/ninja/kill()
|
||||
if(!success_spawn && control)
|
||||
control.occurrences--
|
||||
return ..()
|
||||
|
||||
/datum/round_event/ghost_role/ninja/spawn_role()
|
||||
//selecting a spawn_loc
|
||||
if(!spawn_loc)
|
||||
var/list/spawn_locs = list()
|
||||
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
|
||||
if(isturf(L.loc))
|
||||
spawn_locs += L.loc
|
||||
for(var/obj/effect/landmark/loneopspawn/L in GLOB.landmarks_list)
|
||||
if(isturf(L.loc))
|
||||
spawn_locs += L.loc
|
||||
if(!spawn_locs.len)
|
||||
return kill()
|
||||
spawn_loc = pick(spawn_locs)
|
||||
if(!spawn_loc)
|
||||
return MAP_ERROR
|
||||
|
||||
//selecting a candidate player
|
||||
var/list/candidates = get_candidates(ROLE_NINJA, null, ROLE_NINJA)
|
||||
if(!candidates.len)
|
||||
return NOT_ENOUGH_PLAYERS
|
||||
|
||||
var/mob/dead/selected_candidate = pick_n_take(candidates)
|
||||
var/key = selected_candidate.key
|
||||
|
||||
//Prepare ninja player mind
|
||||
var/datum/mind/Mind = new /datum/mind(key)
|
||||
Mind.assigned_role = ROLE_NINJA
|
||||
Mind.special_role = ROLE_NINJA
|
||||
Mind.active = 1
|
||||
|
||||
//spawn the ninja and assign the candidate
|
||||
var/mob/living/carbon/human/Ninja = create_space_ninja(spawn_loc)
|
||||
Mind.transfer_to(Ninja)
|
||||
var/datum/antagonist/ninja/ninjadatum = new
|
||||
ninjadatum.helping_station = pick(TRUE,FALSE)
|
||||
Mind.add_antag_datum(ninjadatum)
|
||||
|
||||
if(Ninja.mind != Mind) //something has gone wrong!
|
||||
stack_trace("Ninja created with incorrect mind")
|
||||
|
||||
spawned_mobs += Ninja
|
||||
message_admins("[ADMIN_LOOKUPFLW(Ninja)] has been made into a ninja by an event.")
|
||||
log_game("[key_name(Ninja)] was spawned as a ninja by an event.")
|
||||
success_spawn = TRUE
|
||||
|
||||
return SUCCESSFUL_SPAWN
|
||||
|
||||
|
||||
//=======//NINJA CREATION PROCS//=======//
|
||||
|
||||
/proc/create_space_ninja(spawn_loc)
|
||||
var/mob/living/carbon/human/new_ninja = new(spawn_loc)
|
||||
var/datum/preferences/A = new()//Randomize appearance for the ninja.
|
||||
A.real_name = "[pick(GLOB.ninja_titles)] [pick(GLOB.ninja_names)]"
|
||||
A.copy_to(new_ninja)
|
||||
new_ninja.dna.update_dna_identity()
|
||||
return new_ninja
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* # Spider Charge
|
||||
*
|
||||
* A unique version of c4 possessed only by the space ninja. Has a stronger blast radius.
|
||||
* Can only be detonated by space ninjas with the bombing objective. Can only be set up where the objective says it can.
|
||||
* When it primes, the space ninja responsible will have their objective set to complete.
|
||||
*
|
||||
*/
|
||||
/obj/item/grenade/plastic/c4/ninja
|
||||
name = "spider charge"
|
||||
desc = "A modified C-4 charge supplied to you by the Spider Clan. Its explosive power has been juiced up, but only works in one specific area."
|
||||
icon_state = "plasticspider0"
|
||||
item_state = "plasticspider"
|
||||
boom_sizes = list(2, 4, 6)
|
||||
var/mob/detonator = null
|
||||
|
||||
/obj/item/grenade/plastic/c4/ninja/afterattack(atom/movable/AM, mob/user, flag)
|
||||
var/datum/antagonist/ninja/ninja_antag = user.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!ninja_antag)
|
||||
to_chat(user, "<span class='notice'>You fiddle with the charge, but nothing happens.</span>")
|
||||
return
|
||||
var/datum/objective/plant_explosive/objective = locate() in ninja_antag.objectives
|
||||
if(!objective)
|
||||
to_chat(user, "<span class='notice'>You can't seem to activate the charge. It's location-locked, but you don't know where to detonate it.</span>")
|
||||
return
|
||||
if(objective.detonation_location != get_area(user))
|
||||
to_chat(user, "<span class='notice'>This isn't the location you're supposed to use this!</span>")
|
||||
return
|
||||
detonator = user
|
||||
return ..()
|
||||
|
||||
/obj/item/grenade/plastic/c4/ninja/prime(mob/living/lanced_by)
|
||||
. = ..()
|
||||
anchored = TRUE
|
||||
//Since we already did the checks in afterattack, the denonator must be a ninja with the bomb objective.
|
||||
if(!detonator)
|
||||
return
|
||||
var/datum/antagonist/ninja/ninja_antag = detonator.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
var/datum/objective/plant_explosive/objective = locate() in ninja_antag.objectives
|
||||
objective.completed = TRUE
|
||||
|
||||
/obj/item/grenade/plastic/c4/ninja/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/screwdriver))
|
||||
to_chat(user, "<span class='notice'>The wire panel is locked in place, clearly you aren't supposed to be opening it!</span>")
|
||||
return
|
||||
@@ -8,10 +8,10 @@
|
||||
ears = /obj/item/radio/headset
|
||||
shoes = /obj/item/clothing/shoes/space_ninja
|
||||
gloves = /obj/item/clothing/gloves/space_ninja
|
||||
back = /obj/item/tank/jetpack/carbondioxide
|
||||
l_pocket = /obj/item/grenade/plastic/x4
|
||||
r_pocket = /obj/item/tank/internals/emergency_oxygen
|
||||
internals_slot = SLOT_R_STORE
|
||||
l_pocket = /obj/item/grenade/plastic/c4/ninja
|
||||
r_pocket = /obj/item/hypospray/mkii/CMO/combat
|
||||
suit_store = /obj/item/tank/internals/oxygen
|
||||
internals_slot = SLOT_S_STORE
|
||||
belt = /obj/item/energy_katana
|
||||
implants = list(/obj/item/implant/explosive)
|
||||
|
||||
@@ -21,5 +21,3 @@
|
||||
var/obj/item/clothing/suit/space/space_ninja/S = H.wear_suit
|
||||
if(istype(H.belt, belt))
|
||||
S.energyKatana = H.belt
|
||||
S.randomize_param()
|
||||
|
||||
|
||||
@@ -1,25 +1,13 @@
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Dear ninja gloves
|
||||
|
||||
This isn't because I like you
|
||||
this is because your father is a bastard
|
||||
|
||||
...
|
||||
I guess you're a little cool.
|
||||
-Sayu
|
||||
|
||||
|
||||
see ninjaDrainAct.dm for ninjadrain_act()
|
||||
Touch() simply calls this on it's target now
|
||||
Ninja's electricuting people when?
|
||||
-Remie
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* # Ninja Gloves
|
||||
*
|
||||
* Space ninja's gloves. Gives access to a number of special interactions.
|
||||
*
|
||||
* Gloves only found from space ninjas. Allows the wearer to access special interactions with various objects.
|
||||
* These interactions are detailed in ninjaDrainAct.dm in the suit file.
|
||||
* These interactions are toggled by an action tied to the gloves. The interactions will not activate if the user is also not wearing a ninja suit.
|
||||
*
|
||||
*/
|
||||
/obj/item/clothing/gloves/space_ninja
|
||||
desc = "These nano-enhanced gloves insulate from electricity and provide fire resistance."
|
||||
name = "ninja gloves"
|
||||
@@ -32,11 +20,24 @@
|
||||
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
|
||||
strip_delay = 120
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
var/draining = 0
|
||||
var/candrain = 0
|
||||
actions_types = list(/datum/action/item_action/toggle_glove)
|
||||
var/datum/action/innate/doorjack/ninja/hack
|
||||
///Whether or not we're currently draining something
|
||||
var/draining = FALSE
|
||||
///Whether or not we can currently drain something
|
||||
var/candrain = FALSE
|
||||
///Minimum amount of power we can drain in a single drain action
|
||||
var/mindrain = 200
|
||||
///Maximum amount of power we can drain in a single drain action
|
||||
var/maxdrain = 400
|
||||
|
||||
///Whether or not the security console hack was used to set everyone to arrest
|
||||
var/security_console_hack_success = FALSE
|
||||
///Whether or not the communication console hack was used to summon another antagonist
|
||||
var/communication_console_hack_success = FALSE
|
||||
///How many times the gloves have been used to force open doors.
|
||||
var/door_hack_counter = 0
|
||||
///Whether or not the cyborg hack was used to syndify a cyborg
|
||||
var/borg_hack_success = FALSE
|
||||
var/stunforce = 100
|
||||
|
||||
/obj/item/clothing/gloves/space_ninja/Touch(atom/A,proximity)
|
||||
@@ -45,9 +46,9 @@
|
||||
if(!ishuman(loc))
|
||||
return FALSE //Only works while worn
|
||||
|
||||
var/mob/living/carbon/human/H = loc
|
||||
var/mob/living/carbon/human/wearer = loc
|
||||
|
||||
var/obj/item/clothing/suit/space/space_ninja/suit = H.wear_suit
|
||||
var/obj/item/clothing/suit/space/space_ninja/suit = wearer.wear_suit
|
||||
if(!istype(suit))
|
||||
return FALSE
|
||||
if(isturf(A))
|
||||
@@ -56,17 +57,17 @@
|
||||
if(!proximity)
|
||||
return FALSE
|
||||
|
||||
A.add_fingerprint(H)
|
||||
A.add_fingerprint(wearer)
|
||||
|
||||
draining = TRUE
|
||||
. = A.ninjadrain_act(suit,H,src)
|
||||
. = A.ninjadrain_act(suit,wearer,src)
|
||||
draining = FALSE
|
||||
|
||||
if(isnum(.)) //Numerical values of drained handle their feedback here, Alpha values handle it themselves (Research hacking)
|
||||
if(.)
|
||||
to_chat(H, "<span class='notice'>Gained <B>[DisplayEnergy(.)]</B> of energy from [A].</span>")
|
||||
to_chat(wearer, "<span class='notice'>Gained <B>[DisplayEnergy(.)]</B> of energy from [A].</span>")
|
||||
else
|
||||
to_chat(H, "<span class='danger'>\The [A] has run dry of energy, you must find another source!</span>")
|
||||
to_chat(wearer, "<span class='danger'>\The [A] has run dry of energy, you must find another source!</span>")
|
||||
. = INTERRUPT_UNARMED_ATTACK
|
||||
else
|
||||
. = FALSE //as to not cancel attack_hand()
|
||||
@@ -75,12 +76,13 @@
|
||||
. = ..()
|
||||
REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
|
||||
/obj/item/clothing/gloves/space_ninja/proc/toggledrain()
|
||||
var/mob/living/carbon/human/U = loc
|
||||
to_chat(U, "You <b>[candrain?"disable":"enable"]</b> special interaction.")
|
||||
candrain=!candrain
|
||||
|
||||
/obj/item/clothing/gloves/space_ninja/examine(mob/user)
|
||||
. = ..()
|
||||
if(HAS_TRAIT_FROM(src, TRAIT_NODROP, NINJA_SUIT_TRAIT))
|
||||
. += "The energy drain mechanism is <B>[candrain?"active":"inactive"]</B>."
|
||||
|
||||
/obj/item/clothing/gloves/space_ninja/ui_action_click(mob/user, action)
|
||||
if(istype(action, /datum/action/item_action/toggle_glove))
|
||||
toggledrain()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
|
||||
|
||||
/**
|
||||
* # Ninja Hood
|
||||
*
|
||||
* Space ninja's hood. Provides armor and blocks AI tracking.
|
||||
*
|
||||
* A hood that only exists as a part of space ninja's starting kit. Provides armor equal of space ninja's suit and disallows an AI to track the wearer.
|
||||
*
|
||||
*/
|
||||
/obj/item/clothing/head/helmet/space/space_ninja
|
||||
desc = "What may appear to be a simple black garment is in fact a highly sophisticated nano-weave helmet. Standard issue ninja gear."
|
||||
name = "ninja hood"
|
||||
icon_state = "s-ninja"
|
||||
item_state = "s-ninja_mask"
|
||||
armor = list("melee" = 60, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 25, "fire" = 100, "acid" = 100)
|
||||
strip_delay = 12
|
||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 20,"energy" = 30, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 100, "acid" = 100)
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
blockTracking = 1//Roughly the only unique thing about this helmet.
|
||||
blockTracking = TRUE//Roughly the only unique thing about this helmet.
|
||||
flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
|
||||
|
||||
/obj/item/clothing/head/helmet/space/space_ninja/dropped(mob/user)
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
|
||||
/*
|
||||
|
||||
Contents:
|
||||
- The Ninja Space Mask
|
||||
- Ninja Space Mask speech modification
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* # Ninja Mask
|
||||
*
|
||||
* Space ninja's mask. Makes you sound like a real anime girl. Barely able to be considered a real upside.
|
||||
*
|
||||
* A mask which only spawns as a part of space ninja's starting kit. Functions as a gas mask.
|
||||
*
|
||||
*/
|
||||
/obj/item/clothing/mask/gas/space_ninja
|
||||
name = "ninja mask"
|
||||
desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement."
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
It will teleport people to a holding facility after 30 seconds. (Check the process() proc to change where teleport goes)
|
||||
It is possible to destroy the net by the occupant or someone else.
|
||||
*/
|
||||
|
||||
/obj/structure/energy_net
|
||||
name = "energy net"
|
||||
desc = "It's a net made of green energy."
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "energynet"
|
||||
|
||||
density = TRUE//Can't pass through.
|
||||
opacity = 0//Can see through.
|
||||
mouse_opacity = MOUSE_OPACITY_ICON//So you can hit it with stuff.
|
||||
anchored = TRUE//Can't drag/grab the net.
|
||||
layer = ABOVE_ALL_MOB_LAYER
|
||||
max_integrity = 50 //How much health it has.
|
||||
can_buckle = 1
|
||||
buckle_lying = 0
|
||||
buckle_prevents_pull = TRUE
|
||||
var/mob/living/carbon/affecting //Who it is currently affecting, if anyone.
|
||||
var/mob/living/carbon/master //Who shot web. Will let this person know if the net was successful or failed.
|
||||
var/check = 15//30 seconds before teleportation. Could be extended I guess.
|
||||
var/success = FALSE
|
||||
|
||||
|
||||
/obj/structure/energy_net/play_attack_sound(damage, damage_type = BRUTE, damage_flag = 0)
|
||||
switch(damage_type)
|
||||
if(BRUTE)
|
||||
playsound(src, 'sound/weapons/slash.ogg', 80, 1)
|
||||
if(BURN)
|
||||
playsound(src, 'sound/weapons/slash.ogg', 80, 1)
|
||||
|
||||
/obj/structure/energy_net/Destroy()
|
||||
if(!success)
|
||||
if(!QDELETED(affecting))
|
||||
affecting.visible_message("[affecting.name] was recovered from the energy net!", "You were recovered from the energy net!", "<span class='italics'>You hear a grunt.</span>")
|
||||
if(!QDELETED(master))//As long as they still exist.
|
||||
to_chat(master, "<span class='userdanger'>ERROR</span>: unable to initiate transport protocol. Procedure terminated.")
|
||||
return ..()
|
||||
|
||||
/obj/structure/energy_net/process()
|
||||
if(QDELETED(affecting)||affecting.loc!=loc)
|
||||
qdel(src)//Get rid of the net.
|
||||
return
|
||||
|
||||
if(check>0)
|
||||
check--
|
||||
return
|
||||
|
||||
success = TRUE
|
||||
qdel(src)
|
||||
if(ishuman(affecting))
|
||||
var/mob/living/carbon/human/H = affecting
|
||||
for(var/obj/item/W in H)
|
||||
if(W == H.w_uniform || W == H.shoes)
|
||||
continue//So all they're left with are shoes and uniform.
|
||||
H.dropItemToGround(W)
|
||||
H.dna.species.give_important_for_life(H) // After we remove items, at least give them what they need to live.
|
||||
/*
|
||||
var/datum/antagonist/antag_datum
|
||||
for(var/datum/antagonist/ninja/AD in GLOB.antagonists) //Because only ninjas get capture objectives; They're not doable without the suit.
|
||||
if(AD.owner == master)
|
||||
antag_datum = AD
|
||||
break
|
||||
for(var/datum/objective/capture/capture in antag_datum)
|
||||
if(istype(affecting, /mob/living/carbon/human)) //Humans.
|
||||
if(affecting.stat == DEAD)//Dead folks are worth less.
|
||||
capture.captured_amount+=0.5
|
||||
continue
|
||||
capture.captured_amount+=1
|
||||
if(istype(affecting, /mob/living/carbon/monkey)) //Monkeys are almost worthless, you failure.
|
||||
capture.captured_amount+=0.1
|
||||
if(istype(affecting, /mob/living/carbon/alien/larva)) //Larva are important for research.
|
||||
if(affecting.stat == DEAD)
|
||||
capture.captured_amount+=0.5
|
||||
continue
|
||||
capture.captured_amount+=1
|
||||
if(istype(affecting, /mob/living/carbon/alien/humanoid)) //Aliens are worth twice as much as humans.
|
||||
if(istype(affecting, /mob/living/carbon/alien/humanoid/royal/queen)) //Queens are worth three times as much as humans.
|
||||
if(affecting.stat == DEAD)
|
||||
capture.captured_amount+=1.5
|
||||
else
|
||||
capture.captured_amount+=3
|
||||
continue
|
||||
if(affecting.stat == DEAD)
|
||||
capture.captured_amount+=1
|
||||
continue
|
||||
capture.captured_amount+=2
|
||||
*/
|
||||
|
||||
affecting.revive(1, 1) //Basically a revive and full heal, including limbs/organs
|
||||
//In case people who have been captured dead want to hang out at the holding area
|
||||
|
||||
playsound(affecting, 'sound/effects/sparks4.ogg', 50, 1)
|
||||
new /obj/effect/temp_visual/dir_setting/ninja/phase/out(affecting.drop_location(), affecting.dir)
|
||||
|
||||
visible_message("[affecting] suddenly vanishes!")
|
||||
affecting.forceMove(pick(GLOB.holdingfacility)) //Throw mob in to the holding facility.
|
||||
to_chat(affecting, "<span class='danger'>You appear in a strange place!</span>")
|
||||
|
||||
if(!QDELETED(master))//As long as they still exist.
|
||||
to_chat(master, "<span class='notice'><b>SUCCESS</b>: transport procedure of [affecting] complete.</span>")
|
||||
do_sparks(5, FALSE, affecting)
|
||||
playsound(affecting, 'sound/effects/phasein.ogg', 25, 1)
|
||||
playsound(affecting, 'sound/effects/sparks2.ogg', 50, 1)
|
||||
new /obj/effect/temp_visual/dir_setting/ninja/phase(affecting.drop_location(), affecting.dir)
|
||||
|
||||
/obj/structure/energy_net/attack_alien(mob/living/carbon/alien/humanoid/user)
|
||||
if(attack_generic(user, 15, BRUTE, "melee", 0)) //Aliens normally deal 60 damage to structures. They'd one-shot nets without this.
|
||||
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
|
||||
|
||||
/obj/structure/energy_net/user_buckle_mob(mob/living/M, mob/living/user)
|
||||
return//We only want our target to be buckled
|
||||
|
||||
/obj/structure/energy_net/user_unbuckle_mob(mob/living/buckled_mob, mob/living/user)
|
||||
return//The net must be destroyed to free the target
|
||||
@@ -1,19 +0,0 @@
|
||||
//Wakes the user so they are able to do their thing. Also injects a decent dose of radium.
|
||||
//Movement impairing would indicate drugs and the like.
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjaboost()
|
||||
|
||||
if(!ninjacost(0,N_ADRENALINE))
|
||||
var/mob/living/carbon/human/H = affecting
|
||||
H.do_adrenaline(150, TRUE, 0, 0, TRUE, list(/datum/reagent/medicine/inaprovaline = 3, /datum/reagent/medicine/synaptizine = 10, /datum/reagent/medicine/omnizine = 10), "<span class='boldnotice'>You feel a sudden surge of energy!</span>")
|
||||
|
||||
H.say(pick("A CORNERED FOX IS MORE DANGEROUS THAN A JACKAL!","HURT ME MOOORRREEE!","IMPRESSIVE!"), forced = "ninjaboost")
|
||||
|
||||
a_boost--
|
||||
to_chat(H, "<span class='notice'>There are <B>[a_boost]</B> adrenaline boosts remaining.</span>")
|
||||
s_coold = 3
|
||||
addtimer(CALLBACK(src, .proc/ninjaboost_after), 70)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjaboost_after()
|
||||
var/mob/living/carbon/human/H = affecting
|
||||
H.reagents.add_reagent(/datum/reagent/radium, a_transfer)
|
||||
to_chat(H, "<span class='danger'>You are beginning to feel the after-effect of the injection.</span>")
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
|
||||
//Cost function for suit Procs/Verbs/Abilities
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjacost(cost = 0, specificCheck = 0)
|
||||
var/mob/living/carbon/human/H = affecting
|
||||
var/actualCost = cost*10
|
||||
if(cost && cell.charge < actualCost)
|
||||
to_chat(H, "<span class='danger'>Not enough energy.</span>")
|
||||
return 1
|
||||
else
|
||||
//This shit used to be handled individually on every proc.. why even bother with a universal check proc then?
|
||||
cell.charge-=(actualCost)
|
||||
|
||||
switch(specificCheck)
|
||||
if(N_STEALTH_CANCEL)
|
||||
cancel_stealth()//Get rid of it.
|
||||
if(N_SMOKE_BOMB)
|
||||
if(!s_bombs)
|
||||
to_chat(H, "<span class='danger'>There are no more smoke bombs remaining.</span>")
|
||||
return 1
|
||||
if(N_ADRENALINE)
|
||||
if(!a_boost)
|
||||
to_chat(H, "<span class='danger'>You do not have any more adrenaline boosters.</span>")
|
||||
return 1
|
||||
return (s_coold)//Returns the value of the variable which counts down to zero.
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
|
||||
//Disables nearby tech equipment.
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjapulse()
|
||||
|
||||
if(!ninjacost(250,N_STEALTH_CANCEL))
|
||||
var/mob/living/carbon/human/H = affecting
|
||||
playsound(H.loc, 'sound/effects/empulse.ogg', 60, 2)
|
||||
empulse_using_range(H, 9) //Procs sure are nice. Slightly weaker than wizard's disable tch.
|
||||
s_coold = 2
|
||||
@@ -1,44 +0,0 @@
|
||||
|
||||
//Allows the ninja to kidnap people
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjanet()
|
||||
var/mob/living/carbon/human/H = affecting
|
||||
var/mob/living/carbon/C
|
||||
|
||||
//If there's only one valid target, let's actually try to capture it, rather than forcing
|
||||
//the user to fiddle with the dialog displaying a list of one
|
||||
//Also, let's make this smarter and not list mobs you can't currently net.
|
||||
var/list/candidates
|
||||
for(var/mob/M in oview(H))
|
||||
if(!M.client)//Monkeys without a client can still step_to() and bypass the net. Also, netting inactive people is lame.
|
||||
continue
|
||||
for(var/obj/structure/energy_net/E in get_turf(M))//Check if they are already being affected by an energy net.
|
||||
if(E.affecting == M)
|
||||
continue
|
||||
LAZYADD(candidates, M)
|
||||
|
||||
if(!LAZYLEN(candidates))
|
||||
return FALSE
|
||||
|
||||
if(candidates.len == 1)
|
||||
C = candidates[1]
|
||||
else
|
||||
C = input("Select who to capture:","Capture who?",null) as null|mob in candidates
|
||||
|
||||
|
||||
if(QDELETED(C)||!(C in oview(H)))
|
||||
return FALSE
|
||||
|
||||
if(!ninjacost(200,N_STEALTH_CANCEL))
|
||||
H.Beam(C,"n_beam",time=15)
|
||||
H.say("Get over here!", forced = "ninja net")
|
||||
var/obj/structure/energy_net/E = new /obj/structure/energy_net(C.drop_location())
|
||||
E.affecting = C
|
||||
E.master = H
|
||||
H.visible_message("<span class='danger'>[H] caught [C] with an energy net!</span>","<span class='notice'>You caught [C] with an energy net!</span>")
|
||||
|
||||
if(C.buckled)
|
||||
C.buckled.unbuckle_mob(affecting,TRUE)
|
||||
E.buckle_mob(C, TRUE) //No moving for you!
|
||||
//The person can still try and attack the net when inside.
|
||||
|
||||
START_PROCESSING(SSobj, E)
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
|
||||
//Smoke bomb
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjasmoke()
|
||||
|
||||
if(!ninjacost(0,N_SMOKE_BOMB))
|
||||
var/mob/living/carbon/human/H = affecting
|
||||
var/datum/effect_system/smoke_spread/bad/smoke = new
|
||||
smoke.set_up(4, H.loc)
|
||||
smoke.start()
|
||||
playsound(H.loc, 'sound/effects/bamf.ogg', 50, 2)
|
||||
s_bombs--
|
||||
to_chat(H, "<span class='notice'>There are <B>[s_bombs]</B> smoke bombs remaining.</span>")
|
||||
s_coold = 1
|
||||
@@ -1,18 +0,0 @@
|
||||
|
||||
|
||||
//Creates a throwing star
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjastar()
|
||||
if(!ninjacost(10))
|
||||
var/mob/living/carbon/human/H = affecting
|
||||
var/obj/item/throwing_star/ninja/N = new(H)
|
||||
if(H.put_in_hands(N))
|
||||
to_chat(H, "<span class='notice'>A throwing star has been created in your hand!</span>")
|
||||
else
|
||||
qdel(N)
|
||||
H.throw_mode_on() //So they can quickly throw it.
|
||||
|
||||
|
||||
/obj/item/throwing_star/ninja
|
||||
name = "ninja throwing star"
|
||||
throwforce = 20
|
||||
embedding = list("pain_mult" = 6, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15)
|
||||
@@ -1,54 +0,0 @@
|
||||
|
||||
/*
|
||||
|
||||
Contents:
|
||||
- Stealth Verbs
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/toggle_stealth()
|
||||
if(!affecting || stealth_cooldown > world.time)
|
||||
return
|
||||
if(stealth)
|
||||
cancel_stealth()
|
||||
else
|
||||
if(cell.charge <= 0)
|
||||
to_chat(affecting, "<span class='warning'>You don't have enough power to enable Stealth!</span>")
|
||||
return
|
||||
stealth = TRUE
|
||||
stealth_cooldown = world.time + 5 SECONDS
|
||||
animate(affecting, alpha = 15, time = 3 SECONDS)
|
||||
affecting.visible_message("<span class='warning'>[affecting.name] vanishes into thin air!</span>", \
|
||||
"<span class='notice'>You are now mostly invisible to normal detection.</span>")
|
||||
addtimer(CALLBACK(src, .proc/enable_signals), 3 SECONDS)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/enable_signals()
|
||||
if(!affecting)
|
||||
return
|
||||
RegisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE), .proc/reduce_stealth)
|
||||
RegisterSignal(affecting, COMSIG_MOVABLE_BUMP, .proc/bumping_stealth)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/reduce_stealth(datum/source)
|
||||
affecting.alpha = min(affecting.alpha + 40, 100)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/bumping_stealth(datum/source, atom/A)
|
||||
if(isliving(A))
|
||||
affecting.alpha = min(affecting.alpha + 20, 100)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/cancel_stealth()
|
||||
if(!affecting || !stealth)
|
||||
return FALSE
|
||||
stealth = !stealth
|
||||
stealth_cooldown = world.time + 5 SECONDS
|
||||
UnregisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE))
|
||||
animate(affecting, alpha = 255, time = 3 SECONDS)
|
||||
affecting.visible_message("<span class='warning'>[affecting.name] appears from thin air!</span>", \
|
||||
"<span class='notice'>You are now visible.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/stealth()
|
||||
if(!s_busy)
|
||||
toggle_stealth()
|
||||
else
|
||||
to_chat(affecting, "<span class='danger'>Stealth does not appear to work!</span>")
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninja_sword_recall()
|
||||
var/mob/living/carbon/human/H = affecting
|
||||
|
||||
var/cost = 0
|
||||
var/inview = 1
|
||||
|
||||
if(!energyKatana)
|
||||
to_chat(H, "<span class='warning'>Could not locate Energy Katana!</span>")
|
||||
return
|
||||
|
||||
if(energyKatana in H)
|
||||
return
|
||||
|
||||
var/distance = get_dist(H,energyKatana)
|
||||
|
||||
if(!(energyKatana in view(H)))
|
||||
cost = distance //Actual cost is cost x 10, so 5 turfs is 50 cost.
|
||||
inview = 0
|
||||
|
||||
if(!ninjacost(cost))
|
||||
if(iscarbon(energyKatana.loc))
|
||||
var/mob/living/carbon/C = energyKatana.loc
|
||||
C.transferItemToLoc(energyKatana, get_turf(energyKatana), TRUE)
|
||||
|
||||
//Somebody swollowed my sword, probably the clown doing a circus act.
|
||||
if(energyKatana in C.stomach_contents)
|
||||
C.stomach_contents -= energyKatana
|
||||
else
|
||||
energyKatana.forceMove(get_turf(energyKatana))
|
||||
|
||||
if(inview) //If we can see the katana, throw it towards ourselves, damaging people as we go.
|
||||
energyKatana.spark_system.start()
|
||||
playsound(H, "sparks", 50, 1)
|
||||
H.visible_message("<span class='danger'>\the [energyKatana] flies towards [H]!</span>","<span class='warning'>You hold out your hand and \the [energyKatana] flies towards you!</span>")
|
||||
energyKatana.throw_at(H, distance+1, energyKatana.throw_speed,H)
|
||||
|
||||
else //Else just TP it to us.
|
||||
energyKatana.returnToOwner(H,1)
|
||||
@@ -1,274 +1,326 @@
|
||||
|
||||
/*
|
||||
|
||||
Contents:
|
||||
- Assorted ninjadrain_act() procs
|
||||
- What is Object Oriented Programming
|
||||
|
||||
They *could* go in their appropriate files, but this is supposed to be modular
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//Needs to return the amount drained from the atom, if no drain on a power object, return FALSE, otherwise, return a define.
|
||||
/atom/proc/ninjadrain_act()
|
||||
/**
|
||||
* Atom level proc for space ninja's glove interactions.
|
||||
*
|
||||
* Proc which only occurs when space ninja uses his gloves on an atom.
|
||||
* Does nothing by default, but effects will vary.
|
||||
* Arguments:
|
||||
* * ninja_suit - The offending space ninja's suit.
|
||||
* * ninja - The human mob wearing the suit.
|
||||
* * ninja_gloves - The offending space ninja's gloves.
|
||||
*/
|
||||
/atom/proc/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
|
||||
|
||||
|
||||
//APC//
|
||||
/obj/machinery/power/apc/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
|
||||
if(!S || !H || !G)
|
||||
/obj/machinery/power/apc/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
var/maxcapacity = 0 //Safety check for batteries
|
||||
var/maxcapacity = FALSE //Safety check for batteries
|
||||
var/drain = 0 //Drain amount from batteries
|
||||
|
||||
. = 0
|
||||
var/drain_total = 0
|
||||
|
||||
if(cell && cell.charge)
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
|
||||
spark_system.set_up(5, 0, loc)
|
||||
|
||||
while(G.candrain && cell.charge> 0 && !maxcapacity)
|
||||
drain = rand(G.mindrain, G.maxdrain)
|
||||
while(ninja_gloves.candrain && cell.charge> 0 && !maxcapacity)
|
||||
drain = rand(ninja_gloves.mindrain, ninja_gloves.maxdrain)
|
||||
|
||||
if(cell.charge < drain)
|
||||
drain = cell.charge
|
||||
|
||||
if(S.cell.charge + drain > S.cell.maxcharge)
|
||||
drain = S.cell.maxcharge - S.cell.charge
|
||||
maxcapacity = 1//Reached maximum battery capacity.
|
||||
if(ninja_suit.cell.charge + drain > ninja_suit.cell.maxcharge)
|
||||
drain = ninja_suit.cell.maxcharge - ninja_suit.cell.charge
|
||||
maxcapacity = TRUE//Reached maximum battery capacity.
|
||||
|
||||
if (do_after(H,10, target = src))
|
||||
if (do_after(ninja ,10, target = src))
|
||||
spark_system.start()
|
||||
playsound(loc, "sparks", 50, 1)
|
||||
cell.charge -= drain
|
||||
S.cell.charge += drain
|
||||
. += drain
|
||||
ninja_suit.cell.charge += drain
|
||||
drain_total += drain
|
||||
else
|
||||
break
|
||||
|
||||
if(!(obj_flags & EMAGGED))
|
||||
flick("apc-spark", G)
|
||||
flick("apc-spark", ninja_gloves)
|
||||
playsound(loc, "sparks", 50, 1)
|
||||
obj_flags |= EMAGGED
|
||||
locked = FALSE
|
||||
update_icon()
|
||||
|
||||
|
||||
|
||||
|
||||
return drain_total
|
||||
|
||||
//SMES//
|
||||
/obj/machinery/power/smes/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
|
||||
if(!S || !H || !G)
|
||||
/obj/machinery/power/smes/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
var/maxcapacity = 0 //Safety check for batteries
|
||||
var/drain = 0 //Drain amount from batteries
|
||||
|
||||
. = 0
|
||||
var/drain = FALSE //Drain amount from batteries
|
||||
var/drain_total = 0
|
||||
|
||||
if(charge)
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
|
||||
spark_system.set_up(5, 0, loc)
|
||||
|
||||
while(G.candrain && charge > 0 && !maxcapacity)
|
||||
drain = rand(G.mindrain, G.maxdrain)
|
||||
while(ninja_gloves.candrain && charge > 0 && !maxcapacity)
|
||||
drain = rand(ninja_gloves.mindrain, ninja_gloves.maxdrain)
|
||||
|
||||
if(charge < drain)
|
||||
drain = charge
|
||||
|
||||
if(S.cell.charge + drain > S.cell.maxcharge)
|
||||
drain = S.cell.maxcharge - S.cell.charge
|
||||
maxcapacity = 1
|
||||
if(ninja_suit.cell.charge + drain > ninja_suit.cell.maxcharge)
|
||||
drain = ninja_suit.cell.maxcharge - ninja_suit.cell.charge
|
||||
maxcapacity = TRUE
|
||||
|
||||
if (do_after(H,10, target = src))
|
||||
if (do_after(ninja,10, target = src))
|
||||
spark_system.start()
|
||||
playsound(loc, "sparks", 50, 1)
|
||||
charge -= drain
|
||||
S.cell.charge += drain
|
||||
. += drain
|
||||
ninja_suit.cell.charge += drain
|
||||
drain_total += drain
|
||||
|
||||
else
|
||||
break
|
||||
|
||||
return drain_total
|
||||
|
||||
//CELL//
|
||||
/obj/item/stock_parts/cell/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
|
||||
if(!S || !H || !G)
|
||||
/obj/item/stock_parts/cell/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
. = 0
|
||||
var/drain_total = 0
|
||||
|
||||
if(charge)
|
||||
if(G.candrain && do_after(H,30, target = src))
|
||||
. = charge
|
||||
if(S.cell.charge + charge > S.cell.maxcharge)
|
||||
S.cell.charge = S.cell.maxcharge
|
||||
if(ninja_gloves.candrain && do_after(ninja,30, target = src))
|
||||
drain_total = charge
|
||||
if(ninja_suit.cell.charge + charge > ninja_suit.cell.maxcharge)
|
||||
ninja_suit.cell.charge = ninja_suit.cell.maxcharge
|
||||
else
|
||||
S.cell.charge += charge
|
||||
ninja_suit.cell.charge += charge
|
||||
charge = 0
|
||||
corrupt()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/proc/AI_notify_hack()
|
||||
var/turf/location = get_turf(src)
|
||||
var/alertstr = "<span class='userdanger'>Network Alert: Hacking attempt detected[location?" in [location]":". Unable to pinpoint location"]</span>."
|
||||
for(var/mob/living/silicon/ai/AI in GLOB.player_list)
|
||||
to_chat(AI, alertstr)
|
||||
return drain_total
|
||||
|
||||
//RDCONSOLE//
|
||||
/obj/machinery/computer/rdconsole/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
|
||||
if(!S || !H || !G)
|
||||
/obj/machinery/computer/rdconsole/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
. = DRAIN_RD_HACK_FAILED
|
||||
|
||||
to_chat(H, "<span class='notice'>Hacking \the [src]...</span>")
|
||||
to_chat(ninja, "<span class='notice'>Hacking \the [src]...</span>")
|
||||
AI_notify_hack()
|
||||
|
||||
if(stored_research)
|
||||
to_chat(H, "<span class='notice'>Copying files...</span>")
|
||||
if(do_after(H, S.s_delay, target = src) && G.candrain && src)
|
||||
stored_research.copy_research_to(S.stored_research)
|
||||
to_chat(H, "<span class='notice'>Data analyzed. Process finished.</span>")
|
||||
to_chat(ninja, "<span class='notice'>Copying files...</span>")
|
||||
if(do_after(ninja, ninja_suit.s_delay, target = src) && ninja_gloves.candrain && src)
|
||||
stored_research.copy_research_to( ninja_suit.stored_research)
|
||||
to_chat(ninja, "<span class='notice'>Data analyzed. Process finished.</span>")
|
||||
|
||||
//RD SERVER//
|
||||
//Shamelessly copypasted from above, since these two used to be the same proc, but with MANY colon operators
|
||||
/obj/machinery/rnd/server/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
|
||||
if(!S || !H || !G)
|
||||
//obj/machinery/rnd/server/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
. = DRAIN_RD_HACK_FAILED
|
||||
|
||||
to_chat(H, "<span class='notice'>Hacking \the [src]...</span>")
|
||||
to_chat(ninja, "<span class='notice'>Hacking \the [src]...</span>")
|
||||
AI_notify_hack()
|
||||
|
||||
if(stored_research)
|
||||
to_chat(H, "<span class='notice'>Copying files...</span>")
|
||||
if(do_after(H, S.s_delay, target = src) && G.candrain && src)
|
||||
stored_research.copy_research_to(S.stored_research)
|
||||
to_chat(H, "<span class='notice'>Data analyzed. Process finished.</span>")
|
||||
to_chat(ninja, "<span class='notice'>Copying files...</span>")
|
||||
if(do_after(ninja, ninja_suit.s_delay, target = src) && ninja_gloves.candrain && src)
|
||||
stored_research.copy_research_to(ninja_suit.stored_research)
|
||||
to_chat(ninja, "<span class='notice'>Data analyzed. Process finished.</span>")
|
||||
|
||||
//SECURITY CONSOLE//
|
||||
/obj/machinery/computer/secure_data/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
if(ninja_gloves.security_console_hack_success)
|
||||
return
|
||||
to_chat(ninja, "<span class='notice'>Hacking \the [src]...</span>")
|
||||
AI_notify_hack()
|
||||
if(do_after(ninja, ninja_suit.s_longdelay, target = src) && ninja_gloves.candrain && src)
|
||||
for(var/datum/data/record/rec in sortRecord(GLOB.data_core.general, sortBy, order))
|
||||
for(var/datum/data/record/security_record in GLOB.data_core.security)
|
||||
security_record.fields["criminal"] = "*Arrest*"
|
||||
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!ninja_antag)
|
||||
return
|
||||
ninja_gloves.security_console_hack_success = TRUE
|
||||
var/datum/objective/security_scramble/objective = locate() in ninja_antag.objectives
|
||||
if(objective)
|
||||
objective.completed = TRUE
|
||||
to_chat(ninja, "<span class='notice'>Security record corruption malware uploaded. Process finished; objective completed.</span>")
|
||||
|
||||
//WIRE//
|
||||
/obj/structure/cable/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
|
||||
if(!S || !H || !G)
|
||||
//COMMUNICATIONS CONSOLE//
|
||||
/obj/machinery/computer/communications/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
if(ninja_gloves.communication_console_hack_success)
|
||||
return
|
||||
to_chat(ninja, "<span class='notice'>Hacking \the [src]...</span>")
|
||||
AI_notify_hack()
|
||||
if(do_after(ninja, ninja_suit.s_longdelay, target = src) && ninja_gloves.candrain && src)
|
||||
var/announcement_pick = rand(0, 1)
|
||||
switch(announcement_pick)
|
||||
if(0)
|
||||
priority_announce("Attention crew, it appears that something on your station has caused an unexpected disruption with the station's airlock network.", "[command_name()] High-Priority Update")
|
||||
var/datum/round_event_control/grey_tide/greytide_event = new/datum/round_event_control/grey_tide
|
||||
greytide_event.runEvent()
|
||||
if(1)
|
||||
priority_announce("Attention crew, it appears that something on your station has made unexpected communication with a syndicate ship in nearby space.", "[command_name()] High-Priority Update")
|
||||
var/datum/round_event_control/pirates/pirate_event = new/datum/round_event_control/pirates
|
||||
pirate_event.runEvent()
|
||||
ninja_gloves.communication_console_hack_success = TRUE
|
||||
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!ninja_antag)
|
||||
return
|
||||
var/datum/objective/terror_message/objective = locate() in ninja_antag.objectives
|
||||
if(objective)
|
||||
objective.completed = TRUE
|
||||
to_chat(ninja, "<span class='notice'>Signal decryption malware uploaded. Process finished; objective completed.</span>")
|
||||
|
||||
//AIRLOCK//
|
||||
/obj/machinery/door/airlock/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
var/maxcapacity = 0 //Safety check
|
||||
if(!operating && density && hasPower() && !(obj_flags & EMAGGED))
|
||||
emag_act()
|
||||
ninja_gloves.door_hack_counter++
|
||||
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!ninja_antag)
|
||||
return
|
||||
var/datum/objective/door_jack/objective = locate() in ninja_antag.objectives
|
||||
if(objective && objective.doors_required <= ninja_gloves.door_hack_counter)
|
||||
objective.completed = TRUE
|
||||
|
||||
//WIRE//
|
||||
/obj/structure/cable/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
var/maxcapacity = FALSE //Safety check
|
||||
var/drain = 0 //Drain amount
|
||||
|
||||
. = 0
|
||||
var/drain_total = 0
|
||||
|
||||
var/datum/powernet/PN = powernet
|
||||
while(G.candrain && !maxcapacity && src)
|
||||
drain = (round((rand(G.mindrain, G.maxdrain))/2))
|
||||
var/datum/powernet/wire_powernet = powernet
|
||||
while(ninja_gloves.candrain && !maxcapacity && src)
|
||||
drain = (round((rand(ninja_gloves.mindrain, ninja_gloves.maxdrain))/2))
|
||||
var/drained = 0
|
||||
if(PN && do_after(H,10, target = src))
|
||||
if(wire_powernet && do_after(ninja,10, target = src))
|
||||
drained = min(drain, delayed_surplus())
|
||||
add_delayedload(drained)
|
||||
if(drained < drain)//if no power on net, drain apcs
|
||||
for(var/obj/machinery/power/terminal/T in PN.nodes)
|
||||
if(istype(T.master, /obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/AP = T.master
|
||||
for(var/obj/machinery/power/terminal/affected_terminal in wire_powernet.nodes)
|
||||
if(istype(affected_terminal.master, /obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/AP = affected_terminal.master
|
||||
if(AP.operating && AP.cell && AP.cell.charge > 0)
|
||||
AP.cell.charge = max(0, AP.cell.charge - 5)
|
||||
drained += 5
|
||||
else
|
||||
break
|
||||
|
||||
S.cell.charge += drained
|
||||
if(S.cell.charge > S.cell.maxcharge)
|
||||
. += (drained-(S.cell.charge - S.cell.maxcharge))
|
||||
S.cell.charge = S.cell.maxcharge
|
||||
maxcapacity = 1
|
||||
ninja_suit.cell.charge += drained
|
||||
if(ninja_suit.cell.charge > ninja_suit.cell.maxcharge)
|
||||
. += (drained-(ninja_suit.cell.charge - ninja_suit.cell.maxcharge))
|
||||
ninja_suit.cell.charge = ninja_suit.cell.maxcharge
|
||||
maxcapacity = TRUE
|
||||
else
|
||||
. += drained
|
||||
S.spark_system.start()
|
||||
drain_total += drained
|
||||
ninja_suit.spark_system.start()
|
||||
|
||||
return drain_total
|
||||
|
||||
//MECH//
|
||||
/obj/mecha/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
|
||||
if(!S || !H || !G)
|
||||
/obj/mecha/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
var/maxcapacity = 0 //Safety check
|
||||
var/maxcapacity = FALSE //Safety check
|
||||
var/drain = 0 //Drain amount
|
||||
. = 0
|
||||
var/drain_total = 0
|
||||
|
||||
occupant_message("<span class='danger'>Warning: Unauthorized access through sub-route 4, block H, detected.</span>")
|
||||
if(get_charge())
|
||||
while(G.candrain && cell.charge > 0 && !maxcapacity)
|
||||
drain = rand(G.mindrain,G.maxdrain)
|
||||
while(ninja_gloves.candrain && cell.charge > 0 && !maxcapacity)
|
||||
drain = rand(ninja_gloves.mindrain, ninja_gloves.maxdrain)
|
||||
if(cell.charge < drain)
|
||||
drain = cell.charge
|
||||
if(S.cell.charge + drain > S.cell.maxcharge)
|
||||
drain = S.cell.maxcharge - S.cell.charge
|
||||
maxcapacity = 1
|
||||
if (do_after(H,10, target = src))
|
||||
if(ninja_suit.cell.charge + drain > ninja_suit.cell.maxcharge)
|
||||
drain = ninja_suit.cell.maxcharge - ninja_suit.cell.charge
|
||||
maxcapacity = TRUE
|
||||
if (do_after(ninja, 10, target = src))
|
||||
spark_system.start()
|
||||
playsound(loc, "sparks", 50, 1)
|
||||
cell.use(drain)
|
||||
S.cell.charge += drain
|
||||
. += drain
|
||||
ninja_suit.cell.give(drain)
|
||||
drain_total += drain
|
||||
else
|
||||
break
|
||||
|
||||
return drain_total
|
||||
|
||||
//BORG//
|
||||
/mob/living/silicon/robot/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
|
||||
if(!S || !H || !G)
|
||||
/mob/living/silicon/robot/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves || (ROLE_NINJA in faction))
|
||||
return INVALID_DRAIN
|
||||
if(ninja_gloves.borg_hack_success)
|
||||
return
|
||||
to_chat(src, "<span class='danger'>Warni-***BZZZZZZZZZRT*** UPLOADING SPYDERPATCHER VERSION 9.5.2...</span>")
|
||||
if (do_after(ninja, 60, target = src))
|
||||
spark_system.start()
|
||||
playsound(loc, "sparks", 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
to_chat(src, "<span class='danger'>UPLOAD COMPLETE. NEW CYBORG MODULE DETECTED. INSTALLING...</span>")
|
||||
faction = list(ROLE_NINJA)
|
||||
bubble_icon = "syndibot"
|
||||
UnlinkSelf()
|
||||
ionpulse = TRUE
|
||||
laws = new /datum/ai_laws/ninja_override()
|
||||
module.transform_to(pick(/obj/item/robot_module/syndicate/spider, /obj/item/robot_module/syndicate_medical/spider, /obj/item/robot_module/saboteur/spider))
|
||||
|
||||
var/maxcapacity = 0 //Safety check
|
||||
var/drain = 0 //Drain amount
|
||||
. = 0
|
||||
|
||||
to_chat(src, "<span class='danger'>Warning: Unauthorized access through sub-route 12, block C, detected.</span>")
|
||||
|
||||
if(cell && cell.charge)
|
||||
while(G.candrain && cell.charge > 0 && !maxcapacity)
|
||||
drain = rand(G.mindrain,G.maxdrain)
|
||||
if(cell.charge < drain)
|
||||
drain = cell.charge
|
||||
if(S.cell.charge+drain > S.cell.maxcharge)
|
||||
drain = S.cell.maxcharge - S.cell.charge
|
||||
maxcapacity = 1
|
||||
if (do_after(H,10))
|
||||
spark_system.start()
|
||||
playsound(loc, "sparks", 50, 1)
|
||||
cell.charge -= drain
|
||||
S.cell.charge += drain
|
||||
. += drain
|
||||
else
|
||||
break
|
||||
|
||||
var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja)
|
||||
if(!ninja_antag)
|
||||
return
|
||||
ninja_gloves.borg_hack_success = TRUE
|
||||
var/datum/objective/cyborg_hijack/objective = locate() in ninja_antag.objectives
|
||||
if(objective)
|
||||
objective.completed = TRUE
|
||||
|
||||
//CARBON MOBS//
|
||||
/mob/living/carbon/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/S, mob/living/carbon/human/H, obj/item/clothing/gloves/space_ninja/G)
|
||||
if(!S || !H || !G)
|
||||
/mob/living/carbon/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves)
|
||||
if(!ninja_suit || !ninja || !ninja_gloves)
|
||||
return INVALID_DRAIN
|
||||
|
||||
. = DRAIN_MOB_SHOCK_FAILED
|
||||
|
||||
//Default cell = 10,000 charge, 10,000/1000 = 10 uses without charging/upgrading
|
||||
if(S.cell && S.cell.charge && S.cell.use(500))
|
||||
if(ninja_suit.cell?.charge && ninja_suit.cell.use(1000))
|
||||
. = DRAIN_MOB_SHOCK
|
||||
//Got that electric touch
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
|
||||
spark_system.set_up(5, 0, loc)
|
||||
playsound(src, "sparks", 50, 1)
|
||||
visible_message("<span class='danger'>[H] electrocutes [src] with [H.p_their()] touch!</span>", "<span class='userdanger'>[H] electrocutes you with [H.p_their()] touch!</span>")
|
||||
electrocute_act(15, H, flags = SHOCK_NOSTUN)
|
||||
visible_message("<span class='danger'>[ninja] electrocutes [src] with [ninja.p_their()] touch!</span>", "<span class='userdanger'>[ninja] electrocutes you with [ninja.p_their()] touch!</span>")
|
||||
electrocute_act(15, ninja, flags = SHOCK_NOSTUN)
|
||||
|
||||
DefaultCombatKnockdown(G.stunforce, override_hardstun = 0)
|
||||
apply_effect(EFFECT_STUTTER, G.stunforce)
|
||||
DefaultCombatKnockdown(ninja_gloves.stunforce, override_hardstun = 0)
|
||||
apply_effect(EFFECT_STUTTER, ninja_gloves.stunforce)
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_MINOR_SHOCK)
|
||||
|
||||
set_last_attacker(H)
|
||||
log_combat(H, src, "stunned")
|
||||
lastattacker = ninja.real_name
|
||||
lastattackerckey = ninja.ckey
|
||||
log_combat(ninja, src, "stunned")
|
||||
set_last_attacker(ninja)
|
||||
log_combat(ninja, src, "stunned")
|
||||
|
||||
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* # Energy Net
|
||||
*
|
||||
* Energy net which ensnares prey until it is destroyed. Used by space ninjas.
|
||||
*
|
||||
* Energy net which keeps its target from moving until it is destroyed. Used to send
|
||||
* players to a holding area in which they could never leave, but such feature has since
|
||||
* been removed.
|
||||
*/
|
||||
/obj/structure/energy_net
|
||||
name = "energy net"
|
||||
desc = "It's a net made of green energy."
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "energynet"
|
||||
|
||||
|
||||
density = TRUE//Can't pass through.
|
||||
opacity = FALSE //Can see through.
|
||||
mouse_opacity = MOUSE_OPACITY_ICON//So you can hit it with stuff.
|
||||
anchored = TRUE//Can't drag/grab the net.
|
||||
layer = ABOVE_ALL_MOB_LAYER
|
||||
max_integrity = 60 //How much health it has.
|
||||
can_buckle = 1
|
||||
buckle_lying = 0
|
||||
buckle_prevents_pull = TRUE
|
||||
///The creature currently caught in the net
|
||||
var/mob/living/affecting
|
||||
|
||||
/obj/structure/energy_net/play_attack_sound(damage, damage_type = BRUTE, damage_flag = 0)
|
||||
if(damage_type == BRUTE || damage_type == BURN)
|
||||
playsound(src, 'sound/weapons/slash.ogg', 80, TRUE)
|
||||
|
||||
/obj/structure/energy_net/Destroy()
|
||||
if(!QDELETED(affecting))
|
||||
affecting.visible_message("<span class='notice'>[affecting.name] is recovered from the energy net!</span>", "<span class='notice'>You are recovered from the energy net!</span>", "<span class='hear'>You hear a grunt.</span>")
|
||||
affecting = null
|
||||
return ..()
|
||||
|
||||
/obj/structure/energy_net/attack_paw(mob/user)
|
||||
return attack_hand()
|
||||
|
||||
/obj/structure/energy_net/user_buckle_mob(mob/living/M, mob/user, check_loc = TRUE)
|
||||
return//We only want our target to be buckled
|
||||
|
||||
/obj/structure/energy_net/user_unbuckle_mob(mob/living/buckled_mob, mob/living/user)
|
||||
return//The net must be destroyed to free the target
|
||||
@@ -0,0 +1,38 @@
|
||||
//Wakes the user so they are able to do their thing. Also injects a decent dose of radium.
|
||||
//Movement impairing would indicate drugs and the like.
|
||||
|
||||
/datum/action/item_action/ninjaboost
|
||||
check_flags = NONE
|
||||
name = "Adrenaline Boost"
|
||||
desc = "Inject a secret chemical that will counteract all movement-impairing effect."
|
||||
button_icon_state = "adrenal"
|
||||
icon_icon = 'icons/obj/implants.dmi'
|
||||
required_mobility_flags = NONE
|
||||
|
||||
/**
|
||||
* Proc called to activate space ninja's adrenaline.
|
||||
*
|
||||
* Proc called to use space ninja's adrenaline. Gets the ninja out of almost any stun.
|
||||
* Also makes them shout MGS references when used. After a bit, it injects the user with
|
||||
* radium by calling a different proc.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjaboost()
|
||||
if(ninjacost(0,N_ADRENALINE))
|
||||
return
|
||||
var/mob/living/carbon/human/ninja = affecting
|
||||
ninja.do_adrenaline(150, TRUE, 0, 0, TRUE, list(/datum/reagent/medicine/epinephrine = 3, /datum/reagent/medicine/regen_jelly = 10, /datum/reagent/medicine/stimulants = 2), "<span class='boldnotice'>You feel a sudden surge of energy!</span>")
|
||||
ninja.say(pick("A CORNERED FOX IS MORE DANGEROUS THAN A JACKAL!","HURT ME MOOORRREEE!","IMPRESSIVE!"), forced = "ninjaboost")
|
||||
a_boost = FALSE
|
||||
to_chat(ninja, "<span class='notice'>You have used the adrenaline boost.</span>")
|
||||
addtimer(CALLBACK(src, .proc/ninjaboost_after), 70)
|
||||
|
||||
/**
|
||||
* Proc called to inject the ninja with radium.
|
||||
*
|
||||
* Used after 7 seconds of using the ninja's adrenaline.
|
||||
* Injects the user with how much radium the suit needs to refill an adrenaline boost.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjaboost_after()
|
||||
var/mob/living/carbon/human/ninja = affecting
|
||||
ninja.reagents.add_reagent(/datum/reagent/radium, a_transfer * 0.25)
|
||||
to_chat(ninja, "<span class='danger'>You are beginning to feel the after-effect of the injection.</span>")
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Proc called to check if the ninja can afford an ability's cost.
|
||||
*
|
||||
* Proc which determine whether or not a space ninja can afford to use a specific ability.
|
||||
* It can also cancel stealth if the ability requested it.
|
||||
* Arguments:
|
||||
* * cost - the energy cost of the ability
|
||||
* * specificCheck - Determines if the check is a normal one, an adrenaline one, or a stealth cancel check.
|
||||
* * Returns TRUE or the current cooldown timer if we can't perform the ability, and FALSE if we can.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjacost(cost = 0, specificCheck = 0)
|
||||
var/mob/living/carbon/human/ninja = affecting
|
||||
var/actualCost = cost*10
|
||||
if(cost && cell.charge < actualCost)
|
||||
to_chat(ninja, "<span class='warning'>Not enough energy!</span>")
|
||||
return TRUE
|
||||
else
|
||||
//This shit used to be handled individually on every proc.. why even bother with a universal check proc then?
|
||||
cell.charge-=(actualCost)
|
||||
|
||||
switch(specificCheck)
|
||||
if(N_STEALTH_CANCEL)
|
||||
cancel_stealth()//Get rid of it.
|
||||
if(N_ADRENALINE)
|
||||
if(!a_boost)
|
||||
to_chat(ninja, "<span class='warning'>You do not have any more adrenaline boosters!</span>")
|
||||
return TRUE
|
||||
return (s_coold)//Returns the value of the variable which counts down to zero.
|
||||
@@ -0,0 +1,21 @@
|
||||
//Disables nearby tech equipment.
|
||||
|
||||
/datum/action/item_action/ninjapulse
|
||||
name = "EM Burst (50E)"
|
||||
desc = "Disable any nearby technology with an electro-magnetic pulse."
|
||||
button_icon_state = "emp"
|
||||
icon_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
|
||||
/**
|
||||
* Proc called to allow the ninja to EMP the nearby area.
|
||||
*
|
||||
* Proc called to allow the ninja to EMP the nearby area. By default, costs 500E, which is half of the default battery's max charge.
|
||||
* Also affects the ninja as well.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjapulse()
|
||||
if(ninjacost(500,N_STEALTH_CANCEL))
|
||||
return
|
||||
var/mob/living/carbon/human/H = affecting
|
||||
playsound(H.loc, 'sound/effects/empulse.ogg', 60, 2)
|
||||
empulse(H, 4, 6) //Procs sure are nice. Slightly weaker than wizard's disable tch.
|
||||
s_coold = 4
|
||||
@@ -0,0 +1,15 @@
|
||||
/datum/action/item_action/toggle_glove
|
||||
name = "Toggle interaction"
|
||||
desc = "Switch between normal interaction and drain mode."
|
||||
button_icon_state = "s-ninjan"
|
||||
icon_icon = 'icons/obj/clothing/gloves.dmi'
|
||||
|
||||
/**
|
||||
* Proc called to toggle the ninja glove's special abilities.
|
||||
*
|
||||
* Used to toggle whether or not the ninja glove's abilities will activate on touch.
|
||||
*/
|
||||
/obj/item/clothing/gloves/space_ninja/proc/toggledrain()
|
||||
var/mob/living/carbon/human/ninja = loc
|
||||
to_chat(ninja, "<span class='notice'>You [candrain?"disable":"enable"] special interaction.</span>")
|
||||
candrain=!candrain
|
||||
@@ -0,0 +1,36 @@
|
||||
/datum/action/item_action/ninjanet
|
||||
name = "Energy Net (40E)"
|
||||
desc = "Captures a fallen opponent in a net of energy."
|
||||
button_icon_state = "energynet"
|
||||
icon_icon = 'icons/effects/effects.dmi'
|
||||
|
||||
/**
|
||||
* Proc called to ensnare a person in a energy net.
|
||||
*
|
||||
* Used to ensnare a target in an energy net, preventing them from moving until the net is broken.
|
||||
* Costs 40E, which is 40% of the default battery's max charge. Intended as a means of reliably locking down an opponent when ninja stars won't suffice.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjanet()
|
||||
var/mob/living/carbon/human/ninja = affecting
|
||||
var/mob/living/net_target = input("Select who to capture:","Capture who?",null) as null|mob in sortNames(oview(ninja))
|
||||
|
||||
if(QDELETED(net_target)||!(net_target in oview(ninja)))
|
||||
return
|
||||
|
||||
if(locate(/obj/structure/energy_net) in get_turf(net_target))//Check if they are already being affected by an energy net.
|
||||
to_chat(ninja, "<span class='warning'>[net_target.p_they(TRUE)] are already trapped inside an energy net!</span>")
|
||||
return
|
||||
for(var/turf/between_turf in getline(get_turf(ninja), get_turf(net_target)))
|
||||
if(between_turf.density)//Don't want them shooting nets through walls. It's kind of cheesy.
|
||||
to_chat(ninja, "<span class='warning'>You may not use an energy net through solid obstacles!</span>")
|
||||
return
|
||||
if(!ninjacost(400,N_STEALTH_CANCEL))
|
||||
ninja.Beam(net_target, "n_beam", time = 15)
|
||||
ninja.say("Get over here!", forced = "ninja net")
|
||||
var/obj/structure/energy_net/net = new /obj/structure/energy_net(net_target.drop_location())
|
||||
net.affecting = net_target
|
||||
ninja.visible_message("<span class='danger'>[ninja] caught [net_target] with an energy net!</span>","<span class='notice'>You caught [net_target] with an energy net!</span>")
|
||||
|
||||
if(net_target.buckled)
|
||||
net_target.buckled.unbuckle_mob(affecting,TRUE)
|
||||
net.buckle_mob(net_target, TRUE) //No moving for you!
|
||||
@@ -0,0 +1,46 @@
|
||||
/datum/action/item_action/ninjastar
|
||||
name = "Create Throwing Stars (1E)"
|
||||
desc = "Creates a throwing star in your hand, if possible."
|
||||
button_icon_state = "throwingstar"
|
||||
icon_icon = 'icons/obj/items_and_weapons.dmi'
|
||||
|
||||
/**
|
||||
* Proc called to create a ninja star in the ninja's hands.
|
||||
*
|
||||
* Called to create a ninja star in the wearer's hand. The ninja
|
||||
* star doesn't do much up-front damage, but deals stamina damage
|
||||
* as the target moves around, forcing a finish or flee scenario.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjastar()
|
||||
if(ninjacost(10))
|
||||
return
|
||||
var/mob/living/carbon/human/ninja = affecting
|
||||
var/obj/item/throwing_star/stamina/ninja/ninja_star = new(ninja)
|
||||
if(ninja.put_in_hands(ninja_star))
|
||||
to_chat(ninja, "<span class='notice'>A throwing star has been created in your hand!</span>")
|
||||
else
|
||||
qdel(ninja_star)
|
||||
to_chat(ninja, "<span class='notice'>You can't create a throwing star, your hands are full!</span>")
|
||||
ninja.throw_mode_on() //So they can quickly throw it.
|
||||
|
||||
/**
|
||||
* # Ninja Throwing Star
|
||||
*
|
||||
* a throwing star which specifically makes sure you know it came from a real ninja.
|
||||
*
|
||||
* The most important item in the entire codebase, as without it we would all cease to exist.
|
||||
* Inherits everything that makes it interesting the stamina throwing star, but the most
|
||||
* important change made is that its name specifically has the prefix, 'ninja' in it.
|
||||
* This provides the detective role with information to play off of by ensuring that his
|
||||
* assumption that a space ninja is aboard the ship to be true when he find 20 of these in
|
||||
* the captain's back. Along with this, its throwforce is 10 instead of the 5 of the stamina
|
||||
* throwing star, meaning it'll do a little more damage than the stamina throwing star does as well.
|
||||
* Changes to this item need to be approved by all maintainers, so if you do change it, make sure
|
||||
* you go through the proper channels, lest you get permabanned. Do I make myself clear?
|
||||
*/
|
||||
/obj/item/throwing_star/stamina/ninja
|
||||
name = "ninja throwing star"
|
||||
icon_state = "ninjastar"
|
||||
item_state = "ninjastar"
|
||||
throwforce = 10
|
||||
embedding = list("pain_chance" = 5, "embed_chance" = 100, "fall_chance" = 10, "jostle_chance" = 10, "pain_stam_pct" = 2.5, "jostle_pain_mult" = 3)
|
||||
@@ -0,0 +1,39 @@
|
||||
/datum/action/item_action/ninjastatus
|
||||
check_flags = NONE
|
||||
name = "Status Readout"
|
||||
desc = "Gives a detailed readout about your current status."
|
||||
button_icon_state = "health"
|
||||
icon_icon = 'icons/obj/device.dmi'
|
||||
var/action_background_icon_state = "bg_default_on"
|
||||
|
||||
/**
|
||||
* Proc called to put a status readout to the ninja in chat.
|
||||
*
|
||||
* Called put some information about the ninja's current status into chat.
|
||||
* This information used to be displayed constantly on the status tab screen
|
||||
* when the suit was on, but was turned into this as to remove the code from
|
||||
* human.dm
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjastatus()
|
||||
var/mob/living/carbon/human/ninja = affecting
|
||||
var/list/info_list = list()
|
||||
info_list += "<span class='info'>SpiderOS Status: [s_initialized ? "Initialized" : "Disabled"]</span>\n"
|
||||
//Ninja status
|
||||
info_list += "<span class='info'>Fingerprints: [md5(ninja.dna.uni_identity)]</span>\n"
|
||||
info_list += "<span class='info'>Unique Identity: [ninja.dna.unique_enzymes]</span>\n"
|
||||
info_list += "<span class='info'>Overall Status: [ninja.stat > 1 ? "dead" : "[ninja.health]% healthy"]</span>\n"
|
||||
info_list += "<span class='info'>Nutrition Status: [ninja.nutrition]</span>\n"
|
||||
info_list += "<span class='info'>Oxygen Loss: [ninja.getOxyLoss()]</span>\n"
|
||||
info_list += "<span class='info'>Toxin Levels: [ninja.getToxLoss()]</span>\n"
|
||||
info_list += "<span class='info'>Burn Severity: [ninja.getFireLoss()]</span>\n"
|
||||
info_list += "<span class='info'>Brute Trauma: [ninja.getBruteLoss()]</span>\n"
|
||||
info_list += "<span class='info'>Radiation Levels: [ninja.radiation] rad</span>\n"
|
||||
info_list += "<span class='info'>Body Temperature: [ninja.bodytemperature-T0C] degrees C ([ninja.bodytemperature*1.8-459.67] degrees F)</span>\n"
|
||||
|
||||
//Diseases
|
||||
if(length(ninja.diseases))
|
||||
info_list += "Viruses:"
|
||||
for(var/datum/disease/ninja_disease in ninja.diseases)
|
||||
info_list += "<span class='info'>* [ninja_disease.name], Type: [ninja_disease.spread_text], Stage: [ninja_disease.stage]/[ninja_disease.max_stages], Possible Cure: [ninja_disease.cure_text]</span>\n"
|
||||
|
||||
to_chat(ninja, "[info_list.Join()]")
|
||||
@@ -0,0 +1,46 @@
|
||||
/datum/action/item_action/ninja_stealth
|
||||
name = "Toggle Stealth"
|
||||
desc = "Toggles stealth mode on and off."
|
||||
button_icon_state = "ninja_cloak"
|
||||
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
|
||||
|
||||
/**
|
||||
* Proc called to toggle ninja stealth.
|
||||
*
|
||||
* Proc called to toggle whether or not the ninja is in stealth mode.
|
||||
* If cancelling, calls a separate proc in case something else needs to quickly cancel stealth.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/toggle_stealth()
|
||||
var/mob/living/carbon/human/ninja = affecting
|
||||
if(!ninja)
|
||||
return
|
||||
if(stealth)
|
||||
cancel_stealth()
|
||||
else
|
||||
if(cell.charge <= 0)
|
||||
to_chat(ninja, "<span class='warning'>You don't have enough power to enable Stealth!</span>")
|
||||
return
|
||||
stealth = !stealth
|
||||
animate(ninja, alpha = 20,time = 12)
|
||||
ninja.visible_message("<span class='warning'>[ninja.name] vanishes into thin air!</span>", \
|
||||
"<span class='notice'>You are now mostly invisible to normal detection.</span>")
|
||||
|
||||
/**
|
||||
* Proc called to cancel stealth.
|
||||
*
|
||||
* Called to cancel the stealth effect if it is ongoing.
|
||||
* Does nothing otherwise.
|
||||
* Arguments:
|
||||
* * Returns false if either the ninja no longer exists or is already visible, returns true if we successfully made the ninja visible.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/cancel_stealth()
|
||||
var/mob/living/carbon/human/ninja = affecting
|
||||
if(!ninja)
|
||||
return FALSE
|
||||
if(stealth)
|
||||
stealth = !stealth
|
||||
animate(ninja, alpha = 255, time = 12)
|
||||
ninja.visible_message("<span class='warning'>[ninja.name] appears from thin air!</span>", \
|
||||
"<span class='notice'>You are now visible.</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
@@ -0,0 +1,123 @@
|
||||
#define NINJA_LOCK_PHASE 1
|
||||
#define NINJA_ICON_GENERATE_PHASE 3
|
||||
#define NINJA_COMPLETE_PHASE 6
|
||||
#define NINJA_DEINIT_LOGOFF_PHASE 1
|
||||
#define NINJA_DEINIT_STEALTH_PHASE 5
|
||||
|
||||
GLOBAL_LIST_INIT(ninja_initialize_messages, list(
|
||||
"Now initializing...",
|
||||
"Securing external locking mechanism...\nNeural-net established.",
|
||||
"Extending neural-net interface...\nNow monitoring brain wave pattern...",
|
||||
"Linking neural-net interface...\nPattern <b class='nicegreen'>GREEN</b>, continuing operation.",
|
||||
"VOID-shift device status: <B>ONLINE</B>.\nCLOAK-tech device status: <B>ONLINE</B>.",
|
||||
"Primary system status: <B>ONLINE</B>.\nBackup system status: <B>ONLINE</B>.\nCurrent energy capacity: ",
|
||||
"All systems operational. Welcome to <B>SpiderOS</B>, "
|
||||
))
|
||||
|
||||
GLOBAL_LIST_INIT(ninja_deinitialize_messages, list(
|
||||
"Now de-initializing...",
|
||||
"Shutting down <B>SpiderOS</B>.",
|
||||
"Primary system status: <B>OFFLINE</B>.\nBackup system status: <B>OFFLINE</B>.",
|
||||
"VOID-shift device status: <B>OFFLINE</B>.\nCLOAK-tech device status: <B>OFFLINE</B>.",
|
||||
"Disconnecting neural-net interface...<b class='nicegreen'>Success</b>.",
|
||||
"Disengaging neural-net interface... <b class='nicegreen'>Success</b>.",
|
||||
"Unsecuring external locking mechanism...\nNeural-net abolished.\nOperation status: <B>FINISHED</B>."
|
||||
))
|
||||
|
||||
/datum/action/item_action/initialize_ninja_suit
|
||||
name = "Toggle Ninja Suit"
|
||||
|
||||
/**
|
||||
* Toggles the ninja suit on/off
|
||||
*
|
||||
* Attempts to initialize or deinitialize the ninja suit
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/toggle_on_off()
|
||||
. = TRUE
|
||||
if(s_busy)
|
||||
to_chat(loc, "<span class='warning'>ERROR</span>: You cannot use this function at this time.")
|
||||
return FALSE
|
||||
s_busy = TRUE
|
||||
if(s_initialized)
|
||||
deinitialize()
|
||||
else
|
||||
ninitialize()
|
||||
|
||||
/**
|
||||
* Initializes the ninja suit
|
||||
*
|
||||
* Initializes the ninja suit through seven phases, each of which calls this proc with an incremented phase
|
||||
* Arguments:
|
||||
* * delay - The delay between each phase of initialization
|
||||
* * ninja - The human who is being affected by the suit
|
||||
* * phase - The phase of initialization
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize(delay = s_delay, mob/living/carbon/human/ninja = loc, phase = 0)
|
||||
if(!ninja || !ninja.mind)
|
||||
s_busy = FALSE
|
||||
return
|
||||
if (phase > NINJA_LOCK_PHASE && (ninja.stat == DEAD || ninja.health <= 0))
|
||||
to_chat(ninja, "<span class='danger'><B>FÄAL �Rr�R</B>: 344--93#�&&21 BR��N |/|/aV� PATT$RN <B>RED</B>\nA-A-aB�rT�NG...</span>")
|
||||
unlock_suit(ninja)
|
||||
s_busy = FALSE
|
||||
return
|
||||
|
||||
var/message = GLOB.ninja_initialize_messages[phase + 1]
|
||||
switch(phase)
|
||||
if (NINJA_LOCK_PHASE)
|
||||
if(!lock_suit(ninja))//To lock the suit onto wearer.
|
||||
s_busy = FALSE
|
||||
return
|
||||
if (NINJA_COMPLETE_PHASE - 1)
|
||||
message += "<B>[DisplayEnergy(cell.charge)]</B>."
|
||||
if (NINJA_COMPLETE_PHASE)
|
||||
message += "[ninja.real_name]."
|
||||
ninja.regenerate_icons()
|
||||
s_initialized = TRUE
|
||||
s_busy = FALSE
|
||||
|
||||
to_chat(ninja, "<span class='notice'>[message]</span>")
|
||||
playsound(ninja, 'sound/effects/sparks1.ogg', 10, TRUE)
|
||||
|
||||
if (phase < NINJA_COMPLETE_PHASE)
|
||||
addtimer(CALLBACK(src, .proc/ninitialize, delay, ninja, phase + 1), delay)
|
||||
|
||||
/**
|
||||
* Deinitializes the ninja suit
|
||||
*
|
||||
* Deinitializes the ninja suit through eight phases, each of which calls this proc with an incremented phase
|
||||
* Arguments:
|
||||
* * delay - The delay between each phase of deinitialization
|
||||
* * ninja - The human who is being affected by the suit
|
||||
* * phase - The phase of deinitialization
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize(delay = s_delay, mob/living/carbon/human/ninja = affecting == loc ? affecting : null, phase = 0)
|
||||
if (!ninja || !ninja.mind)
|
||||
s_busy = FALSE
|
||||
return
|
||||
if (phase == 0 && alert("Are you certain you wish to remove the suit? This will take time and remove all abilities.",,"Yes","No") == "No")
|
||||
s_busy = FALSE
|
||||
return
|
||||
|
||||
var/message = GLOB.ninja_deinitialize_messages[phase + 1]
|
||||
switch(phase)
|
||||
if(NINJA_DEINIT_LOGOFF_PHASE)
|
||||
message = "Logging off, [ninja.real_name]. " + message
|
||||
if(NINJA_DEINIT_STEALTH_PHASE)
|
||||
cancel_stealth()
|
||||
to_chat(ninja, "<span class='notice'>[message]</span>")
|
||||
playsound(ninja, 'sound/items/deconstruct.ogg', 10, TRUE)
|
||||
|
||||
if (phase < NINJA_COMPLETE_PHASE)
|
||||
addtimer(CALLBACK(src, .proc/deinitialize, delay, ninja, phase + 1), delay)
|
||||
else
|
||||
unlock_suit(ninja)
|
||||
ninja.regenerate_icons()
|
||||
s_initialized = FALSE
|
||||
s_busy = FALSE
|
||||
|
||||
#undef NINJA_LOCK_PHASE
|
||||
#undef NINJA_ICON_GENERATE_PHASE
|
||||
#undef NINJA_COMPLETE_PHASE
|
||||
#undef NINJA_DEINIT_LOGOFF_PHASE
|
||||
#undef NINJA_DEINIT_STEALTH_PHASE
|
||||
@@ -0,0 +1,48 @@
|
||||
/datum/action/item_action/ninja_sword_recall
|
||||
name = "Recall Energy Katana (Variable Cost)"
|
||||
desc = "Teleports the Energy Katana linked to this suit to its wearer, cost based on distance."
|
||||
button_icon_state = "energy_katana"
|
||||
icon_icon = 'icons/obj/items_and_weapons.dmi'
|
||||
|
||||
/**
|
||||
* Proc called to recall the ninja's sword.
|
||||
*
|
||||
* Called to summon the ninja's katana back to them
|
||||
* If the katana can see the ninja, it will throw itself towards them.
|
||||
* If not, the katana will teleport itself to the ninja.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninja_sword_recall()
|
||||
var/mob/living/carbon/human/ninja = affecting
|
||||
var/cost = 0
|
||||
var/inview = TRUE
|
||||
|
||||
if(!energyKatana)
|
||||
to_chat(ninja, "<span class='warning'>Could not locate Energy Katana!</span>")
|
||||
return
|
||||
|
||||
if(energyKatana in ninja)
|
||||
return
|
||||
|
||||
var/distance = get_dist(ninja,energyKatana)
|
||||
|
||||
if(!(energyKatana in view(ninja)))
|
||||
cost = distance //Actual cost is cost x 10, so 5 turfs is 50 cost.
|
||||
inview = FALSE
|
||||
|
||||
if(!ninjacost(cost))
|
||||
if(iscarbon(energyKatana.loc))
|
||||
var/mob/living/carbon/sword_holder = energyKatana.loc
|
||||
sword_holder.transferItemToLoc(energyKatana, get_turf(energyKatana), TRUE)
|
||||
|
||||
else
|
||||
energyKatana.forceMove(get_turf(energyKatana))
|
||||
|
||||
if(inview) //If we can see the katana, throw it towards ourselves, damaging people as we go.
|
||||
energyKatana.spark_system.start()
|
||||
playsound(ninja, "sparks", 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
ninja.visible_message("<span class='danger'>\the [energyKatana] flies towards [ninja]!</span>","<span class='warning'>You hold out your hand and \the [energyKatana] flies towards you!</span>")
|
||||
energyKatana.throw_at(ninja, distance+1, energyKatana.throw_speed, ninja)
|
||||
|
||||
else //Else just TP it to us.
|
||||
energyKatana.returnToOwner(ninja, 1)
|
||||
s_coold = 4
|
||||
@@ -1,3 +1,12 @@
|
||||
/**
|
||||
* # Ninja Shoes
|
||||
*
|
||||
* Space ninja's shoes. Gives him armor on his feet.
|
||||
*
|
||||
* Space ninja's ninja shoes. How mousey. Gives him slip protection and protection against attacks.
|
||||
* Also are temperature resistant.
|
||||
*
|
||||
*/
|
||||
/obj/item/clothing/shoes/space_ninja
|
||||
name = "ninja shoes"
|
||||
desc = "A pair of running shoes. Excellent for running and even better for smashing skulls."
|
||||
@@ -5,8 +14,7 @@
|
||||
permeability_coefficient = 0.01
|
||||
clothing_flags = NOSLIP
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
armor = list("melee" = 60, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 100, "acid" = 100)
|
||||
strip_delay = 120
|
||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 20,"energy" = 30, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 100, "acid" = 100)
|
||||
cold_protection = FEET
|
||||
min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT
|
||||
heat_protection = FEET
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
|
||||
/*
|
||||
|
||||
Contents:
|
||||
- The Ninja Space Suit
|
||||
- Ninja Space Suit Procs
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// /obj/item/clothing/suit/space/space_ninja
|
||||
|
||||
|
||||
/**
|
||||
* # Ninja Suit
|
||||
*
|
||||
* Space ninja's suit. Provides him with most of his powers.
|
||||
*
|
||||
* Space ninja's suit. Gives space ninja all his iconic powers, which are mostly kept in
|
||||
* the folder ninja_equipment_actions. Has a lot of unique stuff going on, so make sure to check
|
||||
* the variables. Check suit_attackby to see radium interaction, disk copying, and cell replacement.
|
||||
*
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja
|
||||
name = "ninja suit"
|
||||
desc = "A unique, vacuum-proof suit of nano-enhanced armor designed specifically for Spider Clan assassins."
|
||||
@@ -19,12 +16,11 @@ Contents:
|
||||
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/stock_parts/cell)
|
||||
slowdown = 1
|
||||
resistance_flags = LAVA_PROOF | ACID_PROOF
|
||||
armor = list("melee" = 60, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 100, "acid" = 100)
|
||||
strip_delay = 12
|
||||
armor = list("melee" = 40, "bullet" = 30, "laser" = 20,"energy" = 30, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 100, "acid" = 100)
|
||||
|
||||
actions_types = list(/datum/action/item_action/initialize_ninja_suit, /datum/action/item_action/ninjasmoke, /datum/action/item_action/ninjaboost, /datum/action/item_action/ninjapulse, /datum/action/item_action/ninjastar, /datum/action/item_action/ninja_sword_recall, /datum/action/item_action/ninja_stealth, /datum/action/item_action/toggle_glove)
|
||||
actions_types = list(/datum/action/item_action/initialize_ninja_suit, /datum/action/item_action/ninjastatus, /datum/action/item_action/ninjaboost, /datum/action/item_action/ninjapulse, /datum/action/item_action/ninjastar, /datum/action/item_action/ninjanet, /datum/action/item_action/ninja_sword_recall, /datum/action/item_action/ninja_stealth)
|
||||
|
||||
//Important parts of the suit.
|
||||
///The person wearing the suit
|
||||
var/mob/living/carbon/human/affecting = null
|
||||
var/obj/item/stock_parts/cell/cell
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
@@ -37,28 +33,38 @@ Contents:
|
||||
var/obj/item/clothing/shoes/space_ninja/n_shoes
|
||||
var/obj/item/clothing/gloves/space_ninja/n_gloves
|
||||
|
||||
//Main function variables.
|
||||
var/s_initialized = 0//Suit starts off.
|
||||
var/s_coold = 0//If the suit is on cooldown. Can be used to attach different cooldowns to abilities. Ticks down every second based on suit ntick().
|
||||
var/s_cost = 5//Base energy cost each ntick.
|
||||
var/s_acost = 25//Additional cost for additional powers active.
|
||||
var/s_delay = 40//How fast the suit does certain things, lower is faster. Can be overridden in specific procs. Also determines adverse probability.
|
||||
var/a_transfer = 20//How much radium is used per adrenaline boost.
|
||||
var/a_maxamount = 7//Maximum number of adrenaline boosts.
|
||||
var/s_maxamount = 20//Maximum number of smoke bombs.
|
||||
///The space ninja's mask.
|
||||
var/obj/item/clothing/mask/gas/space_ninja/n_mask
|
||||
|
||||
//Support function variables.
|
||||
///Whether or not the suit is currently booted up. Starts off.
|
||||
var/s_initialized = FALSE//Suit starts off.
|
||||
///The suit's current cooldown. If not 0, blocks usage of most abilities, and decrements its value by 1 every process
|
||||
var/s_coold = 0
|
||||
///How much energy the suit expends in a single process
|
||||
var/s_cost = 1
|
||||
///Additional energy cost for cloaking per process
|
||||
var/s_acost = 20
|
||||
///How fast the suit is at certain actions, like draining power from things
|
||||
var/s_delay = 40
|
||||
///How fast the suit is at certain riskier actions, like hacking communications consoles.
|
||||
var/s_longdelay = 200
|
||||
///Units of radium required to refill the adrenaline boost
|
||||
var/a_transfer = 20//How much radium is required to refill the adrenaline boost.
|
||||
///Whether or not the suit is currently in stealth mode.
|
||||
var/stealth = FALSE//Stealth off.
|
||||
var/stealth_cooldown = 0
|
||||
var/s_busy = FALSE//Is the suit busy with a process? Like AI hacking. Used for safety functions.
|
||||
|
||||
//Ability function variables.
|
||||
var/s_bombs = 10//Number of smoke bombs.
|
||||
var/a_boost = 3//Number of adrenaline boosters.
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/get_cell()
|
||||
return cell
|
||||
///Whether or not the wearer is in the middle of an action, like hacking.
|
||||
var/s_busy = FALSE
|
||||
///Whether or not the adrenaline boost ability is available
|
||||
var/a_boost = TRUE
|
||||
/obj/item/clothing/suit/space/space_ninja/examine(mob/user)
|
||||
. = ..()
|
||||
if(!s_initialized)
|
||||
return
|
||||
if(!user == affecting)
|
||||
return
|
||||
. += "All systems operational. Current energy capacity: <B>[DisplayEnergy(cell.charge)]</B>.\n"+\
|
||||
"The CLOAK-tech device is <B>[stealth?"active":"inactive"]</B>.\n"+\
|
||||
"[a_boost?"An adrenaline boost is available to use.":"There is no adrenaline boost available. Try refilling the suit with 20 units of radium."]"
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/Initialize()
|
||||
. = ..()
|
||||
@@ -77,114 +83,157 @@ Contents:
|
||||
cell.name = "black power cell"
|
||||
cell.icon_state = "bscell"
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/Destroy()
|
||||
if(affecting)
|
||||
unlock_suit()
|
||||
return ..()
|
||||
/obj/item/clothing/suit/space/space_ninja/Initialize(mapload)
|
||||
START_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
//Simply deletes all the attachments and self, killing all related procs.
|
||||
/obj/item/clothing/suit/space/space_ninja/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
// Power usage
|
||||
/obj/item/clothing/suit/space/space_ninja/process(delta_time)
|
||||
var/mob/living/carbon/human/user = src.loc
|
||||
if(!user || !ishuman(user) || !(user.wear_suit == src))
|
||||
return
|
||||
|
||||
// Check for energy usage
|
||||
if(s_initialized)
|
||||
if(!affecting)
|
||||
terminate() // Kills the suit and attached objects.
|
||||
else if(cell.charge > 0)
|
||||
if(s_coold > 0)
|
||||
s_coold = max(s_coold - delta_time, 0) // Checks for ability s_cooldown first.
|
||||
cell.charge -= s_cost * delta_time // s_cost is the default energy cost each ntick, usually 5.
|
||||
if(stealth) // If stealth is active.
|
||||
cell.charge -= s_acost * delta_time
|
||||
else
|
||||
cell.charge = 0
|
||||
cancel_stealth()
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/ui_action_click(mob/user, action)
|
||||
if(IS_NINJA_SUIT_INITIALIZATION(action))
|
||||
toggle_on_off()
|
||||
return TRUE
|
||||
if(!s_initialized)
|
||||
to_chat(user, "<span class='warning'><b>ERROR</b>: suit offline. Please activate suit.</span>")
|
||||
return FALSE
|
||||
if(s_coold > 0)
|
||||
to_chat(user, "<span class='warning'><b>ERROR</b>: suit is on cooldown.</span>")
|
||||
return FALSE
|
||||
if(IS_NINJA_SUIT_STATUS(action))
|
||||
ninjastatus()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_BOOST(action))
|
||||
ninjaboost()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_EMP(action))
|
||||
ninjapulse()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_STAR_CREATION(action))
|
||||
ninjastar()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_NET_CREATION(action))
|
||||
ninjanet()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_SWORD_RECALL(action))
|
||||
ninja_sword_recall()
|
||||
return TRUE
|
||||
if(IS_NINJA_SUIT_STEALTH(action))
|
||||
toggle_stealth()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/run_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = ATTACK_TYPE_MELEE)
|
||||
. = ..()
|
||||
if(stealth)
|
||||
cancel_stealth()
|
||||
s_coold = 5
|
||||
|
||||
/**
|
||||
* Proc called to lock the important gear pieces onto space ninja's body.
|
||||
*
|
||||
* Called during the suit startup to lock all gear pieces onto space ninja.
|
||||
* Terminates if a gear piece is not being worn. Also gives the ninja the inability to use firearms.
|
||||
* If the person in the suit isn't a ninja when this is called, this proc just gibs them instead.
|
||||
* Arguments:
|
||||
* * ninja - The person wearing the suit.
|
||||
* * Returns false if the locking fails due to lack of all suit parts, and true if it succeeds.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/lock_suit(mob/living/carbon/human/ninja)
|
||||
if(!istype(ninja))
|
||||
return FALSE
|
||||
if(!IS_SPACE_NINJA(ninja))
|
||||
to_chat(ninja, "<span class='danger'><B>fÄTaL ÈÈRRoR</B>: 382200-*#00CÖDE <B>RED</B>\nUNAUHORIZED USÈ DETÈCeD\nCoMMÈNCING SUB-R0UIN3 13...\nTÈRMInATING U-U-USÈR...</span>")
|
||||
ninja.gib()
|
||||
return FALSE
|
||||
if(!istype(ninja.head, /obj/item/clothing/head/helmet/space/space_ninja))
|
||||
to_chat(ninja, "<span class='userdanger'>ERROR</span>: 100113 UNABLE TO LOCATE HEAD GEAR\nABORTING...")
|
||||
return FALSE
|
||||
if(!istype(ninja.shoes, /obj/item/clothing/shoes/space_ninja))
|
||||
to_chat(ninja, "<span class='userdanger'>ERROR</span>: 122011 UNABLE TO LOCATE FOOT GEAR\nABORTING...")
|
||||
return FALSE
|
||||
if(!istype(ninja.gloves, /obj/item/clothing/gloves/space_ninja))
|
||||
to_chat(ninja, "<span class='userdanger'>ERROR</span>: 110223 UNABLE TO LOCATE HAND GEAR\nABORTING...")
|
||||
return FALSE
|
||||
affecting = ninja
|
||||
ADD_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT) //colons make me go all |=
|
||||
slowdown = 0
|
||||
icon_state = "s-ninjan"
|
||||
n_hood = ninja.head
|
||||
ADD_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_shoes = ninja.shoes
|
||||
ADD_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_shoes.slowdown--
|
||||
n_gloves = ninja.gloves
|
||||
ADD_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_gloves.icon_state = "s-ninjan"
|
||||
n_gloves.item_state = "s-ninjan"
|
||||
n_mask = ninja.wear_mask
|
||||
n_mask.icon_state = "s-ninjan"
|
||||
n_mask.item_state = "s-ninjan"
|
||||
|
||||
ADD_TRAIT(ninja, TRAIT_NOGUNS, NINJA_SUIT_TRAIT)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Proc called to unlock all the gear off space ninja's body.
|
||||
*
|
||||
* Proc which is essentially the opposite of lock_suit. Lets you take off all the suit parts.
|
||||
* Also gets rid of the objection to using firearms from the wearer.
|
||||
* Arguments:
|
||||
* * ninja - The person wearing the suit.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/unlock_suit(mob/living/carbon/human/ninja)
|
||||
affecting = null
|
||||
REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
slowdown = 1
|
||||
icon_state = "s-ninja"
|
||||
if(n_hood)//Should be attached, might not be attached.
|
||||
REMOVE_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_hood.icon_state = "s-ninja"
|
||||
if(n_shoes)
|
||||
REMOVE_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_shoes.slowdown++
|
||||
if(n_gloves)
|
||||
n_gloves.icon_state = "s-ninja"
|
||||
n_gloves.item_state = "s-ninja"
|
||||
REMOVE_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_gloves.candrain = FALSE
|
||||
n_gloves.draining = FALSE
|
||||
if(n_mask)
|
||||
n_mask.icon_state = "s-ninja"
|
||||
n_mask.item_state = "s-ninja"
|
||||
|
||||
REMOVE_TRAIT(ninja, TRAIT_NOGUNS, NINJA_SUIT_TRAIT)
|
||||
|
||||
/**
|
||||
* Proc used to delete all the attachments and itself.
|
||||
*
|
||||
* Can be called to entire rid of the suit pieces and the suit itself.
|
||||
*/
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/terminate()
|
||||
qdel(n_hood)
|
||||
qdel(n_gloves)
|
||||
qdel(n_shoes)
|
||||
qdel(src)
|
||||
|
||||
//Randomizes suit parameters.
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/randomize_param()
|
||||
s_cost = rand(1,20)
|
||||
s_acost = rand(20,100)
|
||||
s_delay = rand(10,100)
|
||||
s_bombs = rand(5,20)
|
||||
a_boost = rand(1,7)
|
||||
|
||||
//This proc prevents the suit from being taken off.
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/lock_suit(mob/living/carbon/human/H)
|
||||
if(!istype(H))
|
||||
return FALSE
|
||||
if(!is_ninja(H))
|
||||
to_chat(H, "<span class='danger'><B>fÄTaL ÈÈRRoR</B>: 382200-*#00CÖDE <B>RED</B>\nUNAUHORIZED USÈ DETÈCeD\nCoMMÈNCING SUB-R0UIN3 13...\nTÈRMInATING U-U-USÈR...</span>")
|
||||
H.gib()
|
||||
return FALSE
|
||||
if(!istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja))
|
||||
to_chat(H, "<span class='userdanger'>ERROR</span>: 100113 UNABLE TO LOCATE HEAD GEAR\nABORTING...")
|
||||
return FALSE
|
||||
if(!istype(H.shoes, /obj/item/clothing/shoes/space_ninja))
|
||||
to_chat(H, "<span class='userdanger'>ERROR</span>: 122011 UNABLE TO LOCATE FOOT GEAR\nABORTING...")
|
||||
return FALSE
|
||||
if(!istype(H.gloves, /obj/item/clothing/gloves/space_ninja))
|
||||
to_chat(H, "<span class='userdanger'>ERROR</span>: 110223 UNABLE TO LOCATE HAND GEAR\nABORTING...")
|
||||
return FALSE
|
||||
affecting = H
|
||||
ADD_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT) //colons make me go all |=
|
||||
n_hood = H.head
|
||||
ADD_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_shoes = H.shoes
|
||||
ADD_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_shoes.slowdown = -0.25
|
||||
n_gloves = H.gloves
|
||||
ADD_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
ADD_TRAIT(affecting, TRAIT_TASED_RESISTANCE, NINJA_SUIT_TRAIT)
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/lockIcons(mob/living/carbon/human/H)
|
||||
icon_state = H.dna.features["body_model"] == FEMALE ? "s-ninjanf" : "s-ninjan"
|
||||
H.gloves.icon_state = "s-ninjan"
|
||||
H.gloves.item_state = "s-ninjan"
|
||||
|
||||
|
||||
//This proc allows the suit to be taken off.
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/unlock_suit()
|
||||
affecting = null
|
||||
REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
icon_state = "s-ninja"
|
||||
if(n_hood)//Should be attached, might not be attached.
|
||||
REMOVE_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
if(n_shoes)
|
||||
REMOVE_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_shoes.slowdown = 0.25
|
||||
if(n_gloves)
|
||||
n_gloves.icon_state = "s-ninja"
|
||||
n_gloves.item_state = "s-ninja"
|
||||
REMOVE_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT)
|
||||
n_gloves.candrain=0
|
||||
n_gloves.draining=0
|
||||
REMOVE_TRAIT(affecting, TRAIT_TASED_RESISTANCE, NINJA_SUIT_TRAIT)
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/examine(mob/user)
|
||||
. = ..()
|
||||
if(s_initialized && user == affecting)
|
||||
. += "All systems operational. Current energy capacity: <B>[DisplayEnergy(cell.charge)]</B>.\n\
|
||||
The CLOAK-tech device is <B>[stealth?"active":"inactive"]</B>.\n\
|
||||
There are <B>[s_bombs]</B> smoke bomb\s remaining.\n\
|
||||
There are <B>[a_boost]</B> adrenaline booster\s remaining."
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/ui_action_click(mob/user, action)
|
||||
if(istype(action, /datum/action/item_action/initialize_ninja_suit))
|
||||
toggle_on_off()
|
||||
return TRUE
|
||||
if(!s_initialized)
|
||||
to_chat(user, "<span class='warning'><b>ERROR</b>: suit offline. Please activate suit.</span>")
|
||||
return FALSE
|
||||
if(istype(action, /datum/action/item_action/ninjasmoke))
|
||||
ninjasmoke()
|
||||
return TRUE
|
||||
if(istype(action, /datum/action/item_action/ninjaboost))
|
||||
ninjaboost()
|
||||
return TRUE
|
||||
if(istype(action, /datum/action/item_action/ninjapulse))
|
||||
ninjapulse()
|
||||
return TRUE
|
||||
if(istype(action, /datum/action/item_action/ninjastar))
|
||||
ninjastar()
|
||||
return TRUE
|
||||
if(istype(action, /datum/action/item_action/ninja_sword_recall))
|
||||
ninja_sword_recall()
|
||||
return TRUE
|
||||
if(istype(action, /datum/action/item_action/ninja_stealth))
|
||||
stealth()
|
||||
return TRUE
|
||||
if(istype(action, /datum/action/item_action/toggle_glove))
|
||||
n_gloves.toggledrain()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -1,52 +1,44 @@
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/attackby(obj/item/I, mob/U, params)
|
||||
if(U!=affecting)//Safety, in case you try doing this without wearing the suit/being the person with the suit.
|
||||
/obj/item/clothing/suit/space/space_ninja/attackby(obj/item/I, mob/ninja, params)
|
||||
if(ninja!=affecting)//Safety, in case you try doing this without wearing the suit/being the person with the suit.
|
||||
return ..()
|
||||
|
||||
if(istype(I, /obj/item/reagent_containers/glass))//If it's a glass beaker.
|
||||
if(I.reagents.has_reagent(/datum/reagent/radium, a_transfer) && a_boost < a_maxamount)
|
||||
I.reagents.remove_reagent(/datum/reagent/radium, a_transfer)
|
||||
a_boost++;
|
||||
to_chat(U, "<span class='notice'>There are now [a_boost] adrenaline boosts remaining.</span>")
|
||||
return
|
||||
if(I.reagents.has_reagent(/datum/reagent/smoke_powder, a_transfer) && s_bombs < s_maxamount)
|
||||
I.reagents.remove_reagent(/datum/reagent/smoke_powder, a_transfer)
|
||||
s_bombs++;
|
||||
to_chat(U, "<span class='notice'>There are now [s_bombs] smoke bombs remaining.</span>")
|
||||
return
|
||||
if(istype(I, /obj/item/reagent_containers/glass) && I.reagents.has_reagent(/datum/reagent/radium, a_transfer) && a_boost != TRUE)//If it's a glass beaker, and what we're transferring is radium.
|
||||
I.reagents.remove_reagent(/datum/reagent/radium, a_transfer)
|
||||
a_boost = TRUE;
|
||||
to_chat(ninja, "<span class='notice'>The suit's adrenaline boost is now reloaded.</span>")
|
||||
return
|
||||
|
||||
|
||||
else if(istype(I, /obj/item/stock_parts/cell))
|
||||
var/obj/item/stock_parts/cell/CELL = I
|
||||
if(CELL.maxcharge > cell.maxcharge && n_gloves && n_gloves.candrain)
|
||||
to_chat(U, "<span class='notice'>Higher maximum capacity detected.\nUpgrading...</span>")
|
||||
if (n_gloves && n_gloves.candrain && do_after(U,s_delay, target = src))
|
||||
U.transferItemToLoc(CELL, src)
|
||||
to_chat(ninja, "<span class='notice'>Higher maximum capacity detected.\nUpgrading...</span>")
|
||||
if (n_gloves?.candrain && do_after(ninja,s_delay, target = src))
|
||||
ninja.transferItemToLoc(CELL, src)
|
||||
CELL.charge = min(CELL.charge+cell.charge, CELL.maxcharge)
|
||||
var/obj/item/stock_parts/cell/old_cell = cell
|
||||
old_cell.charge = 0
|
||||
U.put_in_hands(old_cell)
|
||||
old_cell.add_fingerprint(U)
|
||||
ninja.put_in_hands(old_cell)
|
||||
old_cell.add_fingerprint(ninja)
|
||||
old_cell.corrupt()
|
||||
old_cell.update_icon()
|
||||
cell = CELL
|
||||
to_chat(U, "<span class='notice'>Upgrade complete. Maximum capacity: <b>[round(cell.maxcharge/100)]</b>%</span>")
|
||||
to_chat(ninja, "<span class='notice'>Upgrade complete. Maximum capacity: <b>[round(cell.maxcharge/100)]</b>%</span>")
|
||||
else
|
||||
to_chat(U, "<span class='danger'>Procedure interrupted. Protocol terminated.</span>")
|
||||
to_chat(ninja, "<span class='danger'>Procedure interrupted. Protocol terminated.</span>")
|
||||
return
|
||||
|
||||
else if(istype(I, /obj/item/disk/tech_disk))//If it's a data disk, we want to copy the research on to the suit.
|
||||
var/obj/item/disk/tech_disk/TD = I
|
||||
var/has_research = 0
|
||||
if(has_research)//If it has something on it.
|
||||
to_chat(U, "Research information detected, processing...")
|
||||
if(do_after(U,s_delay, target = src))
|
||||
to_chat(ninja, "Research information detected, processing...")
|
||||
if(do_after(ninja,s_delay, target = src))
|
||||
TD.stored_research.copy_research_to(stored_research)
|
||||
to_chat(U, "<span class='notice'>Data analyzed and updated. Disk erased.</span>")
|
||||
to_chat(ninja, "<span class='notice'>Data analyzed and updated. Disk erased.</span>")
|
||||
else
|
||||
to_chat(U, "<span class='userdanger'>ERROR</span>: Procedure interrupted. Process terminated.")
|
||||
to_chat(ninja, "<span class='userdanger'>ERROR</span>: Procedure interrupted. Process terminated.")
|
||||
else
|
||||
to_chat(U, "<span class='notice'>No research information detected.</span>")
|
||||
to_chat(ninja, "<span class='notice'>No research information detected.</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/toggle_on_off()
|
||||
if(s_busy)
|
||||
to_chat(loc, "<span class='userdanger'>ERROR</span>: You cannot use this function at this time.")
|
||||
return FALSE
|
||||
if(s_initialized)
|
||||
deinitialize()
|
||||
else
|
||||
ninitialize()
|
||||
. = TRUE
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize(delay = s_delay, mob/living/carbon/human/U = loc)
|
||||
if(!U.mind)
|
||||
return //Not sure how this could happen.
|
||||
s_busy = TRUE
|
||||
to_chat(U, "<span class='notice'>Now initializing...</span>")
|
||||
addtimer(CALLBACK(src, .proc/ninitialize_two, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_two(delay, mob/living/carbon/human/U)
|
||||
if(!lock_suit(U))//To lock the suit onto wearer.
|
||||
s_busy = FALSE
|
||||
return
|
||||
to_chat(U, "<span class='notice'>Securing external locking mechanism...\nNeural-net established.</span>")
|
||||
addtimer(CALLBACK(src, .proc/ninitialize_three, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_three(delay, mob/living/carbon/human/U)
|
||||
to_chat(U, "<span class='notice'>Extending neural-net interface...\nNow monitoring brain wave pattern...</span>")
|
||||
addtimer(CALLBACK(src, .proc/ninitialize_four, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_four(delay, mob/living/carbon/human/U)
|
||||
if(U.stat == DEAD|| U.health <= 0)
|
||||
to_chat(U, "<span class='danger'><B>FÄAL �Rr�R</B>: 344--93#�&&21 BR��N |/|/aV� PATT$RN <B>RED</B>\nA-A-aB�rT�NG...</span>")
|
||||
unlock_suit()
|
||||
s_busy = FALSE
|
||||
return
|
||||
lockIcons(U)//Check for icons.
|
||||
U.regenerate_icons()
|
||||
to_chat(U, "<span class='notice'>Linking neural-net interface...\nPattern</span>\green <B>GREEN</B><span class='notice'>, continuing operation.</span>")
|
||||
addtimer(CALLBACK(src, .proc/ninitialize_five, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_five(delay, mob/living/carbon/human/U)
|
||||
to_chat(U, "<span class='notice'>VOID-shift device status: <B>ONLINE</B>.\nCLOAK-tech device status: <B>ONLINE</B>.</span>")
|
||||
addtimer(CALLBACK(src, .proc/ninitialize_six, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_six(delay, mob/living/carbon/human/U)
|
||||
to_chat(U, "<span class='notice'>Primary system status: <B>ONLINE</B>.\nBackup system status: <B>ONLINE</B>.\nCurrent energy capacity: <B>[DisplayEnergy(cell.charge)]</B>.</span>")
|
||||
addtimer(CALLBACK(src, .proc/ninitialize_seven, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_seven(delay, mob/living/carbon/human/U)
|
||||
to_chat(U, "<span class='notice'>All systems operational. Welcome to <B>SpiderOS</B>, [U.real_name].</span>")
|
||||
s_initialized = TRUE
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
s_busy = FALSE
|
||||
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize(delay = s_delay)
|
||||
if(affecting==loc)
|
||||
var/mob/living/carbon/human/U = affecting
|
||||
if(alert("Are you certain you wish to remove the suit? This will take time and remove all abilities.",,"Yes","No")=="No")
|
||||
return
|
||||
s_busy = TRUE
|
||||
addtimer(CALLBACK(src, .proc/deinitialize_two, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_two(delay, mob/living/carbon/human/U)
|
||||
to_chat(U, "<span class='notice'>Now de-initializing...</span>")
|
||||
addtimer(CALLBACK(src, .proc/deinitialize_three, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_three(delay, mob/living/carbon/human/U)
|
||||
to_chat(U, "<span class='notice'>Logging off, [U.real_name]. Shutting down <B>SpiderOS</B>.</span>")
|
||||
addtimer(CALLBACK(src, .proc/deinitialize_four, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_four(delay, mob/living/carbon/human/U)
|
||||
to_chat(U, "<span class='notice'>Primary system status: <B>OFFLINE</B>.\nBackup system status: <B>OFFLINE</B>.</span>")
|
||||
addtimer(CALLBACK(src, .proc/deinitialize_five, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_five(delay, mob/living/carbon/human/U)
|
||||
to_chat(U, "<span class='notice'>VOID-shift device status: <B>OFFLINE</B>.\nCLOAK-tech device status: <B>OFFLINE</B>.</span>")
|
||||
cancel_stealth()//Shutdowns stealth.
|
||||
addtimer(CALLBACK(src, .proc/deinitialize_six, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_six(delay, mob/living/carbon/human/U)
|
||||
to_chat(U, "<span class='notice'>Disconnecting neural-net interface...</span>\green<B>Success</B><span class='notice'>.</span>")
|
||||
addtimer(CALLBACK(src, .proc/deinitialize_seven, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_seven(delay, mob/living/carbon/human/U)
|
||||
to_chat(U, "<span class='notice'>Disengaging neural-net interface...</span>\green<B>Success</B><span class='notice'>.</span>")
|
||||
addtimer(CALLBACK(src, .proc/deinitialize_eight, delay, U), delay)
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/deinitialize_eight(delay, mob/living/carbon/human/U)
|
||||
to_chat(U, "<span class='notice'>Unsecuring external locking mechanism...\nNeural-net abolished.\nOperation status: <B>FINISHED</B>.</span>")
|
||||
unlock_suit()
|
||||
U.regenerate_icons()
|
||||
s_initialized = FALSE
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
s_busy = FALSE
|
||||
@@ -1,17 +0,0 @@
|
||||
/obj/item/clothing/suit/space/space_ninja/process()
|
||||
if(!affecting || !s_initialized)
|
||||
return PROCESS_KILL
|
||||
|
||||
if(cell.charge > 0)
|
||||
if(s_coold)
|
||||
s_coold--//Checks for ability s_cooldown first.
|
||||
|
||||
cell.charge -= s_cost//s_cost is the default energy cost each tick, usually 5.
|
||||
if(stealth && stealth_cooldown <= world.time)//If stealth is active.
|
||||
cell.charge -= s_acost
|
||||
affecting.alpha = max(affecting.alpha - 10, 15)
|
||||
|
||||
else
|
||||
cell.charge = 0
|
||||
if(stealth)
|
||||
cancel_stealth()
|
||||
@@ -59,13 +59,13 @@
|
||||
one though."
|
||||
icon_state = "default_human_l_arm"
|
||||
attack_verb = list("slapped", "punched")
|
||||
max_damage = 150
|
||||
max_damage = 50
|
||||
disable_threshold = 75
|
||||
max_stamina_damage = 50
|
||||
body_zone = BODY_ZONE_L_ARM
|
||||
body_part = ARM_LEFT
|
||||
aux_icons = list(BODY_ZONE_PRECISE_L_HAND = HANDS_PART_LAYER, "l_hand_behind" = BODY_BEHIND_LAYER)
|
||||
body_damage_coeff = 0.25
|
||||
body_damage_coeff = 0.75
|
||||
held_index = 1
|
||||
px_x = -6
|
||||
px_y = 0
|
||||
@@ -121,12 +121,12 @@
|
||||
among humans missing their right arm."
|
||||
icon_state = "default_human_r_arm"
|
||||
attack_verb = list("slapped", "punched")
|
||||
max_damage = 150
|
||||
max_damage = 50
|
||||
disable_threshold = 75
|
||||
body_zone = BODY_ZONE_R_ARM
|
||||
body_part = ARM_RIGHT
|
||||
aux_icons = list(BODY_ZONE_PRECISE_R_HAND = HANDS_PART_LAYER, "r_hand_behind" = BODY_BEHIND_LAYER)
|
||||
body_damage_coeff = 0.25
|
||||
body_damage_coeff = 0.75
|
||||
held_index = 2
|
||||
px_x = 6
|
||||
px_y = 0
|
||||
@@ -184,11 +184,11 @@
|
||||
luck. In this instance, it probably would not have helped."
|
||||
icon_state = "default_human_l_leg"
|
||||
attack_verb = list("kicked", "stomped")
|
||||
max_damage = 150
|
||||
max_damage = 50
|
||||
disable_threshold = 75
|
||||
body_zone = BODY_ZONE_L_LEG
|
||||
body_part = LEG_LEFT
|
||||
body_damage_coeff = 0.25
|
||||
body_damage_coeff = 0.75
|
||||
px_x = -2
|
||||
px_y = 12
|
||||
stam_heal_tick = STAM_RECOVERY_LIMB
|
||||
@@ -243,11 +243,10 @@
|
||||
// alternative spellings of 'pokey' are availible
|
||||
icon_state = "default_human_r_leg"
|
||||
attack_verb = list("kicked", "stomped")
|
||||
max_damage = 150
|
||||
disable_threshold = 75
|
||||
max_damage = 50
|
||||
body_zone = BODY_ZONE_R_LEG
|
||||
body_part = LEG_RIGHT
|
||||
body_damage_coeff = 0.25
|
||||
body_damage_coeff = 0.75
|
||||
px_x = 2
|
||||
px_y = 12
|
||||
max_stamina_damage = 50
|
||||
|
||||
@@ -50,6 +50,70 @@
|
||||
-->
|
||||
<div class="commit sansserif">
|
||||
|
||||
<h2 class="date">20 September 2021</h2>
|
||||
<h3 class="author">BlueWildrose updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="balance">Slime regenerative extracts now require five seconds of wait before they are used. They add 25 disgust when used.</li>
|
||||
</ul>
|
||||
<h3 class="author">DeltaFire15 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Catsurgeons should now spawn at more reasonable locations if possible.</li>
|
||||
<li class="balance">carded AIs can now be converted by conversion sigils (clockcult)</li>
|
||||
<li class="bugfix">There is now a way to acquire nanite storage protocols (bepis, like the other protocols), as opposed to them existing with no way to acquire them.</li>
|
||||
<li class="bugfix">Plastic golems are back to ventcrawler_nude instead of ventcrawler_always</li>
|
||||
</ul>
|
||||
<h3 class="author">Putnam3145 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="config">monstermos config added, disabled</li>
|
||||
</ul>
|
||||
<h3 class="author">buffyuwu updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixed medihound sleeper ui display</li>
|
||||
<li class="rscadd">Adds 4 redesigned jackets and 2 redesigned shirts to loadout</li>
|
||||
<li class="bugfix">Holoparasites no long rename and recolor on relog</li>
|
||||
</ul>
|
||||
<h3 class="author">dapnee updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">attaches an air vent that was just there on the AI sat, changes some areas to what they'd logically be</li>
|
||||
</ul>
|
||||
<h3 class="author">keronshb updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Plague Rats will no longer spawn thousands of dirt decals</li>
|
||||
<li class="bugfix">Plague Rats will no longer spawn thousands of corpses</li>
|
||||
<li class="bugfix">Plague Rats can't spawn or transform off station z anymore</li>
|
||||
<li class="bugfix">Plague Rats shouldn't explosively grow instantly</li>
|
||||
<li class="bugfix">Plague Rats won't spawn infinite miasma anymore.</li>
|
||||
<li class="balance">Plague Rats health is now 100.</li>
|
||||
<li class="balance">Plague Rats can now ventcrawl through everything to prevent farming.</li>
|
||||
<li class="bugfix">Slaughter Demons Slam will now wound again on hit.</li>
|
||||
<li class="balance">Damage for demons back up to 30</li>
|
||||
<li class="balance">Wound Bonus for demons now at 0. image_add: Adds a sprite for the action bar</li>
|
||||
<li class="refactor">Changed the CTRL+SHIFT Click to an action button. People can see the cooldown now too.</li>
|
||||
<li class="rscadd">PAIs can be emagged to reset master</li>
|
||||
</ul>
|
||||
<h3 class="author">qweq12yt updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Fixed space heaters not being able to be interacted/turned on in non powered areas</li>
|
||||
</ul>
|
||||
<h3 class="author">timothyteakettle updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">removes passkey from access circuits as its not used anymore</li>
|
||||
<li class="rscadd">a new mild trauma, **[REDACTED]**</li>
|
||||
</ul>
|
||||
<h3 class="author">zeroisthebiggay updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="balance">glass has do_after</li>
|
||||
<li class="bugfix">box perma has power</li>
|
||||
<li class="bugfix">missing madness mask sprites</li>
|
||||
<li class="balance">The Spider Clan has recently taken up the Space Ninja project again along with the Syndicate. Space Ninjas have been drastically changed as a result, becoming much weaker and more stealth oriented. As a result of cutting costs per ninja, more ninjas were able to be hired. Expect to see them around more often.</li>
|
||||
<li class="bugfix">prisoners cannot latejoin anymore</li>
|
||||
<li class="bugfix">bone satchel onmob sprites</li>
|
||||
<li class="rscadd">new tips</li>
|
||||
<li class="rscdel">old tips</li>
|
||||
<li class="imageadd">all medipens get inhands</li>
|
||||
<li class="rscadd">some more brainhurt lines</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">18 September 2021</h2>
|
||||
<h3 class="author">kiwedespars updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
@@ -472,44 +536,6 @@
|
||||
<ul class="changes bgimages16">
|
||||
<li class="balance">Batons are slightly more powerful.</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">19 July 2021</h2>
|
||||
<h3 class="author">Arturlang updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">The crafting button should no longer silently make more copies of itself on reconects</li>
|
||||
<li class="code_imp">There are no longer two copies of the crafting component.</li>
|
||||
<li class="code_imp">There is no longer a rogue d in tracer.dm tweak: Everything in Misc was moved to Miscelanious in the crafting menu, and Misc was nuked from orbit. Nobody will miss you.</li>
|
||||
</ul>
|
||||
<h3 class="author">MrJWhit updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Fixes a memory leak, there's a good chance that it's the same one that killed kilo.</li>
|
||||
</ul>
|
||||
<h3 class="author">SandPoot updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Put back mob vore with a pref.</li>
|
||||
<li class="code_imp">Taken some stuff from tg for tgui_alert.</li>
|
||||
<li class="refactor">Refactored a lot of code on vore panel.</li>
|
||||
</ul>
|
||||
<h3 class="author">WanderingFox95 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">custom plasteel kegs</li>
|
||||
</ul>
|
||||
<h3 class="author">YakumoChen updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">You can now wear the suffering of others on your head with just a sheet of human skin!</li>
|
||||
<li class="imageadd">Human skin hats</li>
|
||||
</ul>
|
||||
<h3 class="author">keronshb updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Stripping/equipping things to a conscious braindead person (AKA a human owned by a disconnected player) will now give them a message with your visible name and roughly how long ago you touched their stuff when they login again. Touching someone's pockets or adjusting their gear other than equipping/unequipping is not logged. After 5 minutes, you'll have forgotten both their name and exactly how long ago past those 5 minutes it happened. (Credit to Ryll-Ryll)</li>
|
||||
<li class="rscadd">LAZYNULL</li>
|
||||
<li class="rscadd">Breaking mirrors now gives you a bad omen</li>
|
||||
</ul>
|
||||
<h3 class="author">timothyteakettle updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">anthros can now select the cow tail</li>
|
||||
<li class="rscadd">new quirk that allows you to eat trash</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<b>GoonStation 13 Development Team</b>
|
||||
|
||||
@@ -30003,3 +30003,58 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
|
||||
2021-09-18:
|
||||
kiwedespars:
|
||||
- balance: blacklisted morphine and haloperidol from dart guns
|
||||
2021-09-20:
|
||||
BlueWildrose:
|
||||
- balance: Slime regenerative extracts now require five seconds of wait before they
|
||||
are used. They add 25 disgust when used.
|
||||
DeltaFire15:
|
||||
- bugfix: Catsurgeons should now spawn at more reasonable locations if possible.
|
||||
- balance: carded AIs can now be converted by conversion sigils (clockcult)
|
||||
- bugfix: There is now a way to acquire nanite storage protocols (bepis, like the
|
||||
other protocols), as opposed to them existing with no way to acquire them.
|
||||
- bugfix: Plastic golems are back to ventcrawler_nude instead of ventcrawler_always
|
||||
Putnam3145:
|
||||
- config: monstermos config added, disabled
|
||||
buffyuwu:
|
||||
- bugfix: fixed medihound sleeper ui display
|
||||
- rscadd: Adds 4 redesigned jackets and 2 redesigned shirts to loadout
|
||||
- bugfix: Holoparasites no long rename and recolor on relog
|
||||
dapnee:
|
||||
- bugfix: attaches an air vent that was just there on the AI sat, changes some areas
|
||||
to what they'd logically be
|
||||
keronshb:
|
||||
- bugfix: Plague Rats will no longer spawn thousands of dirt decals
|
||||
- bugfix: Plague Rats will no longer spawn thousands of corpses
|
||||
- bugfix: Plague Rats can't spawn or transform off station z anymore
|
||||
- bugfix: Plague Rats shouldn't explosively grow instantly
|
||||
- bugfix: Plague Rats won't spawn infinite miasma anymore.
|
||||
- balance: Plague Rats health is now 100.
|
||||
- balance: Plague Rats can now ventcrawl through everything to prevent farming.
|
||||
- bugfix: Slaughter Demons Slam will now wound again on hit.
|
||||
- balance: Damage for demons back up to 30
|
||||
- balance: 'Wound Bonus for demons now at 0. image_add: Adds a sprite for the action
|
||||
bar'
|
||||
- refactor: Changed the CTRL+SHIFT Click to an action button. People can see the
|
||||
cooldown now too.
|
||||
- rscadd: PAIs can be emagged to reset master
|
||||
qweq12yt:
|
||||
- bugfix: Fixed space heaters not being able to be interacted/turned on in non powered
|
||||
areas
|
||||
timothyteakettle:
|
||||
- bugfix: removes passkey from access circuits as its not used anymore
|
||||
- rscadd: a new mild trauma, **[REDACTED]**
|
||||
zeroisthebiggay:
|
||||
- balance: glass has do_after
|
||||
- bugfix: box perma has power
|
||||
- bugfix: missing madness mask sprites
|
||||
- balance: The Spider Clan has recently taken up the Space Ninja project again along
|
||||
with the Syndicate. Space Ninjas have been drastically changed as a result,
|
||||
becoming much weaker and more stealth oriented. As a result of cutting costs
|
||||
per ninja, more ninjas were able to be hired. Expect to see them around more
|
||||
often.
|
||||
- bugfix: prisoners cannot latejoin anymore
|
||||
- bugfix: bone satchel onmob sprites
|
||||
- rscadd: new tips
|
||||
- rscdel: old tips
|
||||
- imageadd: all medipens get inhands
|
||||
- rscadd: some more brainhurt lines
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "keronshb"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "PAIs can be emagged to reset master"
|
||||
@@ -1,10 +0,0 @@
|
||||
author: "keronshb"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Plague Rats will no longer spawn thousands of dirt decals"
|
||||
- bugfix: "Plague Rats will no longer spawn thousands of corpses"
|
||||
- bugfix: "Plague Rats can't spawn or transform off station z anymore"
|
||||
- bugfix: "Plague Rats shouldn't explosively grow instantly"
|
||||
- bugfix: "Plague Rats won't spawn infinite miasma anymore."
|
||||
- balance: "Plague Rats health is now 100."
|
||||
- balance: "Plague Rats can now ventcrawl through everything to prevent farming."
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "zeroisthebiggay"
|
||||
delete-after: True
|
||||
changes:
|
||||
- balance: "glass has do_after"
|
||||
@@ -1,8 +0,0 @@
|
||||
author: "keronshb"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Slaughter Demons Slam will now wound again on hit."
|
||||
- balance: "Damage for demons back up to 30"
|
||||
- balance: "Wound Bonus for demons now at 0.
|
||||
image_add: Adds a sprite for the action bar"
|
||||
- refactor: "Changed the CTRL+SHIFT Click to an action button. People can see the cooldown now too."
|
||||
@@ -1,5 +0,0 @@
|
||||
author: "zeroisthebiggay"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "new tips"
|
||||
- rscdel: "old tips"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "zeroisthebiggay"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "some more brainhurt lines"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "DeltaFire15"
|
||||
delete-after: True
|
||||
changes:
|
||||
- balance: "carded AIs can now be converted by conversion sigils (clockcult)"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "DeltaFire15"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Catsurgeons should now spawn at more reasonable locations if possible."
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "zeroisthebiggay"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "box perma has power"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "zeroisthebiggay"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "bone satchel onmob sprites"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "Putnam3145"
|
||||
delete-after: True
|
||||
changes:
|
||||
- config: "monstermos config added, disabled"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "qweq12yt"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Fixed space heaters not being able to be interacted/turned on in non powered areas"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "zeroisthebiggay"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "missing madness mask sprites"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "DeltaFire15"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "There is now a way to acquire nanite storage protocols (bepis, like the other protocols), as opposed to them existing with no way to acquire them."
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "timothyteakettle"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "removes passkey from access circuits as its not used anymore"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "zeroisthebiggay"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "prisoners cannot latejoin anymore"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "buffyuwu"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "Adds 4 redesigned jackets and 2 redesigned shirts to loadout"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "BlueWildrose"
|
||||
delete-after: True
|
||||
changes:
|
||||
- balance: "Slime regenerative extracts now require five seconds of wait before they are used. They add 25 disgust when used."
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "dapnee"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "attaches an air vent that was just there on the AI sat, changes some areas to what they'd logically be"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "timothyteakettle"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscadd: "a new mild trauma, **[REDACTED]**"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "DeltaFire15"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Plastic golems are back to ventcrawler_nude instead of ventcrawler_always"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "buffyuwu"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "Holoparasites no long rename and recolor on relog"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "buffyuwu"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "fixed medihound sleeper ui display"
|
||||
@@ -1,4 +0,0 @@
|
||||
author: "zeroisthebiggay"
|
||||
delete-after: True
|
||||
changes:
|
||||
- imageadd: "all medipens get inhands"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "silicons"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "dice bags can only hold dice"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "silicons"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscdel: "limb damage changes reverted"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "silicons"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "crawling can't be adrenals'd"
|
||||
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 227 KiB |
|
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 480 KiB After Width: | Height: | Size: 473 KiB |
|
Before Width: | Height: | Size: 291 KiB After Width: | Height: | Size: 289 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 226 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 22 KiB |