diff --git a/code/WorkInProgress/Chemistry-Holder.dm b/code/WorkInProgress/Chemistry-Holder.dm
index 5c57a0b98f7..500a7a2a793 100644
--- a/code/WorkInProgress/Chemistry-Holder.dm
+++ b/code/WorkInProgress/Chemistry-Holder.dm
@@ -101,7 +101,7 @@ datum
src.update_total()
R.update_total()
R.handle_reactions()
- //src.handle_reactions() Don't need to handle reactions on the source since you're (presumably isolating) and transferring a specific reagent.
+ //src.handle_reactions() Don't need to handle reactions on the source since you're (presumably isolating and) transferring a specific reagent.
return amount
/*
@@ -315,9 +315,9 @@ datum
for(var/A in reagent_list)
var/datum/reagent/R = A
if (R.id == reagent)
- if(!amount) return 1
+ if(!amount) return R
else
- if(R.volume >= amount) return 1
+ if(R.volume >= amount) return R
else return 0
return 0
diff --git a/code/WorkInProgress/Chemistry-Reagents.dm b/code/WorkInProgress/Chemistry-Reagents.dm
index 8c1091435aa..c2109822170 100644
--- a/code/WorkInProgress/Chemistry-Reagents.dm
+++ b/code/WorkInProgress/Chemistry-Reagents.dm
@@ -701,19 +701,19 @@ datum
*/
gold
- name = "gold"
+ name = "Gold"
id = "gold"
description = "Gold is a dense, soft, shiny metal and the most malleable and ductile metal known."
reagent_state = SOLID
silver
- name = "silver"
+ name = "Silver"
id = "silver"
description = "A soft, white, lustrous transition metal, it has the highest electrical conductivity of any element and the highest thermal conductivity of any metal."
reagent_state = SOLID
uranium
- name ="uranium"
+ name ="Uranium"
id = "uranium"
description = "A silvery-white metallic chemical element in the actinide series, weakly radioactive."
reagent_state = SOLID
@@ -730,7 +730,7 @@ datum
new /obj/decal/cleanable/greenglow(T)
aluminum
- name = "aluminum"
+ name = "Aluminum"
id = "aluminum"
description = "A silvery white and ductile member of the boron group of chemical elements."
reagent_state = SOLID
@@ -1065,9 +1065,9 @@ datum
id = "arithrazine"
description = "Arithrazine is an unstable medication used for the most extreme cases of radiation poisoning."
reagent_state = LIQUID
- on_mob_life(var/mob/living/M)
+ on_mob_life(var/mob/living/M as mob)
if(!M) M = holder.my_atom
- M:radiation = 0
+ M:radiation = max(M:radiation-7,0)
if(M:toxloss) M:toxloss--
if(prob(15))
M.take_organ_damage(1, 0)
@@ -1099,20 +1099,6 @@ datum
..()
return
- arithrazine
- name = "Arithrazine"
- id = "arithrazine"
- description = "Arithrazine is an unstable medication used for the most extreme cases of radiation poisoning."
- reagent_state = LIQUID
- on_mob_life(var/mob/living/M as mob)
- if(!M) M = holder.my_atom
- M:radiation = max(M:radiation-3,0)
- if(M:toxloss) M:toxloss--
- if(prob(15))
- M.take_organ_damage(1, 0)
- ..()
- return
-
bicaridine
name = "Bicaridine"
id = "bicaridine"
diff --git a/code/WorkInProgress/Chemistry-Tools.dm b/code/WorkInProgress/Chemistry-Tools.dm
index 7147a8e541c..230e67cc456 100644
--- a/code/WorkInProgress/Chemistry-Tools.dm
+++ b/code/WorkInProgress/Chemistry-Tools.dm
@@ -584,6 +584,10 @@
var/trans = src.reagents.trans_to(target, amount_per_transfer_from_this)
user << "\blue You transfer [trans] units of the solution to [target]."
+ //Safety for dumping stuff into a ninja suit. It handles everything through attackby() and this is unnecessary.
+ else if(istype(target, /obj/item/clothing/suit/space/space_ninja))
+ return
+
else if(reagents.total_volume)
user << "\blue You splash the solution onto [target]."
src.reagents.reaction(target, TOUCH)
diff --git a/code/defines/obj/clothing/suit.dm b/code/defines/obj/clothing/suit.dm
index 139475f8672..e6b027aa282 100644
--- a/code/defines/obj/clothing/suit.dm
+++ b/code/defines/obj/clothing/suit.dm
@@ -403,6 +403,7 @@
mob/living/carbon/affecting = null//The wearer.
obj/item/weapon/cell/cell//Starts out with a high-capacity cell using New().
datum/effects/system/spark_spread/spark_system//To create sparks.
+ reagent_list[] = list("tricordrazine","dexalinp","spaceacillin","anti_toxin","nutriment","radium","hyronalin")//The reagents ids which are added to the suit at New().
//Other articles of ninja gear worn together, used to easily reference them after initializing.
obj/item/clothing/head/helmet/space/space_ninja/n_hood
@@ -412,21 +413,31 @@
//Main function variables.
s_initialized = 0//Suit starts off.
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().
+ s_cost = 5.0//Base energy cost each ntick.
+ s_acost = 25.0//Additional cost for additional powers active.
+ k_cost = 200.0//Kamikaze energy cost each ntick.
+ k_damage = 1.0//Brute damage potentially done by Kamikaze each ntick.
+ s_delay = 40.0//How fast the suit does certain things, lower is faster. Can be overridden in specific procs. Also determines adverse probability.
+ a_transfer = 20.0//How much reagent is transferred when injecting.
+ r_maxamount = 80.0//How much reagent in total there is.
+
+ //Support function variables.
spideros = 0//Mode of SpiderOS. This can change so I won't bother listing the modes here (0 is hub). Check ninja_equipment.dm for how it all works.
s_active = 0//Stealth off.
- k_unlock = 0//To unlock Kamikaze.
+ s_busy = 0//Is the suit busy with a process? Like AI hacking. Used for safety functions.
kamikaze = 0//Kamikaze on or off.
+ k_unlock = 0//To unlock Kamikaze.
//Ability function variables.
s_bombs = 10.0//Number of starting ninja smoke bombs.
a_boost = 3.0//Number of adrenaline boosters.
- a_transfer = 20//How much reagent is transferred when injecting.
//Onboard AI related variables.
- mob/living/silicon/AI//If there is an AI inside the suit. Paths to target.
+ mob/living/silicon/AI//If there is an AI inside the suit.
+ obj/item/device/paicard/pai//A slot for a pAI device
obj/overlay/hologram//Is the AI hologram on or off? Visible only to the wearer of the suit. This works by attaching an image to a blank overlay.
flush = 0//If an AI purge is in progress.
- s_control = 1//If in control of the suit.
+ s_control = 1//If user in control of the suit.
/obj/item/clothing/suit/space/pirate
name = "pirate coat"
diff --git a/code/defines/procs/helpers.dm b/code/defines/procs/helpers.dm
index 8c802cd2996..1658d9a98d7 100644
--- a/code/defines/procs/helpers.dm
+++ b/code/defines/procs/helpers.dm
@@ -381,11 +381,13 @@
//Returns location. Returns null if no location was found.
/proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = 0, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0)
-//Location where the teleport begins, target that will teleport, distance to go, density checking 0/1(yes/no).
-//Random error in tile placement x, error in tile placement y, and block offset.
-//Block offset tells the proc how to place the box. Behind teleport location, relative to starting location, forward, etc.
-//Negative values for offset are accepted, think of it in relation to North, -x is west, -y is south. Error defaults to positive.
-//Turf and target are seperate in case you want to teleport some distance from a turf the target is not standing on or something.
+/*
+Location where the teleport begins, target that will teleport, distance to go, density checking 0/1(yes/no).
+Random error in tile placement x, error in tile placement y, and block offset.
+Block offset tells the proc how to place the box. Behind teleport location, relative to starting location, forward, etc.
+Negative values for offset are accepted, think of it in relation to North, -x is west, -y is south. Error defaults to positive.
+Turf and target are seperate in case you want to teleport some distance from a turf the target is not standing on or something.
+*/
var/dirx = 0//Generic location finding variable.
var/diry = 0
diff --git a/code/game/gamemodes/extra/ninja_abilities.dm b/code/game/gamemodes/extra/ninja_abilities.dm
index f625421639c..bda996c6d24 100644
--- a/code/game/gamemodes/extra/ninja_abilities.dm
+++ b/code/game/gamemodes/extra/ninja_abilities.dm
@@ -1,18 +1,19 @@
/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+++++++++++++++++++++++++++++++++// \\++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++// //++++++++++++++++++++++++++++++++++
==================================SPACE NINJA ABILITIES====================================
___________________________________________________________________________________________
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
-/*X is optional, tells the proc to check for specific stuff. C is also optional.
+//=======//SAFETY CHECK//=======//
+/*
+X is optional, tells the proc to check for specific stuff. C is also optional.
All the procs here assume that the character is wearing the ninja suit if they are using the procs.
They should, as I have made every effort for that to be the case.
In the case that they are not, I imagine the game will run-time error like crazy.
+s_cooldown ticks off each second based on the suit recharge proc, in seconds. Default of 1 seconds. Some abilities have no cool down.
*/
-
-//s_cooldown ticks off each second based on the suit recharge proc, in seconds. Default of 1 seconds. Some abilities have no cool down.
/obj/item/clothing/suit/space/space_ninja/proc/ninjacost(C = 0,X = 0)
var/mob/living/carbon/human/U = affecting
if( (U.stat||U.incorporeal_move)&&X!=3 )//Will not return if user is using an adrenaline booster since you can use them when stat==1.
@@ -34,9 +35,19 @@ In the case that they are not, I imagine the game will run-time error like crazy
return 1
return (s_coold)//Returns the value of the variable which counts down to zero.
-//Smoke
-//Summons smoke in radius of user.
-//Not sure why this would be useful (it's not) but whatever. Ninjas need their smoke bombs.
+//=======//TELEPORT GRAB CHECK//=======//
+/obj/item/clothing/suit/space/space_ninja/proc/handle_teleport_grab(turf/T, mob/living/U)
+ if(istype(U.get_active_hand(),/obj/item/weapon/grab))//Handles grabbed persons.
+ var/obj/item/weapon/grab/G = U.get_active_hand()
+ G.affecting.loc = locate(T.x+rand(-1,1),T.y+rand(-1,1),T.z)//variation of position.
+ if(istype(U.get_inactive_hand(),/obj/item/weapon/grab))
+ var/obj/item/weapon/grab/G = U.get_inactive_hand()
+ G.affecting.loc = locate(T.x+rand(-1,1),T.y+rand(-1,1),T.z)//variation of position.
+ return
+
+//=======//SMOKE//=======//
+/*Summons smoke in radius of user.
+Not sure why this would be useful (it's not) but whatever. Ninjas need their smoke bombs.*/
/obj/item/clothing/suit/space/space_ninja/proc/ninjasmoke()
set name = "Smoke Bomb"
set desc = "Blind your enemies momentarily with a well-placed smoke bomb."
@@ -54,7 +65,7 @@ In the case that they are not, I imagine the game will run-time error like crazy
s_coold = 1
return
-//9-10 Tile Teleport
+//=======//9-8 TILE TELEPORT//=======//
//Click to to teleport 9-10 tiles in direction facing.
/obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt()
set name = "Phase Jaunt (10E)"
@@ -72,12 +83,7 @@ In the case that they are not, I imagine the game will run-time error like crazy
playsound(U.loc, "sparks", 50, 1)
anim(mobloc,src,'mob.dmi',,"phaseout")
- if(istype(U.get_active_hand(),/obj/item/weapon/grab))//Handles grabbed persons.
- var/obj/item/weapon/grab/G = U.get_active_hand()
- G.affecting.loc = locate(destination.x+rand(-1,1),destination.y+rand(-1,1),destination.z)//variation of position.
- if(istype(U.get_inactive_hand(),/obj/item/weapon/grab))
- var/obj/item/weapon/grab/G = U.get_inactive_hand()
- G.affecting.loc = locate(destination.x+rand(-1,1),destination.y+rand(-1,1),destination.z)//variation of position.
+ handle_teleport_grab(destination, U)
U.loc = destination
spawn(0)
@@ -94,7 +100,7 @@ In the case that they are not, I imagine the game will run-time error like crazy
U << "\red The VOID-shift device is malfunctioning, teleportation failed."
return
-//Right Click Teleport
+//=======//RIGHT CLICK TELEPORT//=======//
//Right click to teleport somewhere, almost exactly like admin jump to turf.
/obj/item/clothing/suit/space/space_ninja/proc/ninjashift(turf/T in oview())
set name = "Phase Shift (20E)"
@@ -111,12 +117,7 @@ In the case that they are not, I imagine the game will run-time error like crazy
playsound(U.loc, 'sparks4.ogg', 50, 1)
anim(mobloc,src,'mob.dmi',,"phaseout")
- if(istype(U.get_active_hand(),/obj/item/weapon/grab))//Handles grabbed persons.
- var/obj/item/weapon/grab/G = U.get_active_hand()
- G.affecting.loc = locate(T.x+rand(-1,1),T.y+rand(-1,1),T.z)//variation of position.
- if(istype(U.get_inactive_hand(),/obj/item/weapon/grab))
- var/obj/item/weapon/grab/G = U.get_inactive_hand()
- G.affecting.loc = locate(T.x+rand(-1,1),T.y+rand(-1,1),T.z)//variation of position.
+ handle_teleport_grab(T, U)
U.loc = T
spawn(0)
@@ -133,7 +134,7 @@ In the case that they are not, I imagine the game will run-time error like crazy
U << "\red You cannot teleport into solid walls or from solid matter"
return
-//EMP Pulse
+//=======//EM PULSE//=======//
//Disables nearby tech equipment.
/obj/item/clothing/suit/space/space_ninja/proc/ninjapulse()
set name = "EM Burst (25E)"
@@ -150,7 +151,7 @@ In the case that they are not, I imagine the game will run-time error like crazy
cell.charge-=(C*10)
return
-//Summon Energy Blade
+//=======//ENERGY BLADE//=======//
//Summons a blade of energy in active hand.
/obj/item/clothing/suit/space/space_ninja/proc/ninjablade()
set name = "Energy Blade (5E)"
@@ -182,16 +183,16 @@ In the case that they are not, I imagine the game will run-time error like crazy
s_coold = 1
return
-//Shoot Ninja Stars
-//Shoots ninja stars at random people.
-//This could be a lot better but I'm too tired atm.
+//=======//NINJA STARS//=======//
+/*Shoots ninja stars at random people.
+This could be a lot better but I'm too tired atm.*/
/obj/item/clothing/suit/space/space_ninja/proc/ninjastar()
- set name = "Energy Star (3E)"
+ set name = "Energy Star (5E)"
set desc = "Launches an energy star at a random living target."
set category = "Ninja Ability"
set popup_menu = 0
- var/C = 30
+ var/C = 50
if(!ninjacost(C))
var/mob/living/carbon/human/U = affecting
var/targets[] = list()//So yo can shoot while yo throw dawg
@@ -217,9 +218,9 @@ In the case that they are not, I imagine the game will run-time error like crazy
U << "\red There are no targets in view."
return
-//Energy Net
-//Allows the ninja to capture people, I guess.
-//Must right click on a mob to activate.
+//=======//ENERGY NET//=======//
+/*Allows the ninja to capture people, I guess.
+Must right click on a mob to activate.*/
/obj/item/clothing/suit/space/space_ninja/proc/ninjanet(mob/living/carbon/M in oview())//Only living carbon mobs.
set name = "Energy Net (20E)"
set desc = "Captures a fallen opponent in a net of energy. Will teleport them to a holding facility after 30 seconds."
@@ -255,9 +256,9 @@ In the case that they are not, I imagine the game will run-time error like crazy
U << "They will bring no honor to your Clan!"
return
-//Adrenaline Boost
-//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.
+//=======//ADRENALINE BOOST//=======//
+/*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()
set name = "Adrenaline Boost"
set desc = "Inject a secret chemical that will counteract all movement-impairing effects."
@@ -282,10 +283,14 @@ In the case that they are not, I imagine the game will run-time error like crazy
return
-//KAMIKAZE=============================
-//Or otherwise known as anime mode. Which also happens to be ridiculously powerful.
+/*
+===================================================================================
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+===================================================================================
+Or otherwise known as anime mode. Which also happens to be ridiculously powerful.
+*/
-//Allows for incorporeal movement.
+//=======//NINJA MOVEMENT//=======//
//Also makes you move like you're on crack.
/obj/item/clothing/suit/space/space_ninja/proc/ninjawalk()
set name = "Shadow Walk"
@@ -304,8 +309,8 @@ In the case that they are not, I imagine the game will run-time error like crazy
U << "\blue You will no-longer phase through solid matter."
return
-/*
-Allows to gib up to five squares in a straight line. Seriously.*/
+//=======//5 TILE TELEPORT/GIB//=======//
+//Allows to gib up to five squares in a straight line. Seriously.
/obj/item/clothing/suit/space/space_ninja/proc/ninjaslayer()
set name = "Phase Slayer"
set desc = "Utilizes the internal VOID-shift device to mutilate creatures in a straight line."
@@ -330,6 +335,7 @@ Allows to gib up to five squares in a straight line. Seriously.*/
spawn(0)
anim(T,U,'mob.dmi',,"phasein")
+ handle_teleport_grab(destination, U)
U.loc = destination
spawn(0)
@@ -342,8 +348,9 @@ Allows to gib up to five squares in a straight line. Seriously.*/
U << "\red The VOID-shift device is malfunctioning, teleportation failed."
return
-//Appear behind a randomly chosen mob while a few decoy teleports appear.
-//This is so anime it hurts. But that's the point.
+//=======//TELEPORT BEHIND MOB//=======//
+/*Appear behind a randomly chosen mob while a few decoy teleports appear.
+This is so anime it hurts. But that's the point.*/
/obj/item/clothing/suit/space/space_ninja/proc/ninjamirage()
set name = "Spider Mirage"
set desc = "Utilizes the internal VOID-shift device to create decoys and teleport behind a random target."
@@ -401,6 +408,7 @@ Allows to gib up to five squares in a straight line. Seriously.*/
limit--
if(limit<=0) break
+ handle_teleport_grab(picked, U)
U.loc = picked
U.dir = target.dir
diff --git a/code/game/gamemodes/extra/ninja_equipment.dm b/code/game/gamemodes/extra/ninja_equipment.dm
index b27dcb1b28d..bcfcba14e1c 100644
--- a/code/game/gamemodes/extra/ninja_equipment.dm
+++ b/code/game/gamemodes/extra/ninja_equipment.dm
@@ -1,61 +1,95 @@
/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+++++++++++++++++++++++++++++++++// \\++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++// //++++++++++++++++++++++++++++++++++
===================================SPACE NINJA EQUIPMENT===================================
___________________________________________________________________________________________
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
-//SUIT===================================
+/*
+===================================================================================
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+===================================================================================
+*/
+
+//=======//NEW AND DEL//=======//
/obj/item/clothing/suit/space/space_ninja/New()
..()
verbs += /obj/item/clothing/suit/space/space_ninja/proc/init//suit initialize verb
- //verbs += /obj/item/clothing/suit/space/space_ninja/proc/ai_instruction//for AIs
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/ai_instruction//for AIs
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ai_holo
spark_system = new /datum/effects/system/spark_spread()//spark initialize
spark_system.set_up(5, 0, src)
spark_system.attach(src)
- var/datum/reagents/R = new/datum/reagents(520)//reagent initialize
- reagents = R
- R.my_atom = src
- reagents.add_reagent("tricordrazine", 80)
- reagents.add_reagent("dexalinp", 80)
- reagents.add_reagent("spaceacillin", 80)
- reagents.add_reagent("anti_toxin", 80)
- reagents.add_reagent("radium", 120)//AI can inject radium directly. There should be at least 60 units left over after adrenaline boosting.
- reagents.add_reagent("nutriment", 80)
+ var/reagent_amount//reagent initialize
+ for(var/reagent_id in reagent_list)
+ reagent_amount += reagent_id == "radium" ? r_maxamount+(a_boost*a_transfer) : r_maxamount//AI can inject radium directly.
+ reagents = new(reagent_amount)
+ reagents.my_atom = src
+ for(var/reagent_id in reagent_list)
+ reagent_id == "radium" ? reagents.add_reagent(reagent_id, r_maxamount+(a_boost*a_transfer)) : reagents.add_reagent(reagent_id, r_maxamount)//It will take into account radium used for adrenaline boosting.
cell = new/obj/item/weapon/cell/high//The suit should *always* have a battery because so many things rely on it.
cell.charge = 9000//Starting charge should not be higher than maximum charge. It leads to problems with recharging.
/obj/item/clothing/suit/space/space_ninja/Del()
+ if(affecting)//To make sure the window is closed.
+ affecting << browse(null, "window=hack spideros")
if(AI)//If there are AIs present when the ninja kicks the bucket.
- killai(AI)
+ killai()
+ if(hologram)//If there is a hologram
+ del(hologram.i_attached)//Delete it and the attached image.
+ del(hologram)
..()
return
-/obj/item/clothing/suit/space/space_ninja/proc/terminate()
//Simply deletes all the attachments and self, killing all related procs.
+/obj/item/clothing/suit/space/space_ninja/proc/terminate()
del(n_hood)
del(n_gloves)
del(n_shoes)
del(src)
-/obj/item/clothing/suit/space/space_ninja/proc/killai(var/mob/living/silicon/ai/A as mob)
+/obj/item/clothing/suit/space/space_ninja/proc/killai(var/mob/living/silicon/ai/A = AI)
if(A.client)
A << "\red Self-erase protocol dete-- *bzzzzz*"
A << browse(null, "window=hack spideros")
AI = null
- A.death(1)//Kill
- del(AI)
+ A.death(1)//Kill, deleting mob.
+ del(A)
return
-/obj/item/clothing/suit/space/space_ninja/attackby(var/obj/item/device/aicard/aicard_temp as obj, U as mob)//When the suit is attacked by an AI card.
- if(istype(aicard_temp, /obj/item/device/aicard))//If it's actually an AI card.
- if(s_control)
- aicard_temp.transfer_ai("NINJASUIT","AICARD",src,U)
- else
- U << "\red ERROR: \black Remote access channel disabled."
+//=======//SUIT VERBS//=======//
+//Verbs link to procs because verb-like procs have a bug which prevents their use if the arguments are not readily referenced.
+
+/obj/item/clothing/suit/space/space_ninja/proc/init()
+ set name = "Initialize Suit"
+ set desc = "Initializes the suit for field operation."
+ set category = "Ninja Equip"
+
+ ninitialize()
+ return
+
+/obj/item/clothing/suit/space/space_ninja/proc/deinit()
+ set name = "De-Initialize Suit"
+ set desc = "Begins procedure to remove the suit."
+ set category = "Ninja Equip"
+
+ if(s_control&&!s_busy)
+ deinitialize()
+ else
+ affecting << "\red The function did not trigger!"
+ return
+
+/obj/item/clothing/suit/space/space_ninja/proc/spideros()
+ set name = "Display SpiderOS"
+ set desc = "Utilize built-in computer system."
+ set category = "Ninja Equip"
+
+ if(s_control&&!s_busy&&!kamikaze)
+ display_spideros()
+ else
+ affecting << "\red The interface is locked!"
return
/obj/item/clothing/suit/space/space_ninja/proc/stealth()
@@ -63,9 +97,702 @@ ________________________________________________________________________________
set desc = "Utilize the internal CLOAK-tech device to activate or deactivate stealth-camo."
set category = "Ninja Equip"
- toggle_stealth()
+ if(s_control&&!s_busy)
+ toggle_stealth()
+ else
+ affecting << "\red Stealth does not appear to work!"
return
+//=======//PROCESS PROCS//=======//
+
+/obj/item/clothing/suit/space/space_ninja/proc/ntick(var/mob/living/carbon/human/U as mob)
+ set background = 1
+
+ //Runs in the background while the suit is initialized.
+ spawn while(cell.charge>=0)
+
+ //Let's check for some safeties.
+ if(affecting&&affecting.monkeyizing) terminate()//Kills the suit and attached objects.
+ if(!s_initialized) return//When turned off the proc stops.
+ if(AI&&AI.stat==2)//If there is an AI and it's ded. Shouldn't happen without purging, could happen.
+ if(!s_control)
+ ai_return_control()//Return control to ninja if the AI was previously in control.
+ killai()//Delete AI.
+
+ //Now let's do the normal processing.
+ if(s_coold) s_coold--//Checks for ability s_cooldown first.
+ var/A = s_cost//s_cost is the default energy cost each ntick, usually 5.
+ if(!kamikaze)
+ if(blade_check(U))//If there is a blade held in hand.
+ A += s_acost
+ if(s_active)//If stealth is active.
+ A += s_acost
+ else
+ if(prob(s_delay))//Suit delay is used as probability. May change later.
+ U.bruteloss += k_damage//Default damage done, usually 1.
+ A = k_cost//kamikaze cost.
+ cell.charge-=A
+ if(cell.charge<=0)
+ if(kamikaze)
+ U.say("I DIE TO LIVE AGAIN!")
+ U << browse(null, "window=spideros")//Just in case.
+ U.death()
+ return
+ cell.charge=0
+ cancel_stealth()
+ sleep(10)//Checks every second.
+
+//=======//INITIALIZE//=======//
+
+/obj/item/clothing/suit/space/space_ninja/proc/ninitialize(delay = s_delay, mob/living/carbon/human/U = loc)
+ if(U.mind&&U.mind.assigned_role=="MODE"&&!s_initialized&&!s_busy)//Shouldn't be busy... but anything is possible I guess.
+ s_busy = 1
+ for(var/i = 0,i<7,i++)
+ switch(i)
+ if(0)
+ U << "\blue Now initializing..."
+ if(1)
+ if(!lock_suit(U))//To lock the suit onto wearer.
+ break
+ U << "\blue Securing external locking mechanism...\nNeural-net established."
+ if(2)
+ U << "\blue Extending neural-net interface...\nNow monitoring brain wave pattern..."
+ if(3)
+ if(U.stat==2||U.health<=0)
+ U << "\red FĆAL ÈRrÖR: 344--93#†&&21 BRÄÌN |/|/aVÈ PATT$RN RED\nA-A-aBÖrTÌNG..."
+ unlock_suit()
+ break
+ lock_suit(U,1)//Check for icons.
+ U.update_clothing()
+ U << "\blue Linking neural-net interface...\nPattern \green GREEN\blue, continuing operation."
+ if(4)
+ U << "\blue VOID-shift device status: ONLINE.\nCLOAK-tech device status: ONLINE."
+ if(5)
+ U << "\blue Primary system status: ONLINE.\nBackup system status: ONLINE.\nCurrent energy capacity: [cell.charge]."
+ if(6)
+ U << "\blue All systems operational. Welcome to SpiderOS, [U.real_name]."
+ grant_ninja_verbs()
+ grant_equip_verbs()
+ ntick(U)
+ sleep(delay)
+ s_busy = 0
+ else
+ if(!U.mind||U.mind.assigned_role!="MODE")//Your run of the mill persons shouldn't know what it is. Or how to turn it on.
+ U << "You do not understand how this suit functions. Where the heck did it even come from?"
+ else if(s_initialized)
+ U << "\red The suit is already functioning. \black Please report this bug."
+ else
+ U << "\red ERROR: \black You cannot use this function at this time."
+ return
+
+//=======//DEINITIALIZE//=======//
+
+/obj/item/clothing/suit/space/space_ninja/proc/deinitialize(delay = s_delay)
+ if(affecting==loc&&!s_busy)
+ var/mob/living/carbon/human/U = affecting
+ if(!s_initialized)
+ U << "\red The suit is not initialized. \black Please report this bug."
+ return
+ if(alert("Are you certain you wish to remove the suit? This will take time and remove all abilities.",,"Yes","No")=="No")
+ return
+ if(s_busy||flush)
+ U << "\red ERROR: \black You cannot use this function at this time."
+ return
+ s_busy = 1
+ for(var/i = 0,i<7,i++)
+ switch(i)
+ if(0)
+ U << "\blue Now de-initializing..."
+ remove_kamikaze(U)//Shutdowns kamikaze.
+ spideros = 0//Spideros resets.
+ if(1)
+ U << "\blue Logging off, [U:real_name]. Shutting down SpiderOS."
+ remove_ninja_verbs()
+ if(2)
+ U << "\blue Primary system status: OFFLINE.\nBackup system status: OFFLINE."
+ if(3)
+ U << "\blue VOID-shift device status: OFFLINE.\nCLOAK-tech device status: OFFLINE."
+ cancel_stealth()//Shutdowns stealth.
+ if(4)
+ U << "\blue Disconnecting neural-net interface...\greenSuccess\blue."
+ if(5)
+ U << "\blue Disengaging neural-net interface...\greenSuccess\blue."
+ if(6)
+ U << "\blue Unsecuring external locking mechanism...\nNeural-net abolished.\nOperation status: FINISHED."
+ blade_check(U,2)
+ remove_equip_verbs()
+ unlock_suit()
+ U.update_clothing()
+ sleep(delay)
+ s_busy = 0
+ return
+
+//=======//SPIDEROS PROC//=======//
+
+/obj/item/clothing/suit/space/space_ninja/proc/display_spideros()
+ if(!affecting) return//If no mob is wearing the suit. I almost forgot about this variable.
+ var/mob/living/carbon/human/U = affecting
+ var/mob/living/silicon/ai/A = AI
+ var/display_to = s_control ? U : A//Who do we want to display certain messages to?
+
+ var/dat = "SpiderOS"
+ if(spideros==0)
+ dat += "
Refresh"
+ else
+ dat += "
Refresh"
+ dat += " |
Return"
+ dat += " |
Close"
+ dat += "
"
+ if(s_control)
+ dat += "SpiderOS v.1.337
"
+ dat += "Welcome, [U.real_name].
"
+ else
+ dat += "SpiderOS v.ERR-RR00123
"
+ dat += "
"
+ dat += "
Current Time: [round(world.time / 36000)+12]:[(world.time / 600 % 60) < 10 ? add_zero(world.time / 600 % 60, 1) : world.time / 600 % 60]
"
+ dat += "
Battery Life: [round(cell.charge/100)]%
"
+ dat += "
Smoke Bombs: [s_bombs]
"
+ dat += "
pai Device: "
+ if(pai)
+ dat += "Configure"
+ dat += " | "
+ dat += "Eject"
+ else
+ dat += "None Detected"
+ dat += "
"
+
+ switch(spideros)
+ if(0)
+ dat += "
Available Functions:
"
+ dat += ""
+ if(1)
+ dat += "
Medical Report:
"
+ if(U.dna)
+ dat += "Fingerprints: [md5(U.dna.uni_identity)]
"
+ dat += "Unique identity: [U.dna.unique_enzymes]
"
+ dat += "Overall Status: [U.stat > 1 ? "dead" : "[U.health]% healthy"]
"
+ dat += "Nutrition Status: [U.nutrition]
"
+ dat += "Oxygen loss: [U.oxyloss]"
+ dat += " | Toxin levels: [U.toxloss]
"
+ dat += "Burn severity: [U.fireloss]"
+ dat += " | Brute trauma: [U.bruteloss]
"
+ dat += "Radiation Level: [U.radiation] rad
"
+ dat += "Body Temperature: [U.bodytemperature-T0C]°C ([U.bodytemperature*1.8-459.67]°F)
"
+ if(U.virus)
+ dat += "Warning Virus Detected. Name: [U.virus.name].Type: [U.virus.spread]. Stage: [U.virus.stage]/[U.virus.max_stages]. Possible Cure: [U.virus.cure].
"
+ dat += ""
+ if(2)
+ dat += "
Atmospheric Scan:
"//Headers don't need breaks. They are automatically placed.
+ var/turf/T = get_turf_or_move(U.loc)
+ if (isnull(T))
+ dat += "Unable to obtain a reading."
+ else
+ var/datum/gas_mixture/environment = T.return_air()
+
+ var/pressure = environment.return_pressure()
+ var/total_moles = environment.total_moles()
+
+ dat += "Air Pressure: [round(pressure,0.1)] kPa"
+
+ if (total_moles)
+ var/o2_level = environment.oxygen/total_moles
+ var/n2_level = environment.nitrogen/total_moles
+ var/co2_level = environment.carbon_dioxide/total_moles
+ var/plasma_level = environment.toxins/total_moles
+ var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level)
+ dat += ""
+ dat += "- Nitrogen: [round(n2_level*100)]%
"
+ dat += "- Oxygen: [round(o2_level*100)]%
"
+ dat += "- Carbon Dioxide: [round(co2_level*100)]%
"
+ dat += "- Plasma: [round(plasma_level*100)]%
"
+ dat += "
"
+ if(unknown_level > 0.01)
+ dat += "OTHER: [round(unknown_level)]%
"
+
+ dat += "Temperature: [round(environment.temperature-T0C)]°C"
+ if(3)
+ if(k_unlock==7||!s_control)
+ dat += "
Hidden Menu"
+ dat += "
Anonymous Messenger:
"//Anonymous because the receiver will not know the sender's identity.
+ dat += "
Detected PDAs:
"
+ dat += ""
+ var/count = 0
+ for (var/obj/item/device/pda/P in world)
+ if (!P.owner||P.toff)
+ continue
+ dat += "- [P]"
+ dat += "
"
+ count++
+ dat += "
"
+ if (count == 0)
+ dat += "None detected.
"
+ if(32)
+ dat += "
Hidden Menu:
"
+ if(s_control)
+ dat += "Please input password: "
+ dat += "HERE
"
+ dat += "
"
+ dat += "Remember, you will not be able to recharge energy during this function. If energy runs out, the suit will auto self-destruct.
"
+ dat += "Use with caution. De-initialize the suit when energy is low."
+ else
+ //Only leaving this in for funnays. CAN'T LET YOU DO THAT STAR FOX
+ dat += "WARNING: Hostile runtime intrusion detected: operation locked. The Spider Clan is watching you, INTRUDER."
+ dat += "ERROR: TARANTULA.v.4.77.12 encryption algorithm detected. Unable to decrypt archive.
"
+ if(4)
+ dat += "
Ninja Manual:
"
+ dat += "Who they are:
"
+ dat += "Space ninjas are a special type of ninja, specifically one of the space-faring type. The vast majority of space ninjas belong to the Spider Clan, a cult-like sect, which has existed for several hundred years. The Spider Clan practice a sort of augmentation of human flesh in order to achieve a more perfect state of being and follow Postmodern Space Bushido. They also kill people for money. Their leaders are chosen from the oldest of the grand-masters, people that have lived a lot longer than any mortal man should.
Being a sect of technology-loving fanatics, the Spider Clan have the very best to choose from in terms of hardware--cybernetic implants, exoskeleton rigs, hyper-capacity batteries, and you get the idea. Some believe that much of the Spider Clan equipment is based on reverse-engineered alien technology while others doubt such claims.
Whatever the case, their technology is absolutely superb."
+ dat += "How they relate to other SS13 organizations:
"
+ dat += ""
+ dat += "- *Nanotrasen and the Syndicate are two sides of the same coin and that coin is valuable.
"
+ dat += "- *The Space Wizard Federation is a problem, mainly because they are an extremely dangerous group of unpredictable individuals--not to mention the wizards hate technology and are in direct opposition of the Spider Clan. Best avoided or left well-enough alone. How to battle: wizards possess several powerful abilities to steer clear off. Blind in particular is a nasty spell--jaunt away if you are blinded and never approach a wizard in melee. Stealth may also work if the wizard is not wearing thermal scanners--don't count on this. Run away if you feel threatened and await a better opportunity.
"
+ dat += "- *Changeling Hivemind: extremely dangerous and to be killed on sight. How to battle: they will likely try to absorb you. Adrenaline boost, then phase shift into them. If you get stung, use SpiderOS to inject counter-agents. Stealth may also work but detecting a changeling is the real battle.
"
+ dat += "- *Xeno Hivemind: their skulls make interesting kitchen decorations and are challenging to best, especially in larger nests. How to battle: they can see through your stealth guise and energy stars will not work on them. Best killed with a Phase Shift or at range. If you happen on a projectile stun weapon, use it and then close in to melee.
"
+ dat += "
"
+ dat += "The reason they (you) are here:
"
+ dat += "Space ninjas are renowned throughout the known controlled space as fearless spies, infiltrators, and assassins. They are sent on missions of varying nature by Nanotrasen, the Syndicate, and other shady organizations and people. To hire a space ninja means serious business."
+ dat += "Their playstyle:
"
+ dat += "A mix of traitor, changeling, and wizard. Ninjas rely on energy, or electricity to be precise, to keep their suits running (when out of energy, a suit hibernates). Suits gain energy from objects or creatures that contain electrical charge. APCs, cell batteries, rechargers, SMES batteries, cyborgs, mechs, and exposed wires are currently supported. Through energy ninjas gain access to special powers--while all powers are tied to the ninja suit, the most useful of them are verb activated--to help them in their mission.
It is a constant struggle for a ninja to remain hidden long enough to recharge the suit and accomplish their objective; despite their arsenal of abilities, ninjas can die like any other. Unlike wizards, ninjas do not possess good crowd control and are typically forced to play more subdued in order to achieve their goals. Some of their abilities are specifically designed to confuse and disorient others.
With that said, it should be perfectly possible to completely flip the fuck out and rampage as a ninja."
+ dat += "Their powers:
"
+ dat += "There are two primary types: Equipment and Abilties. Passive effects are always on. Active effects must be turned on and remain active only when there is energy to do so. Ability costs are listed next to them."
+ dat += "Equipment: cannot be tracked by AI (passive), faster speed (passive), stealth (active), vision switch (passive if toggled), voice masking (passive), SpiderOS (passive if toggled), energy drain (passive if toggled)."
+ dat += ""
+ dat += "- Voice masking generates a random name the ninja can use over the radio and in-person. Although, the former use is recommended.
"
+ dat += "- Toggling vision cycles to one of the following: thermal, meson, or darkness vision. The starting mode allows one to scout the identity of those in view, revealing their role. Traitors, revolutionaries, wizards, and other such people will be made known to you.
"
+ dat += "- Stealth, when activated, drains more battery charge and works similarly to a syndicate cloak. The cloak will deactivate when most Abilities are utilized.
"
+ dat += "- On-board AI: The suit is able to download an AI much like an intelicard. Check with SpiderOS for details once downloaded.
"
+ dat += "- SpiderOS is a specialized, PDA-like screen that allows for a small variety of functions, such as injecting healing chemicals directly from the suit. You are using it now, if that was not already obvious. You may also download AI modules directly to the OS.
"
+ dat += "
"
+ dat += "Abilities:"
+ dat += ""
+ dat += "- *Phase Shift (2000E) and Phase Jaunt (1000E) are unique powers in that they can both be used for defense and offense. Jaunt launches the ninja forward facing up to 9 squares, somewhat randomly selecting the final destination. Shift can only be used on turf in view but is precise (cannot be used on walls). Any living mob in the area teleported to is instantly gibbed (mechs are damaged, huggers and other similar critters are killed). It is possible to teleport with a target, provided you grab them before teleporting.
"
+ dat += "- *Energy Blade (500E) is a highly effective weapon. It is summoned directly to the ninja's hand and can also function as an EMAG for certain objects (doors/lockers/etc). You may also use it to cut through walls and disabled doors. Experiment! The blade will crit humans in two hits. This item cannot be placed in containers and when dropped or thrown disappears. Having an energy blade drains more power from the battery each tick.
"
+ dat += "- *EM Pulse (2500E) is a highly useful ability that will create an electromagnetic shockwave around the ninja, disabling technology whenever possible. If used properly it can render a security force effectively useless. Of course, getting beat up with a toolbox is not accounted for.
"
+ dat += "- *Energy Star (500E) is a ninja star made of green energy AND coated in poison. It works by picking a random living target within range and can be spammed to great effect in incapacitating foes. Just remember that the poison used is also used by the Xeno Hivemind (and will have no effect on them).
"
+ dat += "- *Energy Net (2000E) is a non-lethal solution to incapacitating humanoids. The net is made of non-harmful phase energy and will halt movement as long as it remains in effect--it can be destroyed. If the net is not destroyed, after a certain time it will teleport the target to a holding facility for the Spider Clan and then vanish. You will be notified if the net fails or succeeds in capturing a target in this manner. Combine with energy stars or stripping to ensure success. Abduction never looked this leet.
"
+ dat += "- *Adrenaline Boost (1 E. Boost/3) recovers the user from stun, weakness, and paralysis. Also injects 20 units of radium into the bloodstream.
"
+ dat += "- *Smoke Bomb (1 Sm.Bomb/10) is a weak but potentially useful ability. It creates harmful smoke and can be used in tandem with other powers to confuse enemies.
"
+ dat += "- *???: unleash the True Ultimate Power!
"
+ dat += "IMPORTANT:
"
+ dat += ""
+ dat += "- *Make sure to toggle Special Interaction from the Ninja Equipment menu to interact differently with certain objects.
"
+ dat += "- *Your starting power cell can be replaced if you find one with higher maximum energy capacity by clicking on the new cell with the same hand (super and hyper cells).
"
+ dat += "- *Conserve your energy. Without it, you are very vulnerable.
"
+ dat += "
"
+ dat += "That is all you will need to know. The rest will come with practice and talent. Good luck!"
+ dat += "Master /N
"
+ if(5)
+ var/laws
+ dat += "
AI Control:
"
+ //var/mob/living/silicon/ai/A = AI
+ if(AI)//If an AI exists.
+ dat += "Stored AI: [A.name]
"
+ dat += "System integrity: [(A.health+100)/2]%
"
+
+ for (var/index = 1, index <= A.laws.ion.len, index++)
+ var/law = A.laws.ion[index]
+ if (length(law) > 0)
+ var/num = ionnum()
+ laws += "- [num]. [law]
"
+
+ //I personally think this makes things a little more fun. Ninjas can override all but law 0.
+ //if (A.laws.zeroth)
+ // laws += "- 0: [A.laws.zeroth]
"
+
+ var/number = 1
+ for (var/index = 1, index <= A.laws.inherent.len, index++)
+ var/law = A.laws.inherent[index]
+ if (length(law) > 0)
+ laws += "- [number]: [law]
"
+ number++
+
+ for (var/index = 1, index <= A.laws.supplied.len, index++)
+ var/law = A.laws.supplied[index]
+ if (length(law) > 0)
+ laws += "- [number]: [law]
"
+ number++
+
+ dat += "Laws:
"
+
+ if (!flush)
+ dat += {"Purge AI
"}
+ else
+ dat += "Purge in progress...
"
+ dat += {" [A.control_disabled ? "Enable" : "Disable"] Wireless Activity"}
+ if(6)
+ dat += "
Activate Abilities:
"
+ dat += ""
+ dat += ""
+
+ //Setting the can>resize etc to 0 remove them from the drag bar but still allows the window to be draggable.
+ display_to << browse(dat,"window=spideros;size=400x444;border=1;can_resize=0;can_close=0;can_minimize=0")
+
+//=======//SPIDEROS TOPIC PROC//=======//
+
+/obj/item/clothing/suit/space/space_ninja/Topic(href, href_list)
+ ..()
+ var/mob/living/carbon/human/U = affecting
+ var/mob/living/silicon/ai/A = AI
+ var/display_to = s_control ? U : A//Who do we want to display certain messages to?
+
+ if(s_control)
+ if(!affecting||U.stat||!s_initialized)//Check to make sure the guy is wearing the suit after clicking and it's on.
+ U << "\red Your suit must be worn and active to use this function."
+ U << browse(null, "window=spideros")//Closes the window.
+ return
+
+ if(k_unlock!=7&&href_list["choice"]!="Return")
+ var/u1=text2num(href_list["choice"])
+ var/u2=(u1?abs(abs(k_unlock-u1)-2):1)
+ k_unlock=(!u2? k_unlock+1:0)
+ if(k_unlock==7)
+ U << "Anonymous Messenger blinks."
+ else
+ if(!affecting||A.stat||!s_initialized||A.loc!=src)
+ A << "\red This function is not available at this time."
+ A << browse(null, "window=spideros")//Closes the window.
+ return
+
+ switch(href_list["choice"])
+ if("Close")
+ display_to << browse(null, "window=spideros")
+ return
+ if("Refresh")//Refresh, goes to the end of the proc.
+ if("Return")//Return
+ if(spideros<=9)
+ spideros=0
+ else
+ spideros = round(spideros/10)//Best way to do this, flooring to nearest integer. As an example, another way of doing it is attached below:
+ // var/temp = num2text(spideros)
+ // var/return_to = copytext(temp, 1, (length(temp)))//length has to be to the length of the thing because by default it's length+1
+ // spideros = text2num(return_to)//Maximum length here is 6. Use (return_to, X) to specify larger strings if needed.
+
+ if("Stealth")
+ toggle_stealth()
+
+ if("Shock")
+ var/damage = min(cell.charge, rand(50,150))//Uses either the current energy left over or between 50 and 150.
+ if(damage>1)//So they don't spam it when energy is a factor.
+ spark_system.start()//SPARKS THERE SHALL BE SPARKS
+ U.electrocute_act(damage, src,0.1,1)//The last argument is a safety for the human proc that checks for gloves.
+ cell.charge -= damage
+ else
+ A << "\red ERROR: \black Not enough energy remaining."
+
+ if("Message")
+ var/obj/item/device/pda/P = locate(href_list["target"])
+ var/t = input(U, "Please enter untraceable message.") as text
+ t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN)
+ if(!t||U.stat||U.wear_suit!=src||!s_initialized)//Wow, another one of these. Man...
+ display_to << browse(null, "window=spideros")
+ return
+ if(isnull(P)||P.toff)//So it doesn't freak out if the object no-longer exists.
+ display_to << "\red Error: unable to deliver message."
+ display_spideros()
+ return
+ P.tnote += "← From [!s_control?(A):"an unknown source"]:
[t]
"
+ if (!P.silent)
+ playsound(P.loc, 'twobeep.ogg', 50, 1)
+ for (var/mob/O in hearers(3, P.loc))
+ O.show_message(text("\icon[P] *[P.ttone]*"))
+ P.overlays = null
+ P.overlays += image('pda.dmi', "pda-r")
+
+ if("Inject")
+ if( (href_list["tag"]=="radium"? (reagents.get_reagent_amount("radium"))<=(a_boost*a_transfer) : !reagents.get_reagent_amount(href_list["tag"])) )//Special case for radium. If there are only a_boost*a_transfer radium units left.
+ display_to << "\red Error: the suit cannot perform this function. Out of [href_list["name"]]."
+ else
+ reagents.reaction(U, 2)
+ reagents.trans_id_to(U, href_list["tag"], href_list["tag"]=="nutriment"?5:a_transfer)//Nutriment is a special case since it's very potent. Shouldn't influence actual refill amounts or anything.
+ display_to << "Injecting..."
+ U << "You feel a tiny prick and a sudden rush of substance in to your veins."
+
+ if("Trigger Ability")
+ var/ability_name = href_list["name"]+href_list["cost"]//Adds the name and cost to create the full proc name.
+ var/proc_arguments//What arguments to later pass to the proc, if any.
+ var/targets[] = list()//To later check for.
+ var/safety = 0//To later make sure we're triggering the proc when needed.
+ switch(href_list["name"])//Special case.
+ if("Phase Shift")
+ safety = 1
+ for(var/turf/T in oview(5,loc))
+ targets.Add(T)
+ if("Energy Net")
+ safety = 1
+ for(var/mob/living/carbon/M in oview(5,loc))
+ targets.Add(M)
+ if(targets.len)//Let's create an argument for the proc if needed.
+ proc_arguments = pick(targets)
+ safety = 0
+ if(!safety)
+ A << "You trigger [href_list["name"]]."
+ U << "[href_list["name"]] suddenly triggered!"
+ call(src,ability_name)(proc_arguments)
+ else
+ A << "There are no potential [href_list["name"]=="Phase Shift"?"destinations" : "targets"] in view."
+
+ if("Unlock Kamikaze")
+ if(input(U)=="Divine Wind")
+ if( !(U.stat||U.wear_suit!=src||!s_initialized) )
+ if( !(cell.charge<=1||s_busy) )
+ s_busy = 1
+ for(var/i = 0, i<4, i++)
+ switch(i)
+ if(0)
+ U << "\blue Engaging mode...\n\blackCODE NAME: \red KAMIKAZE"
+ if(1)
+ U << "\blue Re-routing power nodes... \nUnlocking limiter..."
+ if(2)
+ U << "\blue Power nodes re-routed. \nLimiter unlocked."
+ if(3)
+ grant_kamikaze(U)//Give them verbs and change variables as necessary.
+ U.update_clothing()//Update their clothing.
+ ninjablade()//Summon two energy blades.
+ message_admins("\blue [U.key] used KAMIKAZE mode.", 1)//Let the admins know.
+ s_busy = 0
+ return
+ sleep(s_delay)
+ else
+ U << "\red ERROR: \black Unable to initiate mode."
+ else
+ U << browse(null, "window=spideros")
+ s_busy = 0
+ return
+ else
+ U << "\red ERROR: WRONG PASSWORD!"
+ k_unlock = 0
+ spideros = 0
+ s_busy = 0
+
+ if("Configure pAI")
+ pai.attack_self(U)
+
+ if("Eject pAI")
+ var/turf/T = get_turf(loc)
+ if(T)
+ pai.loc = T
+ pai = null
+ else
+ U << "\red ERROR: \black Could not eject pAI card."
+
+ if("Override AI Laws")
+ var/law_zero = A.laws.zeroth//Remembers law zero, if there is one.
+ A.laws = new /datum/ai_laws/ninja_override
+ A.set_zeroth_law(law_zero)//Adds back law zero if there was one.
+ A.show_laws()
+ U << "\blue Law Override: SUCCESS."
+
+ if("Purge AI")
+ var/confirm = alert("Are you sure you want to purge the AI? This cannot be undone once started.", "Confirm purge", "Yes", "No")
+ if(U.stat||U.wear_suit!=src||!s_initialized)
+ U << browse(null, "window=spideros")
+ return
+ if(confirm == "Yes"&&AI)
+ if(A.laws.zeroth)//Gives a few seconds to re-upload the AI somewhere before it takes full control.
+ s_busy = 1
+ for(var/i=0,i<5,i++)
+ if(AI==A)
+ switch(i)
+ if(0)
+ A << "\red WARNING: \black purge procedure detected. \nNow hacking host..."
+ U << "\red WARNING: HACKING AT††TEMP† IN PR0GRESs!"
+ spideros = 0
+ k_unlock = 0
+ U << browse(null, "window=spideros")
+ if(1)
+ A << "Disconnecting neural interface..."
+ U << "\red WAR†NING: þR†O0†GrÈ--S 2&3%"
+ if(2)
+ A << "Shutting down external protocol..."
+ U << "\red WARNING: PþþþþRÖ†GrÈ5S 677^%"
+ cancel_stealth()
+ if(3)
+ A << "Connecting to kernel..."
+ U << "\red WARNING: ÈR†rÖR_404"
+ A.control_disabled = 0
+ if(4)
+ A << "Connection established and secured. Menu updated."
+ U << "\red WÄr#nING: #%@!!WȆ|_4þ54@ \nUnÄB88l3 TÖ LÖ-†o-LÖCaT2 ##$!ÈRNÈ0..%.."
+ grant_AI_verbs()
+ return
+ sleep(s_delay)
+ else break
+ s_busy = 0
+ U << "\blue Hacking attempt disconnected. Resuming normal operation."
+ else
+ flush = 1
+ A.suiciding = 1
+ A << "Your core files are being purged! This is the end..."
+ spawn(0)
+ display_spideros()//To refresh the screen and let this finish.
+ while (A.stat != 2)
+ A.oxyloss += 2
+ A.updatehealth()
+ sleep(10)
+ killai()
+ U << "Artificial Intelligence was terminated. Rebooting..."
+ flush = 0
+
+ if("Wireless AI")
+ A.control_disabled = !A.control_disabled
+ A << "AI wireless has been [A.control_disabled ? "disabled" : "enabled"]."
+ else//If it's not a defined function, it's a menu.
+ spideros=text2num(href_list["choice"])
+
+ display_spideros()//Refreshes the screen by calling it again (which replaces current screen with new screen).
+ return
+
+//=======//SPECIAL AI FUNCTIONS//=======//
+
+/obj/item/clothing/suit/space/space_ninja/proc/ai_holo(var/turf/T in oview(3,affecting))//To have an internal AI display a hologram to the AI and ninja only.
+ set name = "Display Hologram"
+ set desc = "Channel a holographic image directly to the user's field of vision. Others will not see it."
+ set category = null
+ set src = usr.loc
+
+ if(s_initialized&&affecting&&affecting.client&&istype(affecting.loc, /turf))//If the host exists and they are playing, and their location is a turf.
+ if(!hologram)//If there is not already a hologram.
+ hologram = new(T)//Spawn a blank effect at the location.
+ hologram.invisibility = 101//So that it doesn't show up, ever. This also means one could attach a number of images to a single obj and display them differently to differnet people.
+ hologram.dir = get_dir_to(T,affecting.loc)
+ var/image/I = image('mob.dmi',hologram,"ai-holo")//Attach an image to object.
+ hologram.i_attached = I//To attach the image in order to later reference.
+ AI << I
+ affecting << I
+ affecting << "An image flicks to life nearby. It appears visible to you only."
+
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/ai_holo_clear
+
+ ai_holo_process()//Move to initialize
+ else
+ AI << "\red ERROR: \black Image feed in progress."
+ else
+ AI << "\red ERROR: \black Unable to project image."
+ return
+
+/obj/item/clothing/suit/space/space_ninja/proc/ai_holo_process()
+ set background = 1
+
+ spawn while(hologram&&s_initialized&&AI)//Suit on and there is an AI present.
+ if(!s_initialized||get_dist(affecting,hologram.loc)>3)//Once suit is de-initialized or hologram reaches out of bounds.
+ del(hologram.i_attached)
+ del(hologram)
+
+ verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ai_holo_clear
+ return
+ sleep(10)//Checks every second.
+
+/obj/item/clothing/suit/space/space_ninja/proc/ai_instruction()//Let's the AI know what they can do.
+ set name = "Instructions"
+ set desc = "Displays a list of helpful information."
+ set category = "AI Ninja Equip"
+ set src = usr.loc
+
+ AI << "The menu you are seeing will contain other commands if they become available.\nRight click a nearby turf to display an AI Hologram. It will only be visible to you and your host. You can move it freely using normal movement keys--it will disappear if placed too far away."
+
+/obj/item/clothing/suit/space/space_ninja/proc/ai_holo_clear()
+ set name = "Clear Hologram"
+ set desc = "Stops projecting the current holographic image."
+ set category = "AI Ninja Equip"
+ set src = usr.loc
+
+ del(hologram.i_attached)
+ del(hologram)
+
+ verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ai_holo_clear
+ return
+
+/obj/item/clothing/suit/space/space_ninja/proc/ai_hack_ninja()
+ set name = "Hack SpiderOS"
+ set desc = "Hack directly into the Black Widow(tm) neuro-interface."
+ set category = "AI Ninja Equip"
+ set src = usr.loc
+
+ display_spideros()
+ return
+
+/obj/item/clothing/suit/space/space_ninja/proc/ai_return_control()
+ set name = "Relinquish Control"
+ set desc = "Return control to the user."
+ set category = "AI Ninja Equip"
+ set src = usr.loc
+
+ AI << browse(null, "window=spideros")//Close window
+ AI << "You have seized your hacking attempt. [affecting.real_name] has regained control."
+ affecting << "UPDATE: [AI.real_name] has ceased hacking attempt. All systems clear."
+
+ remove_AI_verbs()
+ return
+
+//=======//GENERAL SUIT PROCS//=======//
+
+/obj/item/clothing/suit/space/space_ninja/attackby(obj/item/I, mob/U)
+ if(U==affecting)//Safety, in case you try doing this without wearing the suit/being the person with the suit.
+ if(istype(I, /obj/item/device/aicard))//If it's an AI card.
+ if(s_control)
+ I:transfer_ai("NINJASUIT","AICARD",src,U)
+ else
+ U << "\red ERROR: \black Remote access channel disabled."
+ return//Return individually so that ..() can run properly at the end of the proc.
+ else if(istype(I, /obj/item/device/paicard) && !pai)//If it's a pai card.
+ U:drop_item()
+ I.loc = src
+ pai = I
+ U << "\blue You slot \the [I] into [src]."
+ updateUsrDialog()
+ return
+ else if(istype(I, /obj/item/weapon/reagent_containers/glass))//If it's a glass beaker.
+ var/total_reagent_transfer//Keep track of this stuff.
+ for(var/reagent_id in reagent_list)
+ var/datum/reagent/R = I.reagents.has_reagent(reagent_id)//Mostly to pull up the name of the reagent after calculating. Also easier to use than writing long proc paths.
+/* if(reagents.get_reagent_amount(reagent_id)=a_transfer)//Radium is always special.
+ //Here we determine how much reagent will actually transfer if there is enough to transfer or there is a need of transfer. Minimum of max amount available (using a_transfer) or amount needed.
+ var/amount_to_transfer = min( (r_maxamount+(reagent_id == "radium"?(a_boost*a_transfer):0)-reagents.get_reagent_amount(reagent_id)) ,(round(I.reagents.get_reagent_amount(reagent_id)/a_transfer))*a_transfer)//In the end here, we round the amount available, then multiply it again.
+ total_reagent_transfer += amount_to_transfer//Add to total reagent trans.
+ I.reagents.remove_reagent(reagent_id, amount_to_transfer)//Remove from beaker.
+ reagents.add_reagent(reagent_id, amount_to_transfer)//Add to suit. Reactions are not important.
+ U << "Added [amount_to_transfer] units of [reagent_id]."//Fix the id label.
+*/
+ if(R&&reagents.get_reagent_amount(reagent_id)=a_transfer)//Radium is always special.
+ //Here we determine how much reagent will actually transfer if there is enough to transfer or there is a need of transfer. Minimum of max amount available (using a_transfer) or amount needed.
+ var/amount_to_transfer = min( (r_maxamount+(reagent_id == "radium"?(a_boost*a_transfer):0)-reagents.get_reagent_amount(reagent_id)) ,(round(R.volume/a_transfer))*a_transfer)//In the end here, we round the amount available, then multiply it again.
+ R.volume -= amount_to_transfer//Remove from reagent volume. Don't want to delete the reagent now since we need to perserve the name.
+ reagents.add_reagent(reagent_id, amount_to_transfer)//Add to suit. Reactions are not important.
+ total_reagent_transfer += amount_to_transfer//Add to total reagent trans.
+ U << "Added [amount_to_transfer] units of [R.name]."//Reports on the specific reagent added.
+ I.reagents.update_total()//Now we manually update the total to make sure everything is properly shoved under the rug.
+
+ U << "Replenished a total of [total_reagent_transfer ? total_reagent_transfer : "zero"] chemical units."//Let the player know how much total volume was added.
+ return
+ ..()
+
/obj/item/clothing/suit/space/space_ninja/proc/toggle_stealth()
var/mob/living/carbon/human/U = affecting
@@ -110,776 +837,25 @@ ________________________________________________________________________________
return 1
return 0
-/obj/item/clothing/suit/space/space_ninja/proc/ntick(var/mob/living/carbon/human/U as mob)
- set background = 1
-
- spawn while(cell.charge>=0)//Runs in the background while the suit is initialized.
- if(affecting&&affecting.monkeyizing) terminate()//Kills the suit and attached objects.
- if(!s_initialized) return//When turned off the proc stops.
- if(s_coold) s_coold--//Checks for ability s_cooldown.
- var/A = 5//Energy cost each tick.
- if(!kamikaze)
- if(istype(U.get_active_hand(), /obj/item/weapon/blade))//Sword check.
+/obj/item/clothing/suit/space/space_ninja/proc/blade_check(mob/living/carbon/U, X = 1)//Default to checking for blade energy.
+ switch(X)
+ if(1)
+ if(istype(U.get_active_hand(), /obj/item/weapon/blade))
if(cell.charge<=0)//If no charge left.
- U.drop_item()//Sword is dropped from active hand (and deleted).
- else A += 20//Otherwise, more energy consumption.
+ U.drop_item()//Blade is dropped from active hand (and deleted).
+ else return 1
else if(istype(U.get_inactive_hand(), /obj/item/weapon/blade))
if(cell.charge<=0)
U.swap_hand()//swap hand
- U.drop_item()//drop sword
- else A += 20
- if(s_active)//If stealth is active.
- A += 25
- else
- if(prob(25))
- U.bruteloss += 1
- A = 200
- cell.charge-=A
- if(cell.charge<=0)
- if(kamikaze)
- U.say("I DIE TO LIVE AGAIN!")
- U << browse(null, "window=spideros")//Just in case.
- U.death()
- return
- cell.charge=0
- cancel_stealth()
- sleep(10)//Checks every second.
-
-/obj/item/clothing/suit/space/space_ninja/proc/init()
- set name = "Initialize Suit"
- set desc = "Initializes the suit for field operation."
- set category = "Ninja Equip"
-
- var/mob/living/carbon/human/U = loc
- if(U.mind&&U.mind.special_role=="Space Ninja"&&U:wear_suit==src&&!s_initialized)
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/init
- U << "\blue Now initializing..."
- sleep(40)
- if(U.mind.assigned_role=="Mime")
- U << "\red FATAL ERROR: 382200-*#00CODE RED\nUNAUTHORIZED USE DETECTED\nCOMMENCING SUB-R0UTIN3 13...\nTERMINATING U-U-USER..."
- U.gib()
- return
- if(!istype(U.head, /obj/item/clothing/head/helmet/space/space_ninja))
- U << "\red ERROR: 100113 UNABLE TO LOCATE HEAD GEAR\nABORTING..."
- return
- if(!istype(U.shoes, /obj/item/clothing/shoes/space_ninja))
- U << "\red ERROR: 122011 UNABLE TO LOCATE FOOT GEAR\nABORTING..."
- return
- if(!istype(U.gloves, /obj/item/clothing/gloves/space_ninja))
- U << "\red ERROR: 110223 UNABLE TO LOCATE HAND GEAR\nABORTING..."
- return
- U << "\blue Securing external locking mechanism...\nNeural-net established."
-
- n_hood = U.head
- n_hood.canremove=0
- n_shoes = U.shoes
- n_shoes.canremove=0
- n_shoes.slowdown--
- n_gloves = U.gloves
- n_gloves.canremove=0
- canremove=0
-
- sleep(40)
- U << "\blue Extending neural-net interface...\nNow monitoring brain wave pattern..."
- sleep(40)
- if(U.stat==2||U.health<=0)
- U << "\red FATAL ERROR: 344--93#&&21 BRAIN WAV3 PATT$RN RED\nA-A-AB0RTING..."
- U.head.canremove=1
- U.shoes.canremove=1
- U.gloves.canremove=1
- canremove=1
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/init
- return
- if(U.gender==FEMALE)
- icon_state = "s-ninjanf"
- else
- icon_state = "s-ninjan"
- U.gloves.icon_state = "s-ninjan"
- U.gloves.item_state = "s-ninjan"
- U.update_clothing()
- U << "\blue Linking neural-net interface...\nPattern \green GREEN\blue, continuing operation."
- sleep(40)
- U << "\blue VOID-shift device status: ONLINE.\nCLOAK-tech device status: ONLINE."
- sleep(40)
- U << "\blue Primary system status: ONLINE.\nBackup system status: ONLINE.\nCurrent energy capacity: [cell.charge]."
- sleep(40)
- U << "\blue All systems operational. Welcome to SpiderOS, [U.real_name]."
- grant_ninja_verbs()
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/spideros
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/stealth
- n_gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/drain_wire
- n_gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/toggled
- affecting=U
- ntick(U)
- else
- if(U.mind&&U.mind.special_role!="Space Ninja")
- U << "\red You do not understand how this suit functions."
- else if(U.wear_suit!=src)
- U << "\red You must be wearing the suit to use this function."
- else if(s_initialized)
- U << "\red The suit is already functioning."
- else
- U << "\red You cannot use this function at this time."
- return
-
-/obj/item/clothing/suit/space/space_ninja/proc/deinit()
- set name = "De-Initialize Suit"
- set desc = "Begins procedure to remove the suit."
- set category = "Ninja Equip"
-
- if(affecting!=loc)
- return
- var/mob/living/carbon/human/U = affecting
- if(!s_initialized)
- U << "\red The suit is not initialized."
- return
- if(alert("Are you certain you wish to remove the suit? This will take time and remove all abilities.",,"Yes","No")=="No")
- return
-
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/deinit
- U << "\blue Now de-initializing..."
- if(kamikaze)
- U << "\blue Disengaging mode...\n\blackCODE NAME: \red KAMIKAZE"
- remove_kamikaze_verbs()
- U.incorporeal_move = 0
- U.density = 1
- spideros = 0
- sleep(40)
- remove_ninja_verbs()
- U << "\blue Logging off, [U:real_name]. Shutting down SpiderOS."
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/spideros
- sleep(40)
- U << "\blue Primary system status: OFFLINE.\nBackup system status: OFFLINE."
- sleep(40)
- U << "\blue VOID-shift device status: OFFLINE.\nCLOAK-tech device status: OFFLINE."
- if(s_active)//Shutdowns stealth.
- cancel_stealth()
- sleep(40)
- if(U.stat||U.health<=0)
- U << "\red FATAL ERROR: 412--GG##&77 BRAIN WAV3 PATT$RN RED\nI-I-INITIATING S-SELf DeStrCuCCCT%$#@@!!$^#!..."
- spawn(10)
- U << "\red #3#"
- spawn(20)
- U << "\red #2#"
- spawn(30)
- U << "\red #1#: G00DBYE"
- U.gib()
- return
- U << "\blue Disconnecting neural-net interface...\greenSuccess\blue."
- sleep(40)
- U << "\blue Disengaging neural-net interface...\greenSuccess\blue."
- sleep(40)
-
- if(n_hood)
- n_hood.canremove=1
- if(n_shoes)
- n_shoes.canremove=1
- n_shoes.slowdown++
- if(n_gloves)
- n_gloves.icon_state = "s-ninja"
- n_gloves.item_state = "s-ninja"
- n_gloves.canremove=1
- n_gloves.candrain=0
- n_gloves.draining=0
- n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/drain_wire
- n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled
- canremove=1
- s_initialized=0
- affecting=null
- slowdown=1
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/init
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/stealth
- icon_state = "s-ninja"
- U.update_clothing()
-
- if(istype(U.get_active_hand(), /obj/item/weapon/blade))//Sword check.
- U.drop_item()
- if(istype(U.get_inactive_hand(), /obj/item/weapon/blade))
- U.swap_hand()
- U.drop_item()
-
- U << "\blue Unsecuring external locking mechanism...\nNeural-net abolished.\nOperation status: FINISHED."
- return
-
-/obj/item/clothing/suit/space/space_ninja/proc/spideros()
- set name = "Display SpiderOS"
- set desc = "Utilize built-in computer system."
- set category = "Ninja Equip"
-
- if(!affecting) return//If no mob is wearing the suit. I almost forgot about this variable.
- var/mob/living/carbon/human/U = affecting
- var/dat = "SpiderOS"
- if(spideros==0)
- dat += "
Refresh"
- else
- dat += "
Refresh"
- dat += " |
Return"
- dat += " |
Close"
- dat += "
"
- dat += "SpiderOS v.1.337
"
- dat += "Welcome, [U.real_name].
"
- dat += "
"
- dat += "
Current Time: [round(world.time / 36000)+12]:[(world.time / 600 % 60) < 10 ? add_zero(world.time / 600 % 60, 1) : world.time / 600 % 60]
"
- dat += "
Battery Life: [round(cell.charge/100)]%
"
- dat += "
Smoke Bombs: [s_bombs]
"
- dat += "
"
-
- switch(spideros)
- if(0)
- dat += "
Available Functions:
"
- dat += ""
- if(1)
- dat += "
Medical Report:
"
- if(U.dna)
- dat += "Fingerprints: [md5(U.dna.uni_identity)]
"
- dat += "Unique identity: [U.dna.unique_enzymes]
"
- dat += "Overall Status: [U.stat > 1 ? "dead" : "[U.health]% healthy"]
"
- dat += "Nutrition Status: [U.nutrition]
"
- dat += "Oxygen loss: [U.oxyloss]"
- dat += " | Toxin levels: [U.toxloss]
"
- dat += "Burn severity: [U.fireloss]"
- dat += " | Brute trauma: [U.bruteloss]
"
- dat += "Body Temperature: [U.bodytemperature-T0C]°C ([U.bodytemperature*1.8-459.67]°F)
"
- if(U.virus)
- dat += "Warning Virus Detected. Name: [U.virus.name].Type: [U.virus.spread]. Stage: [U.virus.stage]/[U.virus.max_stages]. Possible Cure: [U.virus.cure].
"
- dat += ""
+ U.drop_item()//drop blade
+ else return 1
if(2)
- dat += "
Atmospheric Scan:
"//Headers don't need breaks. They are automatically placed.
- var/turf/T = get_turf_or_move(U.loc)
- if (isnull(T))
- dat += "Unable to obtain a reading."
- else
- var/datum/gas_mixture/environment = T.return_air()
-
- var/pressure = environment.return_pressure()
- var/total_moles = environment.total_moles()
-
- dat += "Air Pressure: [round(pressure,0.1)] kPa"
-
- if (total_moles)
- var/o2_level = environment.oxygen/total_moles
- var/n2_level = environment.nitrogen/total_moles
- var/co2_level = environment.carbon_dioxide/total_moles
- var/plasma_level = environment.toxins/total_moles
- var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level)
- dat += ""
- dat += "- Nitrogen: [round(n2_level*100)]%
"
- dat += "- Oxygen: [round(o2_level*100)]%
"
- dat += "- Carbon Dioxide: [round(co2_level*100)]%
"
- dat += "- Plasma: [round(plasma_level*100)]%
"
- dat += "
"
- if(unknown_level > 0.01)
- dat += "OTHER: [round(unknown_level)]%
"
-
- dat += "Temperature: [round(environment.temperature-T0C)]°C"
- if(3)
- if(k_unlock==7)
- dat += "
Hidden Menu"
- dat += "
Anonymous Messenger:
"//Anonymous because the receiver will not know the sender's identity.
- dat += "
Detected PDAs:
"
- dat += ""
- var/count = 0
- for (var/obj/item/device/pda/P in world)
- if (!P.owner||P.toff)
- continue
- dat += "- [P]"
- dat += "
"
- count++
- dat += "
"
- if (count == 0)
- dat += "None detected.
"
- if(32)
- dat += "
Hidden Menu:
"
- dat += "Please input password: "
- dat += "HERE
"
- dat += "
"
- dat += "Remember, you will not be able to recharge energy during this function. If energy runs out, the suit will auto self-destruct.
"
- dat += "Use with caution. De-initialize the suit when energy is low."
- if(4)
- dat += "
Ninja Manual:
"
- dat += "Who they are:
"
- dat += "Space ninjas are a special type of ninja, specifically one of the space-faring type. The vast majority of space ninjas belong to the Spider Clan, a cult-like sect, which has existed for several hundred years. The Spider Clan practice a sort of augmentation of human flesh in order to achieve a more perfect state of being and follow Postmodern Space Bushido. They also kill people for money. Their leaders are chosen from the oldest of the grand-masters, people that have lived a lot longer than any mortal man should.
Being a sect of technology-loving fanatics, the Spider Clan have the very best to choose from in terms of hardware--cybernetic implants, exoskeleton rigs, hyper-capacity batteries, and you get the idea. Some believe that much of the Spider Clan equipment is based on reverse-engineered alien technology while others doubt such claims.
Whatever the case, their technology is absolutely superb."
- dat += "How they relate to other SS13 organizations:
"
- dat += ""
- dat += "- *Nanotrasen and the Syndicate are two sides of the same coin and that coin is valuable.
"
- dat += "- *The Space Wizard Federation is a problem, mainly because they are an extremely dangerous group of unpredictable individuals--not to mention the wizards hate technology and are in direct opposition of the Spider Clan. Best avoided or left well-enough alone. How to battle: wizards possess several powerful abilities to steer clear off. Blind in particular is a nasty spell--jaunt away if you are blinded and never approach a wizard in melee. Stealth may also work if the wizard is not wearing thermal scanners--don't count on this. Run away if you feel threatened and await a better opportunity.
"
- dat += "- *Changeling Hivemind: extremely dangerous and to be killed on sight. How to battle: they will likely try to absorb you. Adrenaline boost, then phase shift into them. If you get stung, use SpiderOS to inject counter-agents. Stealth may also work but detecting a changeling is the real battle.
"
- dat += "- *Xeno Hivemind: their skulls make interesting kitchen decorations and are challenging to best, especially in larger nests. How to battle: they can see through your stealth guise and energy stars will not work on them. Best killed with a Phase Shift or at range. If you happen on a projectile stun weapon, use it and then close in to melee.
"
- dat += "
"
- dat += "The reason they (you) are here
:"
- dat += "Space ninjas are renowned throughout the known controlled space as fearless spies, infiltrators, and assassins. They are sent on missions of varying nature by Nanotrasen, the Syndicate, and other shady organizations and people. To hire a space ninja means serious business."
- dat += "Their playstyle:
"
- dat += "A mix of traitor, changeling, and wizard. Ninjas rely on energy, or electricity to be precise, to keep their suits running (when out of energy, a suit hibernates). Suits gain energy from objects or creatures that contain electrical charge. APCs, cell batteries, rechargers, SMES batteries, cyborgs, mechs, and exposed wires are currently supported. Through energy ninjas gain access to special powers--while all powers are tied to the ninja suit, the most useful of them are verb activated--to help them in their mission.
It is a constant struggle for a ninja to remain hidden long enough to recharge the suit and accomplish their objective; despite their arsenal of abilities, ninjas can die like any other. Unlike wizards, ninjas do not possess good crowd control and are typically forced to play more subdued in order to achieve their goals. Some of their abilities are specifically designed to confuse and disorient others.
With that said, it should be perfectly possible to completely flip the fuck out and rampage as a ninja."
- dat += "Their powers:
"
- dat += "There are two primary types: Equipment and Abilties. Passive effects are always on. Active effects must be turned on and remain active only when there is energy to do so. Ability costs are listed next to them."
- dat += "Equipment: cannot be tracked by AI (passive), faster speed (passive), stealth (active), vision switch (passive if toggled), voice masking (passive), SpiderOS (passive if toggled), energy drain (passive if toggled)."
- dat += ""
- dat += "- Voice masking generates a random name the ninja can use over the radio and in-person. Although, the former use is recommended.
"
- dat += "- Toggling vision cycles to one of the following: thermal, meson, or darkness vision. The starting mode allows one to scout the identity of those in view, revealing their role. Traitors, revolutionaries, wizards, and other such people will be made known to you.
"
- dat += "- Stealth, when activated, drains more battery charge and works similarly to a syndicate cloak. The cloak will deactivate when most Abilities are utilized.
"
- dat += "- On-board AI: The suit is able to download an AI much like an intelicard. Check with SpiderOS for details once downloaded.
"
- dat += "- SpiderOS is a specialized, PDA-like screen that allows for a small variety of functions, such as injecting healing chemicals directly from the suit. You are using it now, if that was not already obvious. You may also download AI modules directly to the OS.
"
- dat += "
"
- dat += "Abilities:"
- dat += ""
- dat += "- *Phase Shift (2000E) and Phase Jaunt (1000E) are unique powers in that they can both be used for defense and offense. Jaunt launches the ninja forward facing up to 9 squares, somewhat randomly selecting the final destination. Shift can only be used on turf in view but is precise (cannot be used on walls). Any living mob in the area teleported to is instantly gibbed (mechs are damaged, huggers and other similar critters are killed). It is possible to teleport with a target, provided you grab them before teleporting.
"
- dat += "- *Energy Blade (500E) is a highly effective weapon. It is summoned directly to the ninja's hand and can also function as an EMAG for certain objects (doors/lockers/etc). You may also use it to cut through walls and disabled doors. Experiment! The blade will crit humans in two hits. This item cannot be placed in containers and when dropped or thrown disappears. Having an energy blade drains more power from the battery each tick.
"
- dat += "- *EM Pulse (2500E) is a highly useful ability that will create an electromagnetic shockwave around the ninja, disabling technology whenever possible. If used properly it can render a security force effectively useless. Of course, getting beat up with a toolbox is not accounted for.
"
- dat += "- *Energy Star (300E) is a ninja star made of green energy AND coated in poison. It works by picking a random living target within range and can be spammed to great effect in incapacitating foes. Just remember that the poison used is also used by the Xeno Hivemind (and will have no effect on them).
"
- dat += "- *Energy Net (2000E) is a non-lethal solution to incapacitating humanoids. The net is made of non-harmful phase energy and will halt movement as long as it remains in effect--it can be destroyed. If the net is not destroyed, after a certain time it will teleport the target to a holding facility for the Spider Clan and then vanish. You will be notified if the net fails or succeeds in capturing a target in this manner. Combine with energy stars or stripping to ensure success. Abduction never looked this leet.
"
- dat += "- *Adrenaline Boost (1 E. Boost/3) recovers the user from stun, weakness, and paralysis. Also injects 20 units of radium into the bloodstream.
"
- dat += "- *Smoke Bomb (1 Sm.Bomb/10) is a weak but potentially useful ability. It creates harmful smoke and can be used in tandem with other powers to confuse enemies.
"
- dat += "- *???: unleash the True Ultimate Power!
"
- dat += "
IMPORTANT:
"
- dat += ""
- dat += "- *Make sure to toggle Special Interaction from the Ninja Equipment menu to interact differently with certain objects.
"
- dat += "- *Your starting power cell can be replaced if you find one with higher maximum energy capacity by clicking on the new cell with the same hand (super and hyper cells).
"
- dat += "- *Conserve your energy. Without it, you are very vulnerable.
"
- dat += "
"
- dat += "That is all you will need to know. The rest will come with practice and talent. Good luck!"
- dat += "Master /N
"
- if(5)
- var/laws
- dat += "
AI Control:
"
- var/mob/living/silicon/ai/A = AI
- if(AI)//If an AI exists, in case it gets purged while on this screen.
- dat += "Stored AI: [A.name]
"
- dat += "System integrity: [(A.health+100)/2]%
"
-
- for (var/index = 1, index <= A.laws.ion.len, index++)
- var/law = A.laws.ion[index]
- if (length(law) > 0)
- var/num = ionnum()
- laws += "- [num]. [law]
"
-
- //I personally think this makes things a little more fun. Ninjas can override all but law 0.
- //if (A.laws.zeroth)
- // laws += "- 0: [A.laws.zeroth]
"
-
- var/number = 1
- for (var/index = 1, index <= A.laws.inherent.len, index++)
- var/law = A.laws.inherent[index]
- if (length(law) > 0)
- laws += "- [number]: [law]
"
- number++
-
- for (var/index = 1, index <= A.laws.supplied.len, index++)
- var/law = A.laws.supplied[index]
- if (length(law) > 0)
- laws += "- [number]: [law]
"
- number++
-
- dat += "Laws:
"
-
- if (A.stat == 2)//If AI dies while inside the card, such as suiciding.
- killai(A)
- U << "Artificial Intelligence has self-terminated. Rebooting..."
- spideros()//Refresh.
- else
- if (!flush)
- dat += {"Purge AI
"}
- else
- dat += "Purge in progress...
"
- dat += {" [A.control_disabled ? "Enable" : "Disable"] Wireless Activity"}
- dat += ""
-
- U << browse(dat,"window=spideros;size=400x444;border=1;can_resize=0;can_close=0;can_minimize=0")
- //Setting the can>resize etc to 0 remove them from the drag bar but still allows the window to be draggable.
-
-/obj/item/clothing/suit/space/space_ninja/Topic(href, href_list)
- ..()
- var/mob/living/carbon/human/U = affecting
- if(s_control)//If the player is in control.
- if(!affecting||U.stat||!s_initialized)//Check to make sure the guy is wearing the suit after clicking and it's on.
- U << "\red Your suit must be worn and active to use this function."
- U << browse(null, "window=spideros")//Closes the window.
- return
-
- switch(k_unlock)//To unlock Kamikaze mode. Irrelevant elsewhere.
- if(0)
- if(href_list["choice"]=="Stealth"&&spideros==0) k_unlock++
- if(1)
- if(href_list["choice"]=="2"&&spideros==0) k_unlock++
- else if(href_list["choice"]=="Return")
- else k_unlock=0
- if(2)
- if(href_list["choice"]=="3"&&spideros==0) k_unlock++
- else if(href_list["choice"]=="Return")
- else k_unlock=0
- if(3)
- if(href_list["choice"]=="Stealth"&&spideros==0) k_unlock++
- else if(href_list["choice"]=="Return")
- else k_unlock=0
- if(4)
- if(href_list["choice"]=="1"&&spideros==0) k_unlock++
- else if(href_list["choice"]=="Return")
- else k_unlock=0
- if(5)
- if(href_list["choice"]=="1"&&spideros==0) k_unlock++
- else if(href_list["choice"]=="Return")
- else k_unlock=0
- if(6)
- if(href_list["choice"]=="4"&&spideros==0) k_unlock++
- else if(href_list["choice"]=="Return")
- else k_unlock=0
- if(7)//once unlocked, stays unlocked until deactivated.
- else
- k_unlock = 0
-
- switch(href_list["choice"])
- if("Close")
- U << browse(null, "window=spideros")
- return
- if("Refresh")//Refresh, goes to the end of the proc.
- if("Return")//Return
- if(spideros<=9)
- spideros=0
- else
- spideros = round(spideros/10)//Best way to do this, flooring to nearest integer. As an example, another way of doing it is attached below:
- // var/temp = num2text(spideros)
- // var/return_to = copytext(temp, 1, (length(temp)))//length has to be to the length of the thing because by default it's length+1
- // spideros = text2num(return_to)//Maximum length here is 6. Use (return_to, X) to specify larger strings if needed.
- if("Stealth")
- toggle_stealth()
-
- if("0")//Menus are numbers, see note above. 0 is the hub.
- spideros=0
- if("1")//Begin normal menus 1-9.
- spideros=1
- if("2")
- spideros=2
- if("3")
- spideros=3
- if("32")
- spideros=32
- if("4")
- spideros=4
- if("5")
- spideros=5
- if("Message")
- var/obj/item/device/pda/P = locate(href_list["target"])
- var/t = input(U, "Please enter untraceable message.") as text
- t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN)
- if(!t||U.stat||U.wear_suit!=src||!s_initialized)//Wow, another one of these. Man...
- U << browse(null, "window=spideros")
- return
- if(isnull(P)||P.toff)//So it doesn't freak out if the object no-longer exists.
- U << "\red Error: unable to deliver message."
- spideros()
- return
- P.tnote += "← From unknown source:
[t]
"
- if (!P.silent)
- playsound(P.loc, 'twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(3, P.loc))
- O.show_message(text("\icon[P] *[P.ttone]*"))
- P.overlays = null
- P.overlays += image('pda.dmi', "pda-r")
- if("Unlock Kamikaze")
- if(input(U)=="Divine Wind")
- if( !(U.stat||U.wear_suit!=src||!s_initialized||cell.charge<=1) )
- U << "\blue Engaging mode...\n\blackCODE NAME: \red KAMIKAZE"
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/spideros
- sleep(40)
- U << "\blue Re-routing power nodes... \nUnlocking limiter..."
- sleep(40)
- U << "\blue Power nodes re-routed. \nLimiter unlocked."
- sleep(10)
- U << "\red Do or Die, LET'S ROCK!!"
- if(verbs.Find(/obj/item/clothing/suit/space/space_ninja/proc/deinit))//To hopefully prevent engaging kamikaze and de-initializing at the same time.
- grant_kamikaze_verbs()
- if(U.gender==FEMALE)
- icon_state = "s-ninjakf"
- else
- icon_state = "s-ninjak"
- if(n_gloves)
- n_gloves.icon_state = "s-ninjak"
- n_gloves.item_state = "s-ninjak"
- n_gloves.candrain = 0
- n_gloves.draining = 0
- n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/drain_wire
- n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled
- U.update_clothing()
- ninjablade()
- message_admins("\blue [U.key] used KAMIKAZE mode.", 1)
- else
- U << "Nevermind, you cheater."
- U << browse(null, "window=spideros")
- return
- else
- U << "\red ERROR: WRONG PASSWORD!"
- k_unlock = 0
- spideros = 0
- //BEGIN MEDICAL//
- if("Dylovene")//These names really don't matter for specific functions but it's easier to use descriptive names.
- if(!reagents.get_reagent_amount("anti_toxin"))
- U << "\red Error: the suit cannot perform this function. Out of dylovene."
- else
- reagents.reaction(U, 2)
- reagents.trans_id_to(U, "anti_toxin", a_transfer)
- U << "You feel a tiny prick and a sudden rush of liquid in to your veins."
- if("Dexalin Plus")
- if(!reagents.get_reagent_amount("dexalinp"))
- U << "\red Error: the suit cannot perform this function. Out of dexalinp."
- else
- reagents.reaction(U, 2)
- reagents.trans_id_to(U, "dexalinp", a_transfer)
- U << "You feel a tiny prick and a sudden rush of liquid in to your veins."
- if("Tricordazine")
- if(!reagents.get_reagent_amount("tricordrazine"))
- U << "\red Error: the suit cannot perform this function. Out of tricordrazine."
- else
- reagents.reaction(U, 2)
- reagents.trans_id_to(U, "tricordrazine", a_transfer)
- U << "You feel a tiny prick and a sudden rush of liquid in to your veins."
- if("Spacelin")
- if(!reagents.get_reagent_amount("spaceacillin"))
- U << "\red Error: the suit cannot perform this function. Out of spaceacillin."
- else
- reagents.reaction(U, 2)
- reagents.trans_id_to(U, "spaceacillin", a_transfer)
- U << "You feel a tiny prick and a sudden rush of liquid in to your veins."
- if("Nutriment")
- if(!reagents.get_reagent_amount("nutriment"))
- U << "\red Error: the suit cannot perform this function. Out of nutriment."
- else
- reagents.reaction(U, 2)
- reagents.trans_id_to(U, "nutriment", 5)
- U << "You feel a tiny prick and a sudden rush of substance in to your veins."
- //BEGIN AI//
- if("Override Laws")
- var/mob/living/silicon/ai/A = locate(href_list["target"])
- var/law_zero = A.laws.zeroth//Remembers law zero, if there is one.
- A.laws = new /datum/ai_laws/ninja_override
- A.set_zeroth_law(law_zero)//Adds back law zero if there was one.
- A.show_laws()
- U << "\blue Law Override: SUCCESS."
- if("Purge AI")
- var/mob/living/silicon/ai/A = locate(href_list["target"])
- var/confirm = alert("Are you sure you want to purge the AI? This cannot be undone once started.", "Confirm purge", "Yes", "No")
- if(U.stat||U.wear_suit!=src||!s_initialized||!AI)
- U << browse(null, "window=spideros")
- return
- if(confirm == "Yes")
- if(A.laws.zeroth)//Gives a few seconds to re-upload the AI somewhere before it takes full control.
- A << "\red WARNING: \black purge procedure detected. \nNow hacking host..."
- U << "\red WARNING: HACKING ATT--TEMPT IN PR0GRESsS!"
- spideros = 0
- k_unlock = 0
- U << browse(null, "window=spideros")
- sleep(40)
- if(AI==A)
- A << "Disconnecting neural interface..."
- U << "\red WARNING: PRO0GRE--S 2&3%"
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/deinit
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/spideros
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/stealth
- sleep(40)
- if(AI==A)
- A << "Shutting down external protocol..."
- U << "\red WARNING: PPPFRRROGrESS 677^%"
- cancel_stealth()
- sleep(40)
- if(AI==A)
- A << "Connecting to kernel..."
- U << "\red WARNING: ER-RR04"
- A.control_disabled = 0
- sleep(40)
- A << "Connection established and secured. Menu updated."
- U << "\red WARNING: #%@!!WEL4P54@ \nUnABBBL3 TO LO-o-LOCAT2 ##$!ERNE0"
- grant_AI_verbs()
- return
- U << "\blue Hacking attempt disconnected. Resuming normal operation."
- remove_AI_verbs()
- else
- flush = 1
- A.suiciding = 1
- A << "Your core files are being purged! This is the end..."
- spawn(0)
- spideros()//To refresh the screen and let this finish.
- while (A.stat != 2)
- A.oxyloss += 2
- A.updatehealth()
- sleep(10)
- killai(A)
- flush = 0
- if("Wireless AI")
- var/mob/living/silicon/ai/A = locate(href_list["target"])
- A.control_disabled = !A.control_disabled
- A << "AI wireless has been [A.control_disabled ? "disabled" : "enabled"]."
-
- spideros()//Refreshes the screen by calling it again (which replaces current screen with new screen).
-
- else//If they are not in control.
- var/mob/living/silicon/ai/A = AI
- //While AI has control, the person can't take off the suit so checking here would be moot.
- if(isnull(src))//If they AI dies/suit destroyed.
- A << browse(null, "window=hack spideros")
- return
-
- switch(href_list["choice"])
- if("Close")
- A << browse(null, "window=hack spideros")
- return
- if("Refresh")//Refresh, goes to the end of the proc.
- if("Return")//Return
- if(spideros<=9)
- spideros=0
- else
- spideros = round(spideros/10)
- if("Shock")
- var/damage = min(cell.charge, rand(50,150))//Uses either the current energy left over or between 50 and 150.
- if(damage>1)//So they don't spam it when energy is a factor.
- spark_system.start()//SPARKS THERE SHALL BE SPARKS
- U.electrocute_act(damage, src,0.1,1)//The last argument is a safety for the human proc that checks for gloves.
- cell.charge -= damage
- else
- A << "\red ERROR: \black Not enough energy remaining."
- if("0")//Menus are numbers, see note above. 0 is the hub.
- spideros=0
- if("1")//Begin normal menus 1-9.
- spideros=1
- if("2")
- spideros=2
- if("3")
- spideros=3
- if("32")
- spideros=32
- if("4")
- spideros=4
- if("5")
- spideros=5
- if("Message")
- var/obj/item/device/pda/P = locate(href_list["target"])
- var/t = input(U, "Please enter untraceable message.") as text
- t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN)
- if(!t||affecting!=U||!s_initialized)//Wow, another one of these. Man...
- A << browse(null, "window=hack spideros")
- return
- if(isnull(P)||P.toff)//So it doesn't freak out if the object no-longer exists.
- A << "\red Error: unable to deliver message."
- hack_spideros()
- return
- P.tnote += "← From [A]:
[t]
"//Oh ai, u so silly
- if (!P.silent)
- playsound(P.loc, 'twobeep.ogg', 50, 1)
- for (var/mob/O in hearers(3, P.loc))
- O.show_message(text("\icon[P] *[P.ttone]*"))
- P.overlays = null
- P.overlays += image('pda.dmi', "pda-r")
- if("Unlock Kamikaze")
- A << "\red ERROR: \black TARANTULA.v.4.77.12 encryption algorithm detected. Unable to decrypt archive. \n Aborting..."
- //BEGIN MEDICAL//
- if("Dylovene")
- if(!reagents.get_reagent_amount("anti_toxin"))
- A << "\red Error: the suit cannot perform this function. Out of dylovene."
- else
- reagents.reaction(U, 2)
- reagents.trans_id_to(U, "anti_toxin", a_transfer)
- A << "Injecting..."
- U << "You feel a tiny prick and a sudden rush of liquid in to your veins."
- if("Dexalin Plus")
- if(!reagents.get_reagent_amount("dexalinp"))
- A << "\red Error: the suit cannot perform this function. Out of dexalinp."
- else
- reagents.reaction(U, 2)
- reagents.trans_id_to(U, "dexalinp", a_transfer)
- A << "Injecting..."
- U << "You feel a tiny prick and a sudden rush of liquid in to your veins."
- if("Tricordazine")
- if(!reagents.get_reagent_amount("tricordrazine"))
- A << "\red Error: the suit cannot perform this function. Out of tricordrazine."
- else
- reagents.reaction(U, 2)
- reagents.trans_id_to(U, "tricordrazine", a_transfer)
- A << "Injecting..."
- U << "You feel a tiny prick and a sudden rush of liquid in to your veins."
- if("Spacelin")
- if(!reagents.get_reagent_amount("spaceacillin"))
- A << "\red Error: the suit cannot perform this function. Out of spaceacillin."
- else
- reagents.reaction(U, 2)
- reagents.trans_id_to(U, "spaceacillin", a_transfer)
- A << "Injecting..."
- U << "You feel a tiny prick and a sudden rush of liquid in to your veins."
- if("Radium")
- if((reagents.get_reagent_amount("radium"))<=60)//Special case. If there are only 60 radium units left.
- A << "\red Error: the suit cannot perform this function. Out of radium."
- else
- reagents.reaction(U, 2)
- reagents.trans_id_to(U, "radium", a_transfer)
- A << "Injecting..."
- U << "You feel a tiny prick and a sudden rush of liquid in to your veins."
- if("Nutriment")
- if(!reagents.get_reagent_amount("nutriment"))
- A << "\red Error: the suit cannot perform this function. Out of nutriment."
- else
- reagents.reaction(U, 2)
- reagents.trans_id_to(U, "nutriment", 5)
- A << "Injecting..."
- U << "You feel a tiny prick and a sudden rush of substance in to your veins."
- //BEGIN ABILITIES//
- if("Phase Jaunt")
- A << "You trigger [href_list["choice"]]."
- U << "[href_list["choice"]] suddenly triggered!"
- ninjajaunt()
- if("Phase Shift")
- var/turfs[] = list()
- for(var/turf/T in oview(5,loc))
- turfs.Add(T)
- if(turfs.len)
- A << "You trigger [href_list["choice"]]."
- U << "[href_list["choice"]] suddenly triggered!"
- ninjashift(pick(turfs))
- else
- A << "There are no potential destinations in view."
- if("Energy Blade")
- A << "You trigger [href_list["choice"]]."
- U << "[href_list["choice"]] suddenly triggered!"
- ninjablade()
- if("Energy Star")
- A << "You trigger [href_list["choice"]]."
- U << "[href_list["choice"]] suddenly triggered!"
- ninjastar()
- if("Energy Net")
- var/targets[] = list()
- for(var/mob/living/carbon/M in oview(5,loc))
- targets.Add(M)
- if(targets.len)
- A << "You trigger [href_list["choice"]]."
- U << "[href_list["choice"]] suddenly triggered!"
- ninjanet(pick(targets))
- else
- A << "There are no potential targets in view."
- if("EM Pulse")
- A << "You trigger [href_list["choice"]]."
- U << "[href_list["choice"]] suddenly triggered!"
- ninjapulse()
- if("Smoke Bomb")
- A << "You trigger [href_list["choice"]]."
- U << "[href_list["choice"]] suddenly triggered!"
- ninjasmoke()
- if("Adrenaline Boost")
- A << "You trigger [href_list["choice"]]."
- U << "[href_list["choice"]] suddenly triggered!"
- ninjaboost()
-
- hack_spideros()
- return
+ if(istype(U.get_active_hand(), /obj/item/weapon/blade))
+ U.drop_item()
+ if(istype(U.get_inactive_hand(), /obj/item/weapon/blade))
+ U.swap_hand()
+ U.drop_item()
+ return 0
/obj/item/clothing/suit/space/space_ninja/examine()
set src in view()
@@ -889,54 +865,21 @@ ________________________________________________________________________________
if(s_control)
U << "All systems operational. Current energy capacity: [cell.charge]."
if(!kamikaze)
- if(s_active)
- U << "The CLOAK-tech device is active."
- else
- U << "The CLOAK-tech device is inactive."
+ U << "The CLOAK-tech device is [s_active?"active":"inactive"]."
else
U << "\red KAMIKAZE MODE ENGAGED!"
U << "There are [s_bombs] smoke bombs remaining."
U << "There are [a_boost] adrenaline boosters remaining."
else
- U << "ERR0R DATAA NoT FOUND 3RROR"
+ U << "ÈrrÖR Ða†Ða†Ä No-†-† fÖÚNÐ 3RRÖr"
-//GLOVES===================================
+/*
+===================================================================================
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+===================================================================================
+*/
-/obj/item/clothing/gloves/space_ninja/proc/toggled()
- set name = "Toggle Interaction"
- set desc = "Toggles special interaction on or off."
- set category = "Ninja Equip"
-
- var/mob/living/carbon/human/U = loc
- if(!candrain)
- candrain=1
- U << "You enable special interaction."
- else
- candrain=0
- U << "You disable special interaction."
-
-//DRAINING PROCS START===================================
-
-/obj/item/clothing/gloves/space_ninja/proc/drain_wire()
- set name = "Drain From Wire"
- set desc = "Drain energy directly from an exposed wire."
- set category = "Ninja Equip"
-
- var/obj/cable/attached
- var/mob/living/carbon/human/U = loc
- if(candrain&&!draining)
- var/turf/T = U.loc
- if(isturf(T) && T.is_plating())
- attached = locate() in T
- if(!attached)
- U << "\red Warning: no exposed cable available."
- else
- U << "\blue Connecting to wire, stand still..."
- if(do_after(U,50)&&!isnull(attached))
- drain("WIRE",attached,U:wear_suit,src)
- else
- U << "\red Procedure interrupted. Protocol terminated."
- return
+//=======//ENERGY DRAIN PROCS//=======//
/obj/item/clothing/gloves/space_ninja/proc/drain(target_type as text, target, obj/suit)
//Var Initialize
@@ -1157,19 +1100,29 @@ ________________________________________________________________________________
return
-//DRAINING PROCS END===================================
+//=======//GENERAL PROCS//=======//
+
+/obj/item/clothing/gloves/space_ninja/proc/toggled()
+ set name = "Toggle Interaction"
+ set desc = "Toggles special interaction on or off."
+ set category = "Ninja Equip"
+
+ var/mob/living/carbon/human/U = loc
+ U << "You [candrain?"disable":"enable"] special interaction."
+ candrain=!candrain
/obj/item/clothing/gloves/space_ninja/examine()
set src in view()
..()
if(!canremove)
var/mob/living/carbon/human/U = loc
- if(candrain)
- U << "The energy drain mechanism is: active."
- else
- U << "The energy drain mechanism is: inactive."
+ U << "The energy drain mechanism is: [candrain?"active":"inactive"]."
-//MASK===================================
+/*
+===================================================================================
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+===================================================================================
+*/
/obj/item/clothing/mask/gas/voice/space_ninja/New()
verbs += /obj/item/clothing/mask/gas/voice/space_ninja/proc/togglev
@@ -1260,7 +1213,7 @@ ________________________________________________________________________________
set desc = "Switches between Night Vision, Meson, or Thermal vision modes."
set category = "Ninja Equip"
//Have to reset these manually since life.dm is retarded like that. Go figure.
- //This will only work for humans since only they have the appropriate code for the mask.
+ //This will only work for humans because only they have the appropriate code for the mask.
var/mob/U = loc
switch(mode)
if(0)
@@ -1280,7 +1233,6 @@ ________________________________________________________________________________
U.sight &= ~SEE_TURFS
U << "Switching mode to Scouter."
-
/obj/item/clothing/mask/gas/voice/space_ninja/examine()
set src in view()
..()
@@ -1303,7 +1255,11 @@ ________________________________________________________________________________
usr << "[mode] is active."//Leaving usr here since it may be on the floor or on a person.
usr << "Voice mimicking algorithm is set to [voice]."
-//ENERGY NET===================================
+/*
+===================================================================================
+<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+===================================================================================
+*/
/*
HerpA:
@@ -1323,148 +1279,150 @@ The sprite for the net is kind of ugly but I couldn't come up with a better one.
opacity = 0//Can see through.
mouse_opacity = 1//So you can hit it with stuff.
anchored = 1//Can't drag/grab.
- var/health = 25//How much health it has.
- var/mob/living/affecting = null//Who it is currently affecting, if anyone.
- var/mob/living/master = null//Who shot web. Will let this person know if the net was successful or failed.
+ var
+ health = 25//How much health it has.
+ mob/living/affecting = null//Who it is currently affecting, if anyone.
+ mob/living/master = null//Who shot web. Will let this person know if the net was successful or failed.
-/obj/effects/energy_net/proc/healthcheck()
- if(health <=0)
- density = 0
- if(affecting)
- var/mob/living/carbon/M = affecting
- M.anchored = 0
- for(var/mob/O in viewers(src, 3))
- O.show_message(text("[] was recovered from the energy net!", M.name), 1, text("You hear a grunt."), 2)
- if(!isnull(master))//As long as they still exist.
- master << "\red ERROR: \black unable to initiate transport protocol. Procedure terminated."
- del(src)
- return
+ proc
+ healthcheck()
+ if(health <=0)
+ density = 0
+ if(affecting)
+ var/mob/living/carbon/M = affecting
+ M.anchored = 0
+ for(var/mob/O in viewers(src, 3))
+ O.show_message(text("[] was recovered from the energy net!", M.name), 1, text("You hear a grunt."), 2)
+ if(!isnull(master))//As long as they still exist.
+ master << "\red ERROR: \black unable to initiate transport protocol. Procedure terminated."
+ del(src)
+ return
-/obj/effects/energy_net/bullet_act(flag)
- switch(flag)
- if (PROJECTILE_BULLET)
- health -= 35
- if (PROJECTILE_PULSE)
- health -= 50
- if (PROJECTILE_LASER)
- health -= 10
- healthcheck()
- return
+ process(var/mob/living/carbon/M as mob)
+ var/check = 30//30 seconds before teleportation. Could be extended I guess.
+ //The person can still try and attack the net when inside.
+ while(!isnull(M)&&!isnull(src)&&check>0)//While M and net exist, and 30 seconds have not passed.
+ check--
+ sleep(10)
-/obj/effects/energy_net/ex_act(severity)
- switch(severity)
- if(1.0)
- health-=50
- if(2.0)
- health-=50
- if(3.0)
- if (prob(50))
+ if(isnull(M)||M.loc!=loc)//If mob is gone or not at the location.
+ if(!isnull(master))//As long as they still exist.
+ master << "\red ERROR: \black unable to locate [affecting]. Procedure terminated."
+ del(src)//Get rid of the net.
+ return
+
+ if(!isnull(src))//As long as both net and person exist.
+ //No need to check for countdown here since while() broke, it's implicit that it finished.
+ spawn(0)
+ playsound(M.loc, 'sparks4.ogg', 50, 1)
+ anim(M.loc,M,'mob.dmi',,"phaseout")
+
+ density = 0//Make the net pass-through.
+ invisibility = 101//Make the net invisible so all the animations can play out.
+ health = INFINITY//Make the net invincible so that an explosion/something else won't kill it while, spawn() is running.
+ M.loc = pick(prisonwarp)//Throw mob in prison.
+
+ spawn(0)
+ var/datum/effects/system/spark_spread/spark_system = new /datum/effects/system/spark_spread()
+ spark_system.set_up(5, 0, M.loc)
+ spark_system.start()
+ playsound(M.loc, 'Deconstruct.ogg', 50, 1)
+ playsound(M.loc, 'sparks2.ogg', 50, 1)
+ anim(M.loc,M,'mob.dmi',,"phasein")
+ del(src)//Wait for everything to finish, delete the net. Else it will stop everything once net is deleted, including the spawn(0).
+
+ for(var/mob/O in viewers(src, 3))
+ O.show_message(text("[] vanished!", M), 1, text("You hear sparks flying!"), 2)
+
+ if(!isnull(master))//As long as they still exist.
+ master << "\blue SUCCESS: \black transport procedure of [affecting] complete."
+
+ M.anchored = 0//Important.
+
+ else//And they are free.
+ M << "\blue You are free of the net!"
+ return
+
+ bullet_act(flag)
+ switch(flag)
+ if (PROJECTILE_BULLET)
+ health -= 35
+ if (PROJECTILE_PULSE)
+ health -= 50
+ if (PROJECTILE_LASER)
+ health -= 10
+ healthcheck()
+ return
+
+ ex_act(severity)
+ switch(severity)
+ if(1.0)
health-=50
- else
- health-=25
- healthcheck()
- return
+ if(2.0)
+ health-=50
+ if(3.0)
+ if (prob(50))
+ health-=50
+ else
+ health-=25
+ healthcheck()
+ return
-/obj/effects/energy_net/blob_act()
- health-=50
- healthcheck()
- return
-
-/obj/effects/energy_net/meteorhit()
- health-=50
- healthcheck()
- return
-
-/obj/effects/energy_net/hitby(AM as mob|obj)
- ..()
- for(var/mob/O in viewers(src, null))
- O.show_message(text("\red [src] was hit by [AM]."), 1)
- var/tforce = 0
- if(ismob(AM))
- tforce = 10
- else
- tforce = AM:throwforce
- playsound(src.loc, 'slash.ogg', 80, 1)
- health = max(0, health - tforce)
- healthcheck()
- ..()
- return
-
-/obj/effects/energy_net/attack_hand()
- if ((usr.mutations & HULK))
- usr << text("\blue You easily destroy the energy net.")
- for(var/mob/O in oviewers(src))
- O.show_message(text("\red [] rips the energy net apart!", usr), 1)
+ blob_act()
health-=50
- healthcheck()
- return
-
-/obj/effects/energy_net/attack_paw()
- return attack_hand()
-
-/obj/effects/energy_net/attack_alien()
- if (islarva(usr))
+ healthcheck()
return
- usr << text("\green You claw at the net.")
- for(var/mob/O in oviewers(src))
- O.show_message(text("\red [] claws at the energy net!", usr), 1)
- playsound(src.loc, 'slash.ogg', 80, 1)
- health -= rand(10, 20)
- if(health <= 0)
- usr << text("\green You slice the energy net to pieces.")
+
+ meteorhit()
+ health-=50
+ healthcheck()
+ return
+
+ hitby(AM as mob|obj)
+ ..()
+ for(var/mob/O in viewers(src, null))
+ O.show_message(text("\red [src] was hit by [AM]."), 1)
+ var/tforce = 0
+ if(ismob(AM))
+ tforce = 10
+ else
+ tforce = AM:throwforce
+ playsound(src.loc, 'slash.ogg', 80, 1)
+ health = max(0, health - tforce)
+ healthcheck()
+ ..()
+ return
+
+ attack_hand()
+ if ((usr.mutations & HULK))
+ usr << text("\blue You easily destroy the energy net.")
+ for(var/mob/O in oviewers(src))
+ O.show_message(text("\red [] rips the energy net apart!", usr), 1)
+ health-=50
+ healthcheck()
+ return
+
+ attack_paw()
+ return attack_hand()
+
+ attack_alien()
+ if (islarva(usr))
+ return
+ usr << text("\green You claw at the net.")
for(var/mob/O in oviewers(src))
- O.show_message(text("\red [] slices the energy net apart!", usr), 1)
- healthcheck()
- return
-
-/obj/effects/energy_net/attackby(obj/item/weapon/W as obj, mob/user as mob)
- var/aforce = W.force
- health = max(0, health - aforce)
- healthcheck()
- ..()
- return
-
-/obj/effects/energy_net/proc/process(var/mob/living/carbon/M as mob)
- var/check = 30//30 seconds before teleportation. Could be extended I guess.
- //The person can still try and attack the net when inside.
- while(!isnull(M)&&!isnull(src)&&check>0)//While M and net exist, and 30 seconds have not passed.
- check--
- sleep(10)
-
- if(isnull(M)||M.loc!=loc)//If mob is gone or not at the location.
- if(!isnull(master))//As long as they still exist.
- master << "\red ERROR: \black unable to locate [affecting]. Procedure terminated."
- del(src)//Get rid of the net.
+ O.show_message(text("\red [] claws at the energy net!", usr), 1)
+ playsound(src.loc, 'slash.ogg', 80, 1)
+ health -= rand(10, 20)
+ if(health <= 0)
+ usr << text("\green You slice the energy net to pieces.")
+ for(var/mob/O in oviewers(src))
+ O.show_message(text("\red [] slices the energy net apart!", usr), 1)
+ healthcheck()
return
- if(!isnull(src))//As long as both net and person exist.
- //No need to check for countdown here since while() broke, it's implicit that it finished.
- spawn(0)
- playsound(M.loc, 'sparks4.ogg', 50, 1)
- anim(M.loc,M,'mob.dmi',,"phaseout")
-
- density = 0//Make the net pass-through.
- invisibility = 101//Make the net invisible so all the animations can play out.
- health = INFINITY//Make the net invincible so that an explosion/something else won't kill it while, spawn() is running.
- M.loc = pick(prisonwarp)//Throw mob in prison.
-
- spawn(0)
- var/datum/effects/system/spark_spread/spark_system = new /datum/effects/system/spark_spread()
- spark_system.set_up(5, 0, M.loc)
- spark_system.start()
- playsound(M.loc, 'Deconstruct.ogg', 50, 1)
- playsound(M.loc, 'sparks2.ogg', 50, 1)
- anim(M.loc,M,'mob.dmi',,"phasein")
- del(src)//Wait for everything to finish, delete the net. Else it will stop everything once net is deleted, including the spawn(0).
-
- for(var/mob/O in viewers(src, 3))
- O.show_message(text("[] vanished!", M), 1, text("You hear sparks flying!"), 2)
-
- if(!isnull(master))//As long as they still exist.
- master << "\blue SUCCESS: \black transport procedure of [affecting] complete."
-
- M.anchored = 0//Important.
-
- else//And they are free.
- M << "\blue You are free of the net!"
- return
\ No newline at end of file
+ attackby(obj/item/weapon/W as obj, mob/user as mob)
+ var/aforce = W.force
+ health = max(0, health - aforce)
+ healthcheck()
+ ..()
+ return
\ No newline at end of file
diff --git a/code/game/gamemodes/extra/space_ninja.dm b/code/game/gamemodes/extra/space_ninja.dm
index 4a3efe76e2b..67124e96a97 100644
--- a/code/game/gamemodes/extra/space_ninja.dm
+++ b/code/game/gamemodes/extra/space_ninja.dm
@@ -1,12 +1,70 @@
/*
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-+++++++++++++++++++++++++++++++++++++// \\++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++// //++++++++++++++++++++++++++++++++++
======================================SPACE NINJA SETUP====================================
___________________________________________________________________________________________
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
-/proc/space_ninja_arrival()//This is the random event proc. WIP
+/*
+ README:
+
+ Data:
+
+ >> space_ninja.dm << is this file. It contains a variety of procs related to either spawning space ninjas,
+ modifying their verbs, various help procs, testing debug-related content, or storing unused procs for later.
+ Similar functions should go into this file, along with anything else that may not have an explicit category.
+ IMPORTANT: actual ninja suit, gloves, etc, are stored under the appropriate clothing files. If you need to change
+ variables or look them up, look there. Easiest way is through the map file browser.
+
+ >> ninja_abilities.dm << contains all the ninja-related powers. Spawning energy swords, teleporting, and the like.
+ If more powers are added, or perhaps something related to powers, it should go there. Make sure to describe
+ what an ability/power does so it's easier to reference later without looking at the code.
+ IMPORTANT: verbs are still somewhat funky to work with. If an argument is specified but is not referenced in a way
+ BYOND likes, in the code content, the verb will fail to trigger. Nothing will happen, literally, when clicked.
+ This can be bypassed by either referencing the argument properly, or linking to another proc with the argument
+ attached. The latter is what I like to do for certain cases--sometimes it's necessary to do that regardless.
+
+ >> ninja_equipment.dm << deals with all the equipment-related procs for a ninja. Primarily it has the suit, gloves,
+ and mask. The suit is by far the largest section of code out of the three and includes a lot of code that ties in
+ to other functions. This file has gotten kind of large so breaking it up may be in order. I use section hearders.
+ IMPORTANT: not much to say here. Follow along with the comments and adding new functions should be a breeze. Also
+ know that certain equipment pieces are linked in other files. The energy blade, for example, has special
+ functions defined in the appropriate files (airlock, securestorage, etc).
+
+ General Notes:
+
+ I created space ninjas with the expressed purpose of spicing up boring rounds. That is, ninjas are to xenos as marauders are to
+ death squads. Ninjas are stealthy, tech-savvy, and powerful. Not to say marauders are all of those things, but a clever ninja
+ should have little problem murderampaging their way through just about anything. Short of admin wizards maybe.
+ HOWEVER!
+ Ninjas also have a fairly great weakness as they require energy to use abilities. If, theoretically, there is a game
+ mode based around space ninjas, make sure to account for their energy needs.
+
+ Admin Notes:
+
+ Ninjas are meant for players to respawn as, not admins. They are another way to participate in the game post-death, like pais,
+ xenos, death squads, and cyborgs. Ninjas are not admin PCs--please do not use them for that purpose.
+ I'm currently looking for feedback from regular players since beta testing is largely done. I would appreciate if
+ you spawned regular players as ninjas when rounds are boring. Or exciting, it's all good as long as there is feedback.
+ Admin quick-spawning as ninjas is disabled for that reason. You can spawn ninja gear manually if you want to.
+
+ How to do that:
+ Make sure your character has a mind.
+ Change their assigned_role to "MODE", no quotes. Otherwise, the suit won't initialize.
+ Change their special_role to "Space Ninja", no quotes. Otherwise, the character will be gibbed.
+ Spawn ninja gear, put it on, hit initialize. Let the suit do the rest. You are now a space ninja.
+ I don't recommend messing with suit variables unless you really know what you're doing.
+
+ Miscellaneous Notes:
+
+ Right now I am focused on creating a dynamic objective tree based on round type, in order to create a ninja random event.
+ I'll update when possible.
+*/
+
+//=======//RANDOM EVENT//=======//
+
+/proc/space_ninja_arrival()
/*
var/datum/game_mode/current_mode = ticker.mode
switch (current_mode.config_tag)
@@ -34,7 +92,9 @@ ________________________________________________________________________________
*/
return
-/client/proc/space_ninja()//This is the admin button.
+//=======//ADMIN VERB//=======//
+
+/client/proc/space_ninja()
set category = "Fun"
set name = "Spawn Space Ninja"
set desc = "Spawns a space ninja for when you need a teenager with an attitude."
@@ -69,7 +129,7 @@ ________________________________________________________________________________
var/list/candidates = list()
for(G in world)
if(G.client&&!G.client.holder)
- //if(G.client)//Good for testing. Admins can spawn ninja equipment if they want to.
+ //if(G.client)//Good for testing.
if(((G.client.inactivity/10)/60) <= 5)
candidates.Add(G)
if(candidates.len)
@@ -85,6 +145,9 @@ ________________________________________________________________________________
new_ninja.internal = new_ninja.s_store //So the poor ninja has something to breath when they spawn in spess.
new_ninja.internals.icon_state = "internal1"
+ spawn(0)//Parallel process. Will speed things up a bit.
+ new_ninja.wear_suit:ninitialize(10,new_ninja)//If you're wondering why I'm passing the argument to the proc when the default should suffice,
+ //I'm also wondering that same thing. This makes sure it does not run time error though.
new_ninja.mind.store_memory("Mission: \red [input].")
new_ninja << "\blue \nYou are an elite mercenary assassin of the Spider Clan, [new_ninja.real_name]. The dreaded \red SPACE NINJA!\blue You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor. Remember your training (initialize your suit by right clicking on it)! \nYour current mission is: \red [input]"
@@ -92,6 +155,8 @@ ________________________________________________________________________________
message_admins("\blue [admin_name] has spawned [new_ninja.key] as a Space Ninja. Hide yo children!", 1)
log_admin("[admin_name] used Spawn Space Ninja.")
+//=======//NINJA CREATION PROCS//=======//
+
client/proc/create_space_ninja(obj/spawn_point)
var/mob/living/carbon/human/new_ninja = new(spawn_point.loc)
var/ninja_title = pick(ninja_titles)
@@ -126,7 +191,93 @@ client/proc/create_space_ninja(obj/spawn_point)
resistances += "alien_embryo"
return 1
-//VERB MODIFIERS===================================
+//=======//HELPER PROCS//=======//
+
+//Randomizes suit parameters.
+/obj/item/clothing/suit/space/space_ninja/proc/randomize_param()
+ s_cost = rand(1,20)
+ s_acost = rand(20,100)
+ k_cost = rand(100,500)
+ k_damage = rand(1,20)
+ 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/U, X = 0)
+ if(X)//If you want to check for icons.
+ if(U.gender==FEMALE)
+ icon_state = "s-ninjanf"
+ else
+ icon_state = "s-ninjan"
+ U:gloves.icon_state = "s-ninjan"
+ U:gloves.item_state = "s-ninjan"
+ else
+ if(U.mind.special_role!="Space Ninja")
+ U << "\red fÄTaL ÈÈRRoR: 382200-*#00CÖDE RED\nUNAU†HORIZED USÈ DETÈC†††eD\nCoMMÈNCING SUB-R0U†IN3 13...\nTÈRMInATING U-U-USÈR..."
+ U.gib()
+ return 0
+ if(!istype(U:head, /obj/item/clothing/head/helmet/space/space_ninja))
+ U << "\red ERROR: 100113 \black UNABLE TO LOCATE HEAD GEAR\nABORTING..."
+ return 0
+ if(!istype(U:shoes, /obj/item/clothing/shoes/space_ninja))
+ U << "\red ERROR: 122011 \black UNABLE TO LOCATE FOOT GEAR\nABORTING..."
+ return 0
+ if(!istype(U:gloves, /obj/item/clothing/gloves/space_ninja))
+ U << "\red ERROR: 110223 \black UNABLE TO LOCATE HAND GEAR\nABORTING..."
+ return 0
+
+ affecting = U
+ canremove = 0
+ slowdown = 0
+ n_hood = U:head
+ n_hood.canremove=0
+ n_shoes = U:shoes
+ n_shoes.canremove=0
+ n_shoes.slowdown--
+ n_gloves = U:gloves
+ n_gloves.canremove=0
+
+ return 1
+
+//This proc allows the suit to be taken off.
+/obj/item/clothing/suit/space/space_ninja/proc/unlock_suit()
+ affecting = null
+ canremove = 1
+ slowdown = 1
+ icon_state = "s-ninja"
+ if(n_hood)//Should be attached, might not be attached.
+ n_hood.canremove=1
+ if(n_shoes)
+ n_shoes.canremove=1
+ n_shoes.slowdown++
+ if(n_gloves)
+ n_gloves.icon_state = "s-ninja"
+ n_gloves.item_state = "s-ninja"
+ n_gloves.canremove=1
+ n_gloves.candrain=0
+ n_gloves.draining=0
+
+//=======//GENERIC VERB MODIFIERS//=======//
+
+/obj/item/clothing/suit/space/space_ninja/proc/grant_equip_verbs()
+ verbs -= /obj/item/clothing/suit/space/space_ninja/proc/init
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/spideros
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/stealth
+ n_gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/toggled
+
+ s_initialized = 1
+
+/obj/item/clothing/suit/space/space_ninja/proc/remove_equip_verbs()
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/init
+ verbs -= /obj/item/clothing/suit/space/space_ninja/proc/deinit
+ verbs -= /obj/item/clothing/suit/space/space_ninja/proc/spideros
+ verbs -= /obj/item/clothing/suit/space/space_ninja/proc/stealth
+ if(n_gloves)
+ n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled
+
+ s_initialized = 0
/obj/item/clothing/suit/space/space_ninja/proc/grant_ninja_verbs()
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjashift
@@ -151,7 +302,9 @@ client/proc/create_space_ninja(obj/spawn_point)
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjastar
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjanet
-/obj/item/clothing/suit/space/space_ninja/proc/grant_kamikaze_verbs()
+//=======//KAMIKAZE VERBS//=======//
+
+/obj/item/clothing/suit/space/space_ninja/proc/grant_kamikaze(mob/living/carbon/U)
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjashift
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjapulse
@@ -165,245 +318,85 @@ client/proc/create_space_ninja(obj/spawn_point)
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/stealth
kamikaze = 1
+
+ if(U.gender==FEMALE)
+ icon_state = "s-ninjakf"
+ else
+ icon_state = "s-ninjak"
+ if(n_gloves)
+ n_gloves.icon_state = "s-ninjak"
+ n_gloves.item_state = "s-ninjak"
+ n_gloves.candrain = 0
+ n_gloves.draining = 0
+ n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled
+
cancel_stealth()
-/obj/item/clothing/suit/space/space_ninja/proc/remove_kamikaze_verbs()
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjashift
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjapulse
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjastar
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjanet
+ U << browse(null, "window=spideros")
+ U << "\red Do or Die, LET'S ROCK!!"
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjaslayer
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjawalk
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjamirage
+/obj/item/clothing/suit/space/space_ninja/proc/remove_kamikaze(mob/living/carbon/U)
+ if(kamikaze)
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjashift
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjajaunt
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjapulse
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjastar
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/ninjanet
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/stealth
+ verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjaslayer
+ verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjawalk
+ verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ninjamirage
- kamikaze = 0
- k_unlock = 0
+ verbs += /obj/item/clothing/suit/space/space_ninja/proc/stealth
+ if(n_gloves)
+ n_gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled
+
+ U.incorporeal_move = 0
+ U.density = 1
+ kamikaze = 0
+ k_unlock = 0
+ U << "\blue Disengaging mode...\n\blackCODE NAME: \red KAMIKAZE"
+
+//=======//AI VERBS//=======//
/obj/item/clothing/suit/space/space_ninja/proc/grant_AI_verbs()
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ai_hack_ninja
verbs += /obj/item/clothing/suit/space/space_ninja/proc/ai_return_control
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/deinit
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/spideros
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/stealth
+ s_busy = 0
s_control = 0
/obj/item/clothing/suit/space/space_ninja/proc/remove_AI_verbs()
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ai_hack_ninja
verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ai_return_control
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/spideros
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/stealth
s_control = 1
-//AI COUNTER HACKING/SPECIAL FUNCTIONS===================================
-
-/obj/item/clothing/suit/space/space_ninja/proc/ai_holo(var/turf/T in oview(3,affecting))//To have an internal AI display a hologram to the ninja only.
- set name = "Display Hologram"
- set desc = "Channel a holographic image directly to the user's field of vision. Others will not see it."
- set category = null
- set src = usr.loc
-
- if(s_initialized&&affecting&&affecting.client&&istype(affecting.loc, /turf))//If the host exists and they are playing, and their location is a turf.
- if(!hologram)//If there is not already a hologram.
- hologram = new(T)//Spawn a blank effect at the location.
- hologram.invisibility = 101//So that it doesn't show up, ever. This also means one could attach a number of images to a single obj and display them to differently to differnet people.
- hologram.dir = get_dir_to(T,affecting.loc)
- var/image/I = image('mob.dmi',hologram,"ai-holo")//Attach an image to object.
- hologram.i_attached = I//To attach the image in order to later reference.
- AI << I
- affecting << I
- affecting << "An image flicks to life nearby. It appears visible to you only."
-
- verbs += /obj/item/clothing/suit/space/space_ninja/proc/ai_holo_clear
-
- ai_holo_process()//Move to initialize
- else
- AI << "\red ERROR: \black Image feed in progress."
- else
- AI << "\red ERROR: \black Unable to project image."
- return
-
-/obj/item/clothing/suit/space/space_ninja/proc/ai_holo_process()
- set background = 1
-
- spawn while(hologram&&s_initialized&&AI)//Suit on and there is an AI present.
- if(!s_initialized||get_dist(affecting,hologram.loc)>3)//Once suit is de-initialized or hologram reaches out of bounds.
- del(hologram.i_attached)
- del(hologram)
-
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ai_holo_clear
- return
- sleep(10)//Checks every second.
-
-/obj/item/clothing/suit/space/space_ninja/proc/ai_instruction()//Let's the AI know what they can do.
- set name = "Instructions"
- set desc = "Displays a list of helpful information."
- set category = "AI Ninja Equip"
- set src = usr.loc
-
- AI << "The menu you are seeing will contain other commands if they become available.\nRight click a nearby turf to display an AI Hologram. It will only be visible to you and your host. You can move it freely using normal movement keys--it will disappear if placed too far away."
-
-/obj/item/clothing/suit/space/space_ninja/proc/ai_holo_clear()
- set name = "Clear Hologram"
- set desc = "Stops projecting the current holographic image."
- set category = "AI Ninja Equip"
- set src = usr.loc
-
- del(hologram.i_attached)
- del(hologram)
-
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ai_holo_clear
- return
-
-/obj/item/clothing/suit/space/space_ninja/proc/ai_hack_ninja()
- set name = "Hack SpiderOS"
- set desc = "Hack directly into the Black Widow(tm) neuro-interface."
- set category = "AI Ninja Equip"
- set src = usr.loc
-
- hack_spideros()
- return
-
-/obj/item/clothing/suit/space/space_ninja/proc/ai_return_control()
- set name = "Relinquish Control"
- set desc = "Return control to the user."
- set category = "AI Ninja Equip"
- set src = usr.loc
-
- AI << browse(null, "window=hack spideros")//Close window
- AI << "You have seized your hacking attempt. [affecting] has regained control."
- affecting << "UPDATE: [AI.real_name] has ceased hacking attempt. All systems clear."
-
- verbs -= /obj/item/clothing/suit/space/space_ninja/proc/ai_return_control
- return
-
-/obj/item/clothing/suit/space/space_ninja/proc/hack_spideros()
-
- if(!affecting||!AI) return//Just in case... something went wrong. Very wrong.
- var/mob/living/carbon/human/U = affecting
- var/mob/living/silicon/ai/A = AI
-
- var/dat = "SpiderOS"
- if(spideros==0)
- dat += "
Refresh"
- else
- dat += "
Refresh"
- dat += " |
Return"
- dat += " |
Close"
- dat += "
"
- dat += "SpiderOS v.ERR-RR00123
"
- dat += "
"
- dat += "
Current Time: [round(world.time / 36000)+12]:[(world.time / 600 % 60) < 10 ? add_zero(world.time / 600 % 60, 1) : world.time / 600 % 60]
"
- dat += "
Battery Life: [round(cell.charge/100)]%
"
- dat += "
Smoke Bombs: [s_bombs]
"
- dat += "
"
-
- switch(spideros)
- if(0)
- dat += "
Available Functions:
"
- dat += ""
- if(1)
- dat += "
Medical Report:
"
- if(U.dna)
- dat += "Fingerprints: [md5(U.dna.uni_identity)]
"
- dat += "Unique identity: [U.dna.unique_enzymes]
"
- dat += "Overall Status: [U.stat > 1 ? "dead" : "[U.health]% healthy"]
"
- dat += "Nutrition Status: [U.nutrition]
"
- dat += "Oxygen loss: [U.oxyloss]"
- dat += " | Toxin levels: [U.toxloss]
"
- dat += "Burn severity: [U.fireloss]"
- dat += " | Brute trauma: [U.bruteloss]
"
- dat += "Body Temperature: [U.bodytemperature-T0C]°C ([U.bodytemperature*1.8-459.67]°F)
"
- if(U.virus)
- dat += "Warning Virus Detected. Name: [U.virus.name].Type: [U.virus.spread]. Stage: [U.virus.stage]/[U.virus.max_stages]. Possible Cure: [U.virus.cure].
"
- dat += ""
- if(2)
- dat += "
Atmospheric Scan:
"
- var/turf/T = get_turf_or_move(U.loc)
- if (isnull(T))
- dat += "Unable to obtain a reading."
- else
- var/datum/gas_mixture/environment = T.return_air()
-
- var/pressure = environment.return_pressure()
- var/total_moles = environment.total_moles()
-
- dat += "Air Pressure: [round(pressure,0.1)] kPa"
-
- if (total_moles)
- var/o2_level = environment.oxygen/total_moles
- var/n2_level = environment.nitrogen/total_moles
- var/co2_level = environment.carbon_dioxide/total_moles
- var/plasma_level = environment.toxins/total_moles
- var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level)
- dat += ""
- dat += "- Nitrogen: [round(n2_level*100)]%
"
- dat += "- Oxygen: [round(o2_level*100)]%
"
- dat += "- Carbon Dioxide: [round(co2_level*100)]%
"
- dat += "- Plasma: [round(plasma_level*100)]%
"
- dat += "
"
- if(unknown_level > 0.01)
- dat += "OTHER: [round(unknown_level)]%
"
-
- dat += "Temperature: [round(environment.temperature-T0C)]°C"
- if(3)
- dat += "
Hidden Menu"
- dat += "
Anonymous Messenger:
"//Anonymous because the receiver will not know the sender's identity.
- dat += "
Detected PDAs:
"
- dat += ""
- var/count = 0
- for (var/obj/item/device/pda/P in world)
- if (!P.owner||P.toff)
- continue
- dat += "- [P]"
- dat += "
"
- count++
- dat += "
"
- if (count == 0)
- dat += "None detected.
"
- if(32)//Only leaving this in for funnays. CAN'T LET YOU DO THAT STAR FOX
- dat += "
Hidden Menu:
"
- dat += "Hostile runtime intrusion detected: operation locked. The Spider Clan is watching you, INTRUDER."
- if(4)
- dat += "
Activate Abilities:
"
- dat += ""
-
- dat += ""
-
- A << browse(dat,"window=hack spideros;size=400x444;border=1;can_resize=0;can_close=0;can_minimize=0")
-
-
-//OLD & UNUSED===================================
+//=======//OLD & UNUSED//=======//
/*
+//Old way of draining from wire.
+/obj/item/clothing/gloves/space_ninja/proc/drain_wire()
+ set name = "Drain From Wire"
+ set desc = "Drain energy directly from an exposed wire."
+ set category = "Ninja Equip"
+
+ var/obj/cable/attached
+ var/mob/living/carbon/human/U = loc
+ if(candrain&&!draining)
+ var/turf/T = U.loc
+ if(isturf(T) && T.is_plating())
+ attached = locate() in T
+ if(!attached)
+ U << "\red Warning: no exposed cable available."
+ else
+ U << "\blue Connecting to wire, stand still..."
+ if(do_after(U,50)&&!isnull(attached))
+ drain("WIRE",attached,U:wear_suit,src)
+ else
+ U << "\red Procedure interrupted. Protocol terminated."
+ return
+
I've tried a lot of stuff but adding verbs to the AI while inside an object, inside another object, did not want to work properly.
This was the best work-around I could come up with at the time. Uses objects to then display to panel, based on the object spell system.
Can be added on to pretty easily.
@@ -493,7 +486,7 @@ BYOND fixed the verb bugs so this is no longer necessary. I prefer verb panels.
return
*/
-//DEBUG===================================
+//=======//DEBUG//=======//
/*
Most of these are at various points of incomplete.
diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm
index d814f96f572..9e2721bd5be 100644
--- a/code/game/gamemodes/malfunction/malfunction.dm
+++ b/code/game/gamemodes/malfunction/malfunction.dm
@@ -66,6 +66,9 @@
AI_mind.current << "When you feel you have enough APCs under your control, you may begin the takeover attempt."
AI_mind.current.verbs += /datum/game_mode/malfunction/proc/takeover
AI_mind.current.icon_state = "ai-malf"
+ spawn(10)
+ if(alert(AI_mind.current,"Do you want to use an alternative sprite for your real core?",,"Yes","No")=="Yes")
+ AI_mind.current.icon_state = "ai-malf2"
spawn (rand(waittime_l, waittime_h))
send_intercept()
diff --git a/code/game/machinery/computer/AIcore.dm b/code/game/machinery/computer/AIcore.dm
index ef6430c5f87..ed0f13110af 100644
--- a/code/game/machinery/computer/AIcore.dm
+++ b/code/game/machinery/computer/AIcore.dm
@@ -165,8 +165,11 @@
user << "\red ERROR: \black Remote access channel disabled."
return
-//This is a good place for AI-related object verbs so I'm sticking it here.
-
+/*
+This is a good place for AI-related object verbs so I'm sticking it here.
+If adding stuff to this, don't forget that an AI need to cancel_camera() whenever it physically moves to a different location.
+That prevents a few funky behaviors.
+*/
//What operation to perform based on target, what ineraction to perform based on object used, target itself, user. The object used is src and calls this proc.
/obj/item/proc/transfer_ai(var/choice as text, var/interaction as text, var/target, var/mob/U as mob)
if(!src:flush)
@@ -194,6 +197,7 @@
C.icon_state = "aicard-404"
else
C.icon_state = "aicard-full"
+ T.cancel_camera()
T << "You have been downloaded to a mobile storage device. Remote device connection severed."
U << "\blue Transfer successful: \black [T.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
if("NINJASUIT")
@@ -215,6 +219,7 @@
T.control_disabled = 1
T.loc = C
C.AI = T
+ T.cancel_camera()
T << "You have been downloaded to a mobile storage device. Remote device connection severed."
U << "\blue Transfer successful: \black [T.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
@@ -227,11 +232,12 @@
if(A)//If AI exists on the card. Else nothing since both are empty.
A.control_disabled = 0
A.loc = T.loc//To replace the terminal.
- A << "You have been uploaded to a stationary terminal. Remote device connection restored."
- U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed."
C.icon_state = "aicard"
C.name = "inteliCard"
C.overlays = null
+ A.cancel_camera()
+ A << "You have been uploaded to a stationary terminal. Remote device connection restored."
+ U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed."
del(T)
if("NINJASUIT")
var/obj/item/clothing/suit/space/space_ninja/C = src
@@ -240,6 +246,7 @@
A.control_disabled = 0
C.AI = null
A.loc = T.loc
+ A.cancel_camera()
A << "You have been uploaded to a stationary terminal. Remote device connection restored."
U << "\blue Transfer succesful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed."
del(T)
@@ -252,8 +259,6 @@
if (!C.contents.len)
U << "No AI to copy over!"//Well duh
else for(var/mob/living/silicon/ai/A in C)
- A << "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here."
- U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed."
C.icon_state = "aicard"
C.name = "inteliCard"
C.overlays = null
@@ -265,6 +270,9 @@
else
T.overlays += image('computer.dmi', "ai-fixer-full")
T.overlays -= image('computer.dmi', "ai-fixer-empty")
+ A.cancel_camera()
+ A << "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here."
+ U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed."
else
if(!C.contents.len && T.occupant && !T.active)
C.name = "inteliCard - [T.occupant.name]"
@@ -278,6 +286,7 @@
T.occupant << "You have been downloaded to a mobile storage device. Still no remote access."
U << "\blue Transfer succesful: \black [T.occupant.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
T.occupant.loc = C
+ T.occupant.cancel_camera()
T.occupant = null
else if (C.contents.len)
U << "\red ERROR: \black Artificial intelligence detected on terminal."
@@ -292,14 +301,15 @@
U << "No AI to copy over!"
else
var/mob/living/silicon/ai/A = C.AI
- A << "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here."
- U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed."
A.loc = T
T.occupant = A
C.AI = null
A.control_disabled = 1
T.overlays += image('computer.dmi', "ai-fixer-full")
T.overlays -= image('computer.dmi', "ai-fixer-empty")
+ A.cancel_camera()
+ A << "You have been uploaded to a stationary terminal. Sadly, there is no remote access from here."
+ U << "\blue Transfer successful: \black [A.name] ([rand(1000,9999)].exe) installed and executed succesfully. Local copy has been removed."
else
if(!C.AI && T.occupant && !T.active)
if (T.occupant.stat)
@@ -310,6 +320,7 @@
T.occupant << "You have been downloaded to a mobile storage device. Still no remote access."
U << "\blue Transfer successful: \black [T.occupant.name] ([rand(1000,9999)].exe) removed from host terminal and stored within local memory."
T.occupant.loc = C
+ T.occupant.cancel_camera()
T.occupant = null
else if (C.AI)
U << "\red ERROR: \black Artificial intelligence detected on terminal."
@@ -335,6 +346,7 @@
C.name = "inteliCard - [A.name]"
C.icon_state = "aicard-full"
T.AI = null
+ A.cancel_camera()
A << "You have been uploaded to a mobile storage device."
U << "\blue SUCCESS: \black [A.name] ([rand(1000,9999)].exe) removed from host and stored within local memory."
else//If host AI is empty.
@@ -347,6 +359,7 @@
C.name = "inteliCard"
C.overlays = null
T.AI = A_T
+ A_T.cancel_camera()
A_T << "You have been uploaded to a mobile storage device."
U << "\blue SUCCESS: \black [A_T.name] ([rand(1000,9999)].exe) removed from local memory and installed to host."
else if(A_T)//If the target AI is dead. Else just go to return since nothing would happen if both are empty.
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 2d8608299ed..59b72426c2b 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -57,6 +57,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
hologram.icon = 'mob.dmi'
hologram.icon_state = "ai-holo"
hologram.mouse_opacity = 0//So you can't click on it.
+ hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
hologram.sd_SetLuminosity(1)//To make it glowy.
sd_SetLuminosity(1)//To make the pad glowy.
icon_state = "holopad1"
diff --git a/code/game/objects/devices/PDA/PDA.dm b/code/game/objects/devices/PDA/PDA.dm
index 78043141c0f..132af41699d 100644
--- a/code/game/objects/devices/PDA/PDA.dm
+++ b/code/game/objects/devices/PDA/PDA.dm
@@ -300,7 +300,7 @@
..()
var/mob/living/U = usr
//Looking for master was kind of pointless since PDAs don't appear to have one.
- if (U.contents.Find(src) || (istype(loc, /turf) && get_dist(src, U) <= 1))
+ if ( U.contents.Find(src) || ( istype(loc, /turf) && in_range(src, U) ) )
if ( !(U.stat || U.restrained()) )
add_fingerprint(U)
@@ -627,7 +627,7 @@
var/input=alert("Would you like to inert the card or update owner information?",,"Insert","Update")
//Basic safety check. If either both objects are held by user or PDA is on ground and card is in hand.
- if ( (user.contents.Find(src) && user.contents.Find(C)) || (istype(loc, /turf) && get_dist(src, user) <= 1 && user.contents.Find(C)) )
+ if ( (user.contents.Find(src) && user.contents.Find(C)) || (istype(loc, /turf) && in_range(src, user) && user.contents.Find(C)) )
if ( !(user.stat || user.restrained()) )//If they can still act.
if(input=="Insert")
id_check(user, 2)
diff --git a/code/game/objects/devices/aicard.dm b/code/game/objects/devices/aicard.dm
index 34153c584da..c514a77cbb3 100644
--- a/code/game/objects/devices/aicard.dm
+++ b/code/game/objects/devices/aicard.dm
@@ -63,35 +63,52 @@
dat += "AI nonfunctional"
else
if (!src.flush)
- dat += {"Wipe AI"}
+ dat += {"Wipe AI"}
else
dat += "Wipe in progress"
- dat += {"[A.control_disabled ? "Enable" : "Disable"] Wireless Activity"}
dat += "
"
- dat += {" Close"}
+ dat += {"[A.control_disabled ? "Enable" : "Disable"] Wireless Activity"}
+ dat += "
"
+ dat += {" Close"}
user << browse(dat, "window=aicard")
onclose(user, "aicard")
return
Topic(href, href_list)
- switch(href_list["choice"])
+ /*Let's define the user. It's safer to do it this way, rather than defaulting to usr.
+ For very long menu lines, usr is probably a lot more convenient.*/
+ var/mob/U = href_list["user"]
+ if (!in_range(src, U)||U.machine!=src)//If they are not in range of 1 or less or their machine is not the card (ie, clicked on something else).
+ U << browse(null, "window=aicard")
+ U.machine = null
+ return
+
+ add_fingerprint(U)
+ U.machine = src
+
+ switch(href_list["choice"])//Now we switch based on choice.
if ("Close")
- usr << browse(null, "window=aicard")
- usr.machine = null
+ U << browse(null, "window=aicard")
+ U.machine = null
return
if ("Wipe")
var/confirm = alert("Are you sure you want to wipe this card's memory? This cannot be undone once started.", "Confirm Wipe", "Yes", "No")
if(confirm == "Yes")
- flush = 1
- for(var/mob/living/silicon/ai/A in src)
- A.suiciding = 1
- A << "Your core files are being wiped!"
- while (A.stat != 2)
- A.oxyloss += 2
- A.updatehealth()
- sleep(10)
- flush = 0
+ if(isnull(src)||!in_range(src, U)||U.machine!=src)
+ U << browse(null, "window=aicard")
+ U.machine = null
+ return
+ else
+ flush = 1
+ for(var/mob/living/silicon/ai/A in src)
+ A.suiciding = 1
+ A << "Your core files are being wiped!"
+ while (A.stat != 2)
+ A.oxyloss += 2
+ A.updatehealth()
+ sleep(10)
+ flush = 0
if ("Wireless")
for(var/mob/living/silicon/ai/A in src)
@@ -101,7 +118,7 @@
overlays -= image('pda.dmi', "aicard-on")
else
overlays += image('pda.dmi', "aicard-on")
- attack_self(usr)
+ attack_self(U)
diff --git a/code/game/objects/devices/paicard.dm b/code/game/objects/devices/paicard.dm
index 2ae71b91854..1fc18e7ea7a 100644
--- a/code/game/objects/devices/paicard.dm
+++ b/code/game/objects/devices/paicard.dm
@@ -47,6 +47,7 @@
return
Topic(href, href_list)
+
if(href_list["setdna"])
if(pai.master_dna)
return
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 1b956db2312..f15d0d5f197 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -46,9 +46,12 @@ mob/new_player
preferences.lastchangelog = lastchangelog
preferences.savefile_save(src)
//PDA Resource Initialisation =======================================================>
-
-
- if (client) //load the PDA iconset into the client
+ /*
+ Quick note: local dream daemon instances don't seem to cache images right. Might be
+ a local problem with my machine but it's annoying nontheless.
+ */
+ if (client)
+ //load the PDA iconset into the client
src << browse_rsc('pda_atmos.png')
src << browse_rsc('pda_back.png')
src << browse_rsc('pda_bell.png')
@@ -87,9 +90,9 @@ mob/new_player
src << browse_rsc('sos_11.png')
src << browse_rsc('sos_12.png')
src << browse_rsc('sos_13.png')
+ src << browse_rsc('sos_14.png')
//End PDA Resource Initialisation =====================================================>
-
Logout()
ready = 0
..()
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index b10d616eb64..9388a8eda3e 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -102,6 +102,12 @@
PN = powernets[netnum]
return PN
+/obj/cable/attack_hand(mob/user)
+ if(ishuman(user))
+ if(istype(user:gloves, /obj/item/clothing/gloves/space_ninja)&&user:gloves:candrain&&!user:gloves:draining)
+ call(/obj/item/clothing/gloves/space_ninja/proc/drain)("WIRE",src,user:wear_suit)
+ return
+
/obj/cable/attackby(obj/item/W, mob/user)
var/turf/T = src.loc
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index 72f43059fef..9a2b07a01f8 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/spideros_icons/sos_14.png b/icons/spideros_icons/sos_14.png
new file mode 100644
index 00000000000..9d90684d8c6
Binary files /dev/null and b/icons/spideros_icons/sos_14.png differ
diff --git a/tgstation.dme b/tgstation.dme
index 2f405705b7e..adce7ff486b 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -54,7 +54,6 @@
#define FILE_DIR "code/game/machinery/pipe"
#define FILE_DIR "code/game/magic"
#define FILE_DIR "code/game/magic/cultist"
-#define FILE_DIR "code/game/magic/playerpower"
#define FILE_DIR "code/game/mecha"
#define FILE_DIR "code/game/mecha/combat"
#define FILE_DIR "code/game/mecha/equipment"
@@ -148,7 +147,6 @@
#define DEBUG
// END_PREFERENCES
// BEGIN_INCLUDE
-#include
#include "code\names.dm"
#include "code\setup.dm"
#include "code\stylesheet.dm"