diff --git a/code/defines/obj/clothing/suit.dm b/code/defines/obj/clothing/suit.dm index f82e1d1a97f..0e416139aa3 100644 --- a/code/defines/obj/clothing/suit.dm +++ b/code/defines/obj/clothing/suit.dm @@ -377,7 +377,7 @@ var/charge = 9000.0//Starts at 90% of normal capacity. var/maxcharge = 30000.0//I want the suit upgradable if the ninja is able to find the parts but for now this'll do. var/initialize = 0//Suit starts off. - var/spideros = 0//Mode of SpiderOS. This can change so I won't bother listing the modes here (0 is hub). Check clothing.dm for how it all works. + var/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. var/unlock = 0 var/sbombs = 10.0//Number of starting ninja smoke bombs. var/aboost = 3.0//Number of adrenaline boosters. diff --git a/code/game/gamemodes/extra/ninja_abilities.dm b/code/game/gamemodes/extra/ninja_abilities.dm new file mode 100644 index 00000000000..1df647d1218 --- /dev/null +++ b/code/game/gamemodes/extra/ninja_abilities.dm @@ -0,0 +1,460 @@ +//ABILITIES============================= + +/*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. +*/ +/mob/proc/ninjacost(var/C as num,var/X as num) + var/mob/living/carbon/human/U = src + var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit + if(U.stat||U.incorporeal_move) + U << "\red You must be conscious and solid to do this." + return 0 + else if(C&&S.charge[S.sbombs] smoke bombs remaining." + var/datum/effects/system/bad_smoke_spread/smoke = new /datum/effects/system/bad_smoke_spread() + smoke.set_up(10, 0, loc) + smoke.start() + playsound(loc, 'bamf.ogg', 50, 2) + return + +//9-10 Tile Teleport +//Click to to teleport 9-10 tiles in direction facing. +/mob/proc/ninjajaunt() + set name = "Phase Jaunt" + set desc = "Utilizes the internal VOID-shift device to rapidly transit in direction facing." + set category = "Ninja" + + var/C = 100 + if(ninjacost(C,1)) + var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit + var/list/turfs = new/list() + var/turf/picked + var/turf/mobloc = get_turf(loc) + var/safety = 0 +/* switch(dir)//This can be done better but really isn't worth it in my opinion. + if(NORTH) + //highest Y + //X the same + for(var/turf/T in orange(10)) + if(T.density) continue + if(T.x>world.maxx || T.x<1) continue + if(T.y>world.maxy || T.y<1) continue + if((T.y-mobloc.y)<9 || ((T.x+mobloc.x+1)-(mobloc.x*2))>2) continue + turfs += T + if(SOUTH) + //lowest Y + //X the same + for(var/turf/T in orange(10)) + if(T.density) continue + if(T.x>world.maxx || T.x<1) continue + if(T.y>world.maxy || T.y<1) continue + if((mobloc.y-T.y)<9 || ((T.x+mobloc.x+1)-(mobloc.x*2))>2) continue + turfs += T + if(EAST) + //highest X + //Y the same + for(var/turf/T in orange(10)) + if(T.density) continue + if(T.x>world.maxx || T.x<1) continue + if(T.y>world.maxy || T.y<1) continue + if((T.x-mobloc.x)<9 || ((T.y+mobloc.y+1)-(mobloc.y*2))>2) continue + turfs += T + if(WEST) + //lowest X + //Y the same + for(var/turf/T in orange(10)) + if(T.density) continue + if(T.x>world.maxx || T.x<1) continue + if(T.y>world.maxy || T.y<1) continue + if((mobloc.x-T.x)<9 || ((T.y+mobloc.y+1)-(mobloc.y*2))>2) continue + turfs += T + else + safety = 1*/ + var/locx + var/locy + switch(dir)//Gets rectengular range for target. + if(NORTH) + locx = mobloc.x + locy = (mobloc.y+9) + for(var/turf/T in block(locate(locx-3,locy-1,loc.z), locate(locx+3,locy+1,loc.z) )) + if(T.density) continue + if(T.x>world.maxx || T.x<1) continue + if(T.y>world.maxy || T.y<1) continue + turfs += T + if(SOUTH) + locx = mobloc.x + locy = (mobloc.y-9) + for(var/turf/T in block(locate(locx-3,locy-1,loc.z), locate(locx+3,locy+1,loc.z) )) + if(T.density) continue + if(T.x>world.maxx || T.x<1) continue + if(T.y>world.maxy || T.y<1) continue + turfs += T + if(EAST) + locy = mobloc.y + locx = (mobloc.x+9) + for(var/turf/T in block(locate(locx-1,locy-3,loc.z), locate(locx+1,locy+3,loc.z) )) + if(T.density) continue + if(T.x>world.maxx || T.x<1) continue + if(T.y>world.maxy || T.y<1) continue + turfs += T + if(WEST) + locy = mobloc.y + locx = (mobloc.x-9) + for(var/turf/T in block(locate(locx-1,locy-3,loc.z), locate(locx+1,locy+3,loc.z) )) + if(T.density) continue + if(T.x>world.maxx || T.x<1) continue + if(T.y>world.maxy || T.y<1) continue + turfs += T + else safety = 1 + + if(turfs.len&&!safety)//Cancels the teleportation if no valid turf is found. Usually when teleporting near map edge. + picked = pick(turfs) + spawn(0) + playsound(loc, "sparks", 50, 1) + anim(mobloc,'mob.dmi',src,"phaseout") + + loc = picked + + spawn(0) + S.spark_system.start() + playsound(loc, 'Deconstruct.ogg', 50, 1) + playsound(loc, "sparks", 50, 1) + anim(loc,'mob.dmi',src,"phasein") + + spawn(0)//Any living mobs in teleport area are gibbed. + for(var/mob/living/M in picked) + if(M==src) continue + M.gib() + S.charge-=(C*10) + else + src << "\red The VOID-shift device is malfunctioning, teleportation failed." + return + +//Right Click Teleport +//Right click to teleport somewhere, almost exactly like admin jump to turf. +/mob/proc/ninjashift(var/turf/T in oview()) + set name = "Phase Shift" + set desc = "Utilizes the internal VOID-shift device to rapidly transit to a destination in view." + set category = null//So it does not show up on the panel but can still be right-clicked. + + var/C = 200 + if(ninjacost(C,1)) + var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit + if(!T.density) + var/turf/mobloc = get_turf(loc) + spawn(0) + playsound(loc, 'sparks4.ogg', 50, 1) + anim(mobloc,'mob.dmi',src,"phaseout") + + loc = T + + spawn(0) + S.spark_system.start() + playsound(loc, 'Deconstruct.ogg', 50, 1) + playsound(loc, 'sparks2.ogg', 50, 1) + anim(loc,'mob.dmi',src,"phasein") + + spawn(0)//Any living mobs in teleport area are gibbed. + for(var/mob/living/M in T) + if(M==src) continue + M.gib() + S.charge-=(C*10) + else + src << "\red You cannot teleport into solid walls." + return + +//EMP Pulse +//Disables nearby tech equipment. +/mob/proc/ninjapulse() + set name = "EM Burst" + set desc = "Disable any nearby technology with a electro-magnetic pulse." + set category = "Ninja" + + var/C = 250 + if(ninjacost(C,1)) + var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit + playsound(loc, 'EMPulse.ogg', 60, 2) + empulse(src, 4, 6) //Procs sure are nice. Slightly weaker than wizard's disable tch. + S.charge-=(C*10) + return + +//Summon Energy Blade +//Summons a blade of energy in active hand. +/mob/proc/ninjablade() + set name = "Energy Blade" + set desc = "Create a focused beam of energy in your active hand." + set category = "Ninja" + + var/C = 50 + if(ninjacost(C)) + var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit + if(!S.kamikaze) + if(!get_active_hand()&&!istype(get_inactive_hand(), /obj/item/weapon/blade)) + var/obj/item/weapon/blade/W = new() + W.spark_system.start() + playsound(loc, "sparks", 50, 1) + put_in_hand(W) + S.charge-=(C*10) + else + src << "\red You can only summon one blade. Try dropping an item first." + else//Else you can run around with TWO energy blades. I don't know why you'd want to but cool factor remains. + if(!get_active_hand()) + var/obj/item/weapon/blade/W = new() + put_in_hand(W) + if(!get_inactive_hand()) + var/obj/item/weapon/blade/W = new() + put_in_inactive_hand(W) + S.spark_system.start() + playsound(loc, "sparks", 50, 1) + return + +//Shoot Ninja Stars +//Shoots ninja stars at random people. +//This could be a lot better but I'm too tired atm. +/mob/proc/ninjastar() + set name = "Energy Star" + set desc = "Launches an energy star at a random living target." + set category = "Ninja" + + var/C = 30 + if(ninjacost(C)) + var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit + var/targets[]//So yo can shoot while yo throw dawg + targets = new() + for(var/mob/living/M in oview(7)) + if(M.stat==2) continue//Doesn't target corpses. + targets.Add(M) + if(targets.len) + var/mob/living/target=pick(targets)//The point here is to pick a random, living mob in oview to shoot stuff at. + + var/turf/curloc = loc + var/atom/targloc = get_turf(target) + if (!targloc || !istype(targloc, /turf) || !curloc) + return + if (targloc == curloc) + return + var/obj/bullet/neurodart/A = new /obj/bullet/neurodart(loc) + A.current = curloc + A.yo = targloc.y - curloc.y + A.xo = targloc.x - curloc.x + S.charge-=(C*10) + A.process() + else + src << "\red There are no targets in view." + 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. +/mob/proc/ninjaboost() + set name = "Adrenaline Boost" + set desc = "Inject a secret chemical that will counteract all movement-impairing effects." + set category = "Ninja" + + if(ninjacost(,3)) + var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit + //Wouldn't need to track adrenaline boosters if there was a miracle injection to get rid of paralysis and the like instantly. + //For now, adrenaline boosters ARE the miracle injection. Well, radium, really. + paralysis = 0 + stunned = 0 + weakened = 0 + spawn(30) + say(pick("A CORNERED FOX IS MORE DANGEROUS THAN A JACKAL!","HURT ME MOOORRREEE!","IMPRESSIVE!")) + spawn(70) + S.reagents.reaction(src, 2) + S.reagents.trans_id_to(src, "radium", S.amount_per_transfer_from_this) + src << "\red You are beginning to feal the after-effects of the injection." + S.aboost-- + return + +//KAMIKAZE============================= +//Or otherwise known as anime mode. Which also happens to be ridiculously powerful. + +//Allows for incorporeal movement. +//Also makes you move like you're on crack. +/mob/proc/ninjawalk() + set name = "Shadow Walk" + set desc = "Combines the VOID-shift and CLOAK-tech devices to freely move between solid matter. Toggle on or off." + set category = "Ninja" + + if(!usr.incorporeal_move) + incorporeal_move = 1 + density = 0 + src << "\blue You will now phase through solid matter." + else + incorporeal_move = 0 + density = 1 + src << "\blue You will no-longer phase through solid matter." + return + +/* +Added click-spam protection of 1 second. +Allows to gib up to five squares in a straight line. Seriously.*/ +/mob/proc/ninjaslayer() + set name = "Phase Slayer" + set desc = "Utilizes the internal VOID-shift device to mutilate creatures in a straight line." + set category = "Ninja" + + if(ninjacost()) + var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit + var/locx + var/locy + var/turf/mobloc = get_turf(loc) + var/safety = 0 + + switch(dir) + if(NORTH) + locx = mobloc.x + locy = (mobloc.y+5) + if(locy>world.maxy) + safety = 1 + if(SOUTH) + locx = mobloc.x + locy = (mobloc.y-5) + if(locy<1) + safety = 1 + if(EAST) + locy = mobloc.y + locx = (mobloc.x+5) + if(locx>world.maxx) + safety = 1 + if(WEST) + locy = mobloc.y + locx = (mobloc.x-5) + if(locx<1) + safety = 1 + else safety = 1 + if(!safety)//Cancels the teleportation if no valid turf is found. Usually when teleporting near map edge. + say("Ai Satsugai!") + verbs -= /mob/proc/ninjaslayer + var/turf/picked = locate(locx,locy,mobloc.z) + spawn(0) + playsound(loc, "sparks", 50, 1) + anim(mobloc,'mob.dmi',src,"phaseout") + + spawn(0) + for(var/turf/T in getline(mobloc, picked)) + spawn(0) + for(var/mob/living/M in T) + if(M==src) continue + spawn(0) + M.gib() + if(T==mobloc||T==picked) continue + spawn(0) + anim(T,'mob.dmi',src,"phasein") + + loc = picked + + spawn(0) + S.spark_system.start() + playsound(loc, 'Deconstruct.ogg', 50, 1) + playsound(loc, "sparks", 50, 1) + anim(loc,'mob.dmi',src,"phasein") + spawn(10) + verbs += /mob/proc/ninjaslayer + else + src << "\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. +/mob/proc/ninjamirage() + set name = "Spider Mirage" + set desc = "Utilizes the internal VOID-shift device to create decoys and teleport behind a random target." + set category = "Ninja" + + if(ninjacost())//Simply checks for stat. + var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit + var/targets[] + targets = new() + for(var/mob/living/M in oview(6)) + if(M.stat==2) continue//Doesn't target corpses. + targets.Add(M) + if(targets.len) + var/mob/living/target=pick(targets) + var/locx + var/locy + var/turf/mobloc = get_turf(target.loc) + var/safety = 0 + switch(target.dir) + if(NORTH) + locx = mobloc.x + locy = (mobloc.y-1) + if(locy<1) + safety = 1 + if(SOUTH) + locx = mobloc.x + locy = (mobloc.y+1) + if(locy>world.maxy) + safety = 1 + if(EAST) + locy = mobloc.y + locx = (mobloc.x-1) + if(locx<1) + safety = 1 + if(WEST) + locy = mobloc.y + locx = (mobloc.x+1) + if(locx>world.maxx) + safety = 1 + else safety=1 + + if(!safety) + say("Kumo no Shinkiro!") + verbs -= /mob/proc/ninjamirage + var/turf/picked = locate(locx,locy,mobloc.z) + spawn(0) + playsound(loc, "sparks", 50, 1) + anim(mobloc,'mob.dmi',src,"phaseout") + + spawn(0) + var/limit = 4 + for(var/turf/T in oview(5)) + if(prob(20)) + spawn(0) + anim(T,'mob.dmi',src,"phasein") + limit-- + if(limit<=0) break + + loc = picked + dir = target.dir + + spawn(0) + S.spark_system.start() + playsound(loc, 'Deconstruct.ogg', 50, 1) + playsound(loc, "sparks", 50, 1) + anim(loc,'mob.dmi',src,"phasein") + + spawn(10) + verbs += /mob/proc/ninjamirage + else + src << "\red The VOID-shift device is malfunctioning, teleportation failed." + else + src << "\red There are no targets in view." + return \ No newline at end of file diff --git a/code/game/gamemodes/extra/ninja_equipment.dm b/code/game/gamemodes/extra/ninja_equipment.dm new file mode 100644 index 00000000000..a69ac54a254 --- /dev/null +++ b/code/game/gamemodes/extra/ninja_equipment.dm @@ -0,0 +1,915 @@ +//===================================SPESS NINJA STUFF=================================== + +//SUIT=================================== + +/obj/item/clothing/suit/space/space_ninja/New() + ..() + src.verbs += /obj/item/clothing/suit/space/space_ninja/proc/init//suit initialize verb + 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(480)//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", 80) + reagents.add_reagent("nutriment", 80) + +/obj/item/clothing/suit/space/space_ninja/proc/ntick(var/mob/living/carbon/human/U as mob) + set hidden = 1 + set background = 1 + + spawn while(initialize&&charge>=0)//Suit on and has power. + if(!initialize) return//When turned off the proc stops. + var/A = 5//Energy cost each tick. + if(!kamikaze) + if(istype(U.get_active_hand(), /obj/item/weapon/blade))//Sword check. + if(charge<=0)//If no charge left. + U.drop_item()//Sword is dropped from active hand (and deleted). + else A += 20//Otherwise, more energy consumption. + else if(istype(U.get_inactive_hand(), /obj/item/weapon/blade)) + if(charge<=0) + U.swap_hand()//swap hand + U.drop_item()//drop sword + else A += 20 + if(active) + A += 25 + else + if(prob(25)) + U.bruteloss += 1 + A = 200 + charge-=A + if(charge<0) + if(kamikaze) + U.say("I DIE TO LIVE AGAIN!") + U.death() + return + charge=0 + active=0 + 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 = "Object" + + if(usr.mind&&usr.mind.special_role=="Space Ninja"&&usr:wear_suit==src&&!src.initialize) + var/mob/living/carbon/human/U = usr + 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." + U.head:canremove=0 + U.shoes:canremove=0 + U.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 + 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: [src.charge]." + sleep(40) + U << "\blue All systems operational. Welcome to SpiderOS, [U.real_name]." + U.verbs += /mob/proc/ninjashift + U.verbs += /mob/proc/ninjajaunt + U.verbs += /mob/proc/ninjasmoke + U.verbs += /mob/proc/ninjaboost + U.verbs += /mob/proc/ninjapulse + U.verbs += /mob/proc/ninjablade + U.verbs += /mob/proc/ninjastar + U.mind.special_verbs += /mob/proc/ninjashift + U.mind.special_verbs += /mob/proc/ninjajaunt + U.mind.special_verbs += /mob/proc/ninjasmoke + U.mind.special_verbs += /mob/proc/ninjaboost + U.mind.special_verbs += /mob/proc/ninjapulse + U.mind.special_verbs += /mob/proc/ninjablade + U.mind.special_verbs += /mob/proc/ninjastar + verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit + verbs += /obj/item/clothing/suit/space/space_ninja/proc/spideros + U.gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/drain_wire + U.gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/toggled + initialize=1 + affecting=U + slowdown=0 + U.shoes:slowdown-- + ntick(usr) + else + if(usr.mind&&usr.mind.special_role=="Space Ninja") + usr << "\red You do not understand how this suit functions." + else if(usr:wear_suit!=src) + usr << "\red You must be wearing the suit to use this function." + else if(initialize) + usr << "\red The suit is already functioning." + else + usr << "\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 = "Object" + + if(!initialize) + usr << "\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 + + var/mob/living/carbon/human/U = usr + 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" + U.verbs -= /mob/proc/ninjaslayer + U.verbs -= /mob/proc/ninjawalk + U.verbs -= /mob/proc/ninjamirage + U.mind.special_verbs -= /mob/proc/ninjaslayer + U.mind.special_verbs -= /mob/proc/ninjawalk + U.mind.special_verbs -= /mob/proc/ninjamirage + kamikaze = 0 + unlock = 0 + U.incorporeal_move = 0 + U.density = 1 + icon_state = "s-ninja" + spideros = 0 + sleep(40) + U.verbs -= /mob/proc/ninjashift + U.verbs -= /mob/proc/ninjajaunt + U.verbs -= /mob/proc/ninjasmoke + U.verbs -= /mob/proc/ninjaboost + U.verbs -= /mob/proc/ninjapulse + U.verbs -= /mob/proc/ninjablade + U.verbs -= /mob/proc/ninjastar + U.mind.special_verbs -= /mob/proc/ninjashift + U.mind.special_verbs -= /mob/proc/ninjajaunt + U.mind.special_verbs -= /mob/proc/ninjasmoke + U.mind.special_verbs -= /mob/proc/ninjaboost + U.mind.special_verbs -= /mob/proc/ninjapulse + U.mind.special_verbs -= /mob/proc/ninjablade + U.mind.special_verbs -= /mob/proc/ninjastar + 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(active)//Shutdowns stealth. + active=0 + 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(istype(U.head, /obj/item/clothing/head/helmet/space/space_ninja)) + U.head.canremove=1 + if(istype(U.shoes, /obj/item/clothing/shoes/space_ninja)) + U.shoes:canremove=1 + U.shoes:slowdown++ + if(istype(U.gloves, /obj/item/clothing/gloves/space_ninja)) + U.gloves.icon_state = "s-ninja" + U.gloves.item_state = "s-ninja" + U.gloves:canremove=1 + U.gloves:candrain=0 + U.gloves:draining=0 + U.gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/drain_wire + U.gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled + 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() + canremove=1 + U << "\blue Unsecuring external locking mechanism...\nNeural-net abolished.\nOperation status: FINISHED." + verbs += /obj/item/clothing/suit/space/space_ninja/proc/init + initialize=0 + affecting=null + slowdown=1 + return + +/obj/item/clothing/suit/space/space_ninja/proc/spideros() + set name = "Display SpiderOS" + set desc = "Utilize built-in computer system." + set category = "Object" + + var/mob/living/carbon/human/U = usr + var/dat = "SpiderOS" + /*Here is where you would create a link for the cartridge used if the item has one. + As noted below, it's not worth the effort to make the cartridge removable unless it's done from the hub.*/ + 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(charge/100)]%
" + dat += " Smoke Bombs: [sbombs]
" + dat += "
" + + /* + HOW TO USE OR ADAPT THIS CODE: + The menu structure should not need to be altered to add new entries. Simply place them after what is already there. + As an exception, if there are multiple-tiered windows, for instance, going into medical alerts and then to DNA testing or something, + those menus should be added below their parents but have a greater value. The second sub-menu of menu 2 would have the number 22. + Another sub-menu of menu 2 would be 23, then 24, and up to 29. If those menus have their own sub-menus a similar format follows. + Sub-menu 1 of sub-menu 2(of menu 2) would be 221. Sub-menu 5 of sub-menu 2(of menu 2) would be 225. Menu 0 is a special case (it's the menu hub); you are free to use menus 1-9 (sub menus can be 0-9) + to create your own data paths. + The Return button, when used, simply removes the final number and navigates to the menu prior. Menu 334, the fourth sub-menu of sub-menu + 3, in menu 3, would navigate to sub menu 3 in menu 3. Or 33. + It is possible to go to a different menu/sub-menu from anywhere. When creating new menus don't forget to add them to Topic proc or else the game + will interpret you using the messenger function (the else clause in the switch). + Other buttons and functions should be named according to what they do.*/ + switch(spideros) + if(0) + /* + For items that use cartridges (PDAs), simply switch() their hub function based on the cartridge inserted. + For ease of use, allow the removal of the cartidge only on the hub. + */ + 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:

"//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 += "" + if(unknown_level > 0.01) + dat += "OTHER: [round(unknown_level)]%
" + + dat += "Temperature: [round(environment.temperature-T0C)]°C" + if(3) + if(unlock==7) + dat += " Hidden Menu" + dat += "

Anonymous Messenger:

"//Anonymous because the receiver will not know the sender's identity. + dat += "

Detected PDAs:

" + dat += "" + if (count == 0) + dat += "None detected.
" + //dat += " Send Virus + 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 += "
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, 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: powers that are activated through the suit and powers that are activated through the verb panel. Passive powers are always on. Active powers must be turned on and remain active only when there is energy to do so. All verb powers are active and their cost is listed next to them." + dat += "Powers of the suit: 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 += "Verbpowers:" + dat += "" + dat += "That is all you will need to know. The rest will come with practice and talent. Good luck!" + dat += "

Master /N

" +/* + //Sub-menu testing stuff. + dat += "
  • To sub-menu 49
  • " + if(31) + dat += "

    Send Virus:

    " + dat += "

    Detected PDAs:

    " + dat += "" + if (count == 0) + dat += "None detected.
    " + if(49) + dat += "

    Other Functions 49:

    " + dat += " To sub-menu 491" + if(491) + dat += "

    Other Functions 491:

    " + dat += " To main menu" +*/ + 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 = usr + if(U.stat||U.wear_suit!=src||!initialize)//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(unlock)//To unlock Kamikaze mode. Irrelevant elsewhere. + if(0) + if(href_list["choice"]=="Stealth"&&spideros==0) unlock++ + if(1) + if(href_list["choice"]=="2"&&spideros==0) unlock++ + else if(href_list["choice"]=="Return") + else unlock=0 + if(2) + if(href_list["choice"]=="3"&&spideros==0) unlock++ + else if(href_list["choice"]=="Return") + else unlock=0 + if(3) + if(href_list["choice"]=="Stealth"&&spideros==0) unlock++ + else if(href_list["choice"]=="Return") + else unlock=0 + if(4) + if(href_list["choice"]=="1"&&spideros==0) unlock++ + else if(href_list["choice"]=="Return") + else unlock=0 + if(5) + if(href_list["choice"]=="1"&&spideros==0) unlock++ + else if(href_list["choice"]=="Return") + else unlock=0 + if(6) + if(href_list["choice"]=="4"&&spideros==0) unlock++ + else if(href_list["choice"]=="Return") + else unlock=0 + if(7)//once unlocked, stays unlocked until deactivated. + else + 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") + if(active) + spawn(0) + anim(usr.loc,'mob.dmi',usr,"uncloak") + active=0 + U << "\blue You are now visible." + for(var/mob/O in oviewers(usr, null)) + O << "[usr.name] appears from thin air!" + else + spawn(0) + anim(usr.loc,'mob.dmi',usr,"cloak") + active=1 + U << "\blue You are now invisible to normal detection." + for(var/mob/O in oviewers(usr, null)) + O << "[usr.name] vanishes into thin air!" + 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 + /*Sub-menu testing stuff. + if("31") + spideros=31 + if("49") + spideros=49 + if("491") + spideros=491 */ + if("Unlock Kamikaze") + if(input(U)=="Divine Wind") + if( !(U.stat||U.wear_suit!=src||!initialize) ) + U << "\blue Engaging mode...\n\blackCODE NAME: \red KAMIKAZE" + 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. + kamikaze = 1 + active = 0 + icon_state = "s-ninjak" + if(istype(U.gloves, /obj/item/clothing/gloves/space_ninja)) + U.gloves.icon_state = "s-ninjak" + U.gloves.item_state = "s-ninjak" + U.gloves:candrain = 0 + U.gloves:draining = 0 + U.gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/drain_wire + U.gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled + U.update_clothing() + U.verbs -= /mob/proc/ninjashift + U.verbs -= /mob/proc/ninjajaunt + U.verbs -= /mob/proc/ninjapulse + U.verbs -= /mob/proc/ninjastar + U.mind.special_verbs -= /mob/proc/ninjashift + U.mind.special_verbs -= /mob/proc/ninjajaunt + U.mind.special_verbs -= /mob/proc/ninjapulse + U.mind.special_verbs -= /mob/proc/ninjastar + U.verbs += /mob/proc/ninjaslayer + U.verbs += /mob/proc/ninjawalk + U.verbs += /mob/proc/ninjamirage + U.mind.special_verbs += /mob/proc/ninjaslayer + U.mind.special_verbs += /mob/proc/ninjawalk + U.mind.special_verbs += /mob/proc/ninjamirage + verbs -= /obj/item/clothing/suit/space/space_ninja/proc/spideros + U.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!" + unlock = 0 + spideros = 0 + 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", amount_per_transfer_from_this) + 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", amount_per_transfer_from_this) + 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", amount_per_transfer_from_this) + 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", amount_per_transfer_from_this) + 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." + + else + /*Leaving this for the messenger because it's an awesome solution. For switch to work, the variable has to be static. + Not the case when P is a specific object. The downside, of course, is that there is only one slot. + The following switch moves data to the appropriate function based on what screen it was clicked on. For now only uses screen 3. + As an example, I added screen 31 to send the silence virus to people in the commented bits. + You can do the same with functions that require dynamic tracking. + */ + switch(spideros) + if(3) + var/obj/item/device/pda/P = locate(href_list["choice"]) + 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||!initialize)//Wow, another one of these. Man... + 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(31) + var/obj/item/device/pda/P = locate(href_list["choice"]) + if (!P.toff) + U.show_message("\blue Virus sent!", 1) + P.silent = 1 + P.ttone = "silence" */ + + spideros()//Refreshes the screen by calling it again (which replaces current screen with new screen). + return + +/obj/item/clothing/suit/space/space_ninja/examine() + set src in view() + ..() + if(initialize) + usr << "All systems operational. Current energy capacity: [src.charge]." + if(!kamikaze) + if(active) + usr << "The CLOAK-tech device is active." + else + usr << "The CLOAK-tech device is inactive." + else + usr << "\red KAMIKAZE MODE ENGAGED!" + usr << "There are [sbombs] smoke bombs remaining." + usr << "There are [aboost] adrenaline boosters remaining." + +//GLOVES=================================== + +/obj/item/clothing/gloves/space_ninja/proc/toggled() + set name = "Toggle Drain" + set desc = "Toggles the energy drain mechanism on or off." + set category = "Object" + if(!candrain) + candrain=1 + usr << "You enable the energy drain mechanism." + else + candrain=0 + usr << "You disable the energy drain mechanism." + +//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 = "Object" + + var/obj/cable/attached + var/mob/living/carbon/human/U = usr + 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 + + +/obj/item/clothing/gloves/space_ninja/proc/drain(var/target_type as text, var/target, var/obj/suit, var/obj/gloves) +//Var Initialize + var/mob/living/carbon/human/U = usr + var/obj/item/clothing/suit/space/space_ninja/S = suit + var/obj/item/clothing/gloves/space_ninja/G = gloves + + var/drain = 0//To drain from battery. + var/maxcapacity = 0//Safety check for full battery. + var/totaldrain = 0//Total energy drained. + + G.draining = 1 + + U << "\blue Now charging battery..." + + switch(target_type) + if("APC") + var/obj/machinery/power/apc/A = target + if(A.cell&&A.cell.charge) + var/datum/effects/system/spark_spread/spark_system = new /datum/effects/system/spark_spread() + spark_system.set_up(5, 0, A.loc) + while(G.candrain&&A.cell.charge>0&&!maxcapacity) + drain = rand(G.mindrain,G.maxdrain) + if(A.cell.chargeS.maxcharge) + drain = S.maxcharge-S.charge + maxcapacity = 1//Reached maximum battery capacity. + if (do_after(U,10)) + spark_system.start() + playsound(A.loc, "sparks", 50, 1) + A.cell.charge-=drain + S.charge+=drain + totaldrain+=drain + else break + U << "\blue Gained [totaldrain] energy from the APC." + if(!A.emagged) + flick("apc-spark", src) + A.emagged = 1 + A.locked = 0 + A.updateicon() + else + U << "\red This APC has run dry of power. You must find another source." + + if("SMES") + var/obj/machinery/power/smes/A = target + if(A.charge) + var/datum/effects/system/spark_spread/spark_system = new /datum/effects/system/spark_spread() + spark_system.set_up(5, 0, A.loc) + while(G.candrain&&A.charge>0&&!maxcapacity) + drain = rand(G.mindrain,G.maxdrain) + if(A.chargeS.maxcharge) + drain = S.maxcharge-S.charge + maxcapacity = 1 + if (do_after(U,10)) + spark_system.start() + playsound(A.loc, "sparks", 50, 1) + A.charge-=drain + S.charge+=drain + totaldrain+=drain + else break + U << "\blue Gained [totaldrain] energy from the SMES cell." + else + U << "\red This SMES cell has run dry of power. You must find another source." + + if("MECHA") + var/obj/mecha/A = target + A.occupant_message("\red Warning: Unauthorized access through sub-route 4, block H, detected.") + if(A.get_charge()) + while(G.candrain&&A.cell.charge>0&&!maxcapacity) + drain = rand(G.mindrain,G.maxdrain) + if(A.cell.chargeS.maxcharge) + drain = S.maxcharge-S.charge + maxcapacity = 1 + if (do_after(U,10)) + A.spark_system.start() + playsound(A.loc, "sparks", 50, 1) + A.cell.use(drain) + S.charge+=drain + totaldrain+=drain + else break + U << "\blue Gained [totaldrain] energy from [src]." + else + U << "\red The exosuit's battery has run dry of power. You must find another source." + + if("CYBORG") + var/mob/living/silicon/robot/A = target + A << "\red Warning: Unauthorized access through sub-route 12, block C, detected." + G.draining = 1 + if(A.cell&&A.cell.charge) + while(G.candrain&&A.cell.charge>0&&!maxcapacity) + drain = rand(G.mindrain,G.maxdrain) + if(A.cell.chargeS.maxcharge) + drain = S.maxcharge-S.charge + maxcapacity = 1 + if (do_after(U,10)) + A.spark_system.start() + playsound(A.loc, "sparks", 50, 1) + A.cell.charge-=drain + S.charge+=drain + totaldrain+=drain + else break + U << "\blue Gained [totaldrain] energy from [A]." + else + U << "\red Their battery has run dry of power. You must find another source." + + if("WIRE") + var/obj/cable/A = target + var/datum/powernet/PN = A.get_powernet() + while(G.candrain&&!maxcapacity&&!isnull(A)) + drain = (round((rand(G.mindrain,G.maxdrain))/2)) + var/drained = 0 + if(PN&&do_after(U,10)) + drained = min(drain, PN.avail) + PN.newload += drained + if(drained < drain)//if no power on net, drain apcs + for(var/obj/machinery/power/terminal/T in PN.nodes) + if(istype(T.master, /obj/machinery/power/apc)) + var/obj/machinery/power/apc/AP = T.master + if(AP.operating && AP.cell && AP.cell.charge>0) + AP.cell.charge = max(0, AP.cell.charge - 5) + drained += 5 + else break + S.charge += drained + if(S.charge>S.maxcharge) + totaldrain += (drained-(S.charge-S.maxcharge)) + S.charge = S.maxcharge + maxcapacity = 1 + else + totaldrain += drained + S.spark_system.start() + if(drained==0) break + U << "\blue Gained [totaldrain] energy from the power network." + else//Else nothing :< + + G.draining = 0 + + return + +//DRAINING PROCS END=================================== + +/obj/item/clothing/gloves/space_ninja/examine() + set src in view() + ..() + if(!canremove) + if(candrain) + usr << "The energy drain mechanism is: active." + else + usr << "The energy drain mechanism is: inactive." + +//MASK=================================== + +/obj/item/clothing/mask/gas/voice/space_ninja/New() + verbs += /obj/item/clothing/mask/gas/voice/space_ninja/proc/togglev + verbs += /obj/item/clothing/mask/gas/voice/space_ninja/proc/switchm + +/obj/item/clothing/mask/gas/voice/space_ninja/proc/togglev() + set name = "Toggle Voice" + set desc = "Toggles the voice synthesizer on or off." + set category = "Object" + var/vchange = (alert("Would you like to synthesize a new name or turn off the voice synthesizer?",,"New Name","Turn Off")) + if(vchange=="New Name") + var/chance = rand(1,100) + switch(chance) + if(1 to 50)//High chance of a regular name. + var/g = pick(0,1) + var/first = null + var/last = pick(last_names) + if(g==0) + first = pick(first_names_female) + else + first = pick(first_names_male) + voice = "[first] [last]" + if(51 to 80)//Smaller chance of a clown name. + var/first = pick(clown_names) + voice = "[first]" + if(81 to 90)//Small chance of a wizard name. + var/first = pick(wizard_first) + var/last = pick(wizard_second) + voice = "[first] [last]" + if(91 to 100)//Small chance of an existing crew name. + var/list/names = new() + for(var/mob/living/carbon/human/M in world) + if(M==usr||!M.client||!M.real_name) continue + names.Add(M) + if(!names.len) + voice = "Cuban Pete"//Smallest chance to be the man. + else + var/mob/picked = pick(names) + voice = picked.real_name + usr << "You are now mimicking [voice]." + return + else + if(voice!="Unknown") + usr << "You deactivate the voice synthesizer." + voice = "Unknown" + else + usr << "The voice synthesizer is already deactivated." + return + +/obj/item/clothing/mask/gas/voice/space_ninja/proc/switchm() + set name = "Switch Mode" + set desc = "Switches between Night Vision, Meson, or Thermal vision modes." + set category = "Object" + //Have to reset these manually since life.dm is retarded like that. Go figure. + switch(mode) + if(1) + mode=2 + usr.see_in_dark = 2 + usr << "Switching mode to Thermal Scanner." + if(2) + mode=3 + usr.see_invisible = 0 + usr.sight &= ~SEE_MOBS + usr << "Switching mode to Meson Scanner." + if(3) + mode=1 + usr.sight &= ~SEE_TURFS + usr << "Switching mode to Night Vision." + +/obj/item/clothing/mask/gas/voice/space_ninja/examine() + set src in view() + ..() + var/mode = "Night Vision" + var/voice = "inactive" + switch(mode) + if(1) + mode = "Night Vision" + if(2) + mode = "Thermal Scanner" + if(3) + mode = "Meson Scanner" + if(vchange==0) + voice = "inactive" + else + voice = "active" + usr << "[mode] is active." + usr << "Voice mimicking algorithm is set to [voice]." \ No newline at end of file diff --git a/code/game/gamemodes/extra/space_ninja.dm b/code/game/gamemodes/extra/space_ninja.dm new file mode 100644 index 00000000000..64538963ed2 --- /dev/null +++ b/code/game/gamemodes/extra/space_ninja.dm @@ -0,0 +1,87 @@ +//SPACE NINJAS============================= +/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 attitude." + if(!src.authenticated || !src.holder) + src << "Only administrators may use this command." + return + if(!ticker.mode)//Apparently, this doesn't actually prevent anything. Huh + alert("The game hasn't started yet!") + return + if(alert("Are you sure you want to send in a space ninja?",,"Yes","No")=="No") + return + + TRYAGAIN + var/input = input(usr, "Please specify which mission the space ninja shall undertake.", "Specify Mission", "") + if(!input) + goto TRYAGAIN + + var/list/LOCLIST = list() + for(var/obj/landmark/X in world) + if (X.name == "carpspawn") + LOCLIST.Add(X) + if(!LOCLIST.len) + alert("No spawn location could be found. Aborting.") + return + + var/obj/landmark/STARTLOC = pick(LOCLIST) + + var/mob/living/carbon/human/new_ninja = new(STARTLOC.loc) + + new_ninja.create_ninja() + + var/admin_name = src//In case admins want to spawn themselves as ninjas. Badmins + + var/mob/dead/observer/G + var/list/candidates = list() + for(G in world) + if(G.client) + if(((G.client.inactivity/10)/60) <= 5) + candidates.Add(G) + if(candidates.len) + G = input("Pick character to spawn as the Space Ninja", "Active Players", G) in candidates//It will auto-pick a person when there is only one candidate. + new_ninja.mind.key = G.key + new_ninja.client = G.client + new_ninja.mind.store_memory("Mission: \red [input].") + del(G) + else + alert("Could not locate a suitable ghost. Aborting.") + del(new_ninja) + return + + 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" + + 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]" + + 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.") + +mob/proc/create_ninja() + var/mob/living/carbon/human/new_ninja = src + var/ninja_title = pick(ninja_titles) + var/ninja_name = pick(ninja_names) + new_ninja.gender = pick(MALE, FEMALE) + new_ninja.real_name = "[ninja_title] [ninja_name]" + new_ninja.age = rand(17,45) + new_ninja.b_type = pick("A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-") + new_ninja.dna.ready_dna(new_ninja) + new_ninja.mind = new + new_ninja.mind.current = new_ninja + new_ninja.mind.assigned_role = "Space Ninja" + new_ninja.mind.special_role = "Space Ninja" + new_ninja.resistances += "alien_embryo" + + var/obj/item/device/radio/R = new /obj/item/device/radio/headset(new_ninja) + new_ninja.equip_if_possible(R, new_ninja.slot_ears) + new_ninja.equip_if_possible(new /obj/item/clothing/under/color/black(new_ninja), new_ninja.slot_w_uniform) + new_ninja.equip_if_possible(new /obj/item/clothing/shoes/space_ninja(new_ninja), new_ninja.slot_shoes) + new_ninja.equip_if_possible(new /obj/item/clothing/suit/space/space_ninja(new_ninja), new_ninja.slot_wear_suit) + new_ninja.equip_if_possible(new /obj/item/clothing/gloves/space_ninja(new_ninja), new_ninja.slot_gloves) + new_ninja.equip_if_possible(new /obj/item/clothing/head/helmet/space/space_ninja(new_ninja), new_ninja.slot_head) + new_ninja.equip_if_possible(new /obj/item/clothing/mask/gas/voice/space_ninja(new_ninja), new_ninja.slot_wear_mask) + new_ninja.equip_if_possible(new /obj/item/device/flashlight(new_ninja), new_ninja.slot_belt) + new_ninja.equip_if_possible(new /obj/item/weapon/plastique(new_ninja), new_ninja.slot_r_store) + new_ninja.equip_if_possible(new /obj/item/weapon/plastique(new_ninja), new_ninja.slot_l_store) + new_ninja.equip_if_possible(new /obj/item/weapon/tank/emergency_oxygen(new_ninja), new_ninja.slot_s_store) \ No newline at end of file diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 85f8d7be0c6..81511fa7750 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -306,38 +306,12 @@ /obj/mecha/attack_hand(mob/user as mob) src.log_message("Attack by hand/paw. Attacker - [user].",1) + if(ishuman(user)) - var/mob/living/carbon/human/U = user - var/obj/item/clothing/gloves/space_ninja/G = U.gloves - if(istype(G) && G.candrain && !G.draining) - var/obj/item/clothing/suit/space/space_ninja/S = U.wear_suit - user << "\blue Now charging battery..." - occupant_message("\red Warning: Unauthorized access through sub-route 4, block H, detected.") - G.draining = 1 - if(get_charge()) - var/drain = 0 - var/maxcapacity = 0 - var/totaldrain = 0 - while(G.candrain&&cell.charge>0&&!maxcapacity) - drain = rand(G.mindrain,G.maxdrain) - if(cell.chargeS.maxcharge) - drain = S.maxcharge-S.charge - maxcapacity = 1 - if (call(/proc/do_after)(U,10))//The mecha do_after proc was being called here instead of the mob one. - spark_system.start() - playsound(src.loc, "sparks", 50, 1) - cell.use(drain) - S.charge+=drain - totaldrain+=drain - else break - U << "\blue Gained [totaldrain] energy from [src]." - G.draining = 0 - return - else - U << "\red The exosuit's battery has run dry of power. You must find another source." + 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)("MECHA",src,user:wear_suit,user:gloves) return + if (user.mutations & 8 && !prob(src.deflect_chance)) src.take_damage(15) src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) diff --git a/code/game/objects/devices/PDA/PDA.dm b/code/game/objects/devices/PDA/PDA.dm index 17042e4f6d9..1851895822d 100644 --- a/code/game/objects/devices/PDA/PDA.dm +++ b/code/game/objects/devices/PDA/PDA.dm @@ -10,13 +10,14 @@ w_class = 2.0 flags = FPRINT | TABLEPASS | ONBELT + //Main variables var/owner = null var/default_cartridge = 0 // Access level defined by cartridge var/obj/item/weapon/cartridge/cartridge = null //current cartridge - var/mode = "main" //0-10, Main menu, Crew manifest, Engine monitor, Atmos scanner, med records, notes, sec records, messenger, mop locator, signaler, status display. - var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner. + var/mode = 0 //Controls what menu the PDA will display. 0 is hub; the rest are either built in or based on cartridge. - var/tmode = 0 //Texting mode, 1 to view recieved messages + //Secondary variables + var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner. var/fon = 0 //Is the flashlight function on? var/f_lum = 4 //Luminosity for the flashlight function var/silent = 0 //To beep or not to beep, that is the question @@ -93,143 +94,205 @@ icon_state = "pda-holy" ttone = "holy" - - /* * The Actual PDA */ - /obj/item/device/pda/pickup(mob/user) - if (src.fon) - src.sd_SetLuminosity(0) - user.sd_SetLuminosity(user.luminosity + src.f_lum) + if (fon) + sd_SetLuminosity(0) + user.sd_SetLuminosity(user.luminosity + f_lum) /obj/item/device/pda/dropped(mob/user) - if (src.fon) - user.sd_SetLuminosity(user.luminosity - src.f_lum) - src.sd_SetLuminosity(src.f_lum) + if (fon) + user.sd_SetLuminosity(user.luminosity - f_lum) + sd_SetLuminosity(f_lum) /obj/item/device/pda/New() ..() spawn(3) - if (src.default_cartridge) - src.cartridge = new src.default_cartridge(src) + if (default_cartridge) + cartridge = new default_cartridge(src) +//NOTE: graphic resources are loaded on client login /obj/item/device/pda/attack_self(mob/user as mob) -/* - if (user.client) //load the PDA iconset into the client - user << browse_rsc('pda_back.png') - user << browse_rsc('pda_bell.png') - user << browse_rsc('pda_blank.png') - user << browse_rsc('pda_boom.png') - user << browse_rsc('pda_bucket.png') - user << browse_rsc('pda_crate.png') - user << browse_rsc('pda_cuffs.png') - user << browse_rsc('pda_eject.png') - user << browse_rsc('pda_exit.png') - user << browse_rsc('pda_flashlight.png') - user << browse_rsc('pda_honk.png') - user << browse_rsc('pda_mail.png') - user << browse_rsc('pda_medical.png') - user << browse_rsc('pda_menu.png') - user << browse_rsc('pda_mule.png') - user << browse_rsc('pda_notes.png') - user << browse_rsc('pda_power.png') - user << browse_rsc('pda_rdoor.png') - user << browse_rsc('pda_reagent.png') - user << browse_rsc('pda_refresh.png') - user << browse_rsc('pda_scanner.png') - user << browse_rsc('pda_signaler.png') - user << browse_rsc('pda_status.png')*/ - - user.machine = src var/dat = "Personal Data Assistant" - dat += " Close" + dat += " Close" - if ((!isnull(src.cartridge)) && (src.mode == "main")) - dat += " | Eject [src.cartridge]" - if (src.mode != "main") - dat += " | Main Menu" - dat += " | Refresh" + if ((!isnull(cartridge)) && (mode == 0)) + dat += " | Eject [cartridge]" + if (mode) + dat += " | Return" + dat += " | Refresh" dat += "
    " - if (!src.owner) + if (!owner) dat += "Warning: No owner information entered. Please swipe card.

    " - dat += " Retry" + dat += " Retry" else - switch (src.mode) - if ("main") + switch (mode) + if (0) dat += "

    PERSONAL DATA ASSISTANT

    " - dat += "Owner: [src.owner], [src.ownjob]
    " - dat += text("ID: []
    ", src, (src.id ? "[src.id.registered], [src.id.assignment]" : "----------")) + dat += "Owner: [owner], [ownjob]
    " + dat += text("ID: []
    ", src, (id ? "[id.registered], [id.assignment]" : "----------")) dat += "Station Time: [round(world.time / 36000)+12]:[(world.time / 600 % 60) < 10 ? add_zero(world.time / 600 % 60, 1) : world.time / 600 % 60]"//:[world.time / 100 % 6][world.time / 100 % 10]" dat += "

    " dat += "

    General Functions

    " dat += "" - - if (src.cartridge.access_engine) + if (cartridge.access_engine) dat += "

    Engineering Functions

    " dat += "" - if (src.cartridge.access_medical) + if (cartridge.access_medical) dat += "

    Medical Functions

    " dat += "" - if (src.cartridge.access_security) + if (cartridge.access_security) dat += "

    Security Functions

    " dat += "" - else dat += "" + else dat += "" if(cartridge.access_quartermaster) dat += "

    Quartermaster Functions:

    " dat += "" - else dat += "" + dat += "" dat += "

    Utilities

    " dat += "" - if ("atmos") + if (1) + dat += "

    Notekeeper V2.1

    " + if ((!isnull(uplink)) && (uplink.active)) + dat += " Lock
    " + else + dat += " Edit
    " + dat += note + if (2) + dat += "

    SpaceMessenger V3.9.4

    " + dat += " Ringer: [silent == 1 ? "Off" : "On"] | " + dat += " Send / Receive: [toff == 1 ? "Off" : "On"] | " + dat += " Set Ringtone | " + dat += " Messages
    " + + if (istype(cartridge, /obj/item/weapon/cartridge/syndicate)) + dat += "

    Hidden Menu

    " + + if (istype(cartridge, /obj/item/weapon/cartridge/clown)) + dat += "

    Hidden Menu

    " + + if (istype(cartridge, /obj/item/weapon/cartridge/mime)) + dat += "

    Hidden Menu

    " + + dat += "

    Detected PDAs

    " + + dat += "
      " + + var/count = 0 + + if (!toff) + for (var/obj/item/device/pda/P in world) + if (!P.owner||P.toff||P == src) continue + dat += "
    • [P]" + dat += "
    • " + count++ + dat += "
    " + if (count == 0) + dat += "None detected.
    " + + if(21) + dat += "

    SpaceMessenger V3.9.4

    " + dat += " Clear Messages" + + dat += "

    Messages

    " + + dat += tnote + dat += "
    " + + if(22) + dat += "

    Datomatix

    " + dat += "[cartridge:shock_charges] detonation charges left.
    " + dat += "

    Detected PDAs

    " + dat += "
      " + var/count = 0 + for (var/obj/item/device/pda/P in world) + if (!P.owner||P.toff||P == src) continue + dat += " ( [P] *Detonate*)" + dat += "" + count++ + dat += "
    " + if (count == 0) + dat += "None detected.
    " + + if(23) + dat += "

    Honk Attack!!

    " + dat += "[cartridge:honk_charges] viral files left.
    " + dat += "

    Detected PDAs

    " + dat += "
      " + var/count = 0 + for (var/obj/item/device/pda/P in world) + if (!P.owner||P.toff||P == src) continue + dat += " ( [P] *Send Virus*)" + dat += "" + count++ + dat += "
    " + if (count == 0) + dat += "None detected.
    " + + if(24) + dat += "

    Silent but Deadly...

    " + dat += "[cartridge:mime_charges] viral files left.
    " + dat += "

    Detected PDAs

    " + dat += "
      " + var/count = 0 + for (var/obj/item/device/pda/P in world) + if (!P.owner||P.toff||P == src) continue + dat += " ( [P] *Send Virus*)" + dat += "" + count++ + dat += "
    " + if (count == 0) + dat += "None detected.
    " + + if (3) dat += "

    Atmospheric Readings

    " var/turf/T = get_turf_or_move(user.loc) @@ -249,371 +312,308 @@ 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 += "Nitrogen: [round(n2_level*100)]%
    " - dat += "Oxygen: [round(o2_level*100)]%
    " - dat += "Carbon Dioxide: [round(co2_level*100)]%
    " - dat += "Plasma: [round(plasma_level*100)]%
    " - if(unknown_level > 0.01) dat += "OTHER: [round(unknown_level)]%
    " - dat += "Temperature: [round(environment.temperature-T0C)]°C
    " - dat += "
    " - - - if ("notes") - dat += "

    Notekeeper V2.1

    " - - if ((!isnull(src.uplink)) && (src.uplink.active)) - dat += "Lock
    " - else - dat += "Edit
    " - - dat += src.note - - if ("cart") - dat += src.cart - - if ("messenger") - - dat += "

    SpaceMessenger V3.9.4

    " - - if (!src.tmode) - - dat += " Ringer: [src.silent == 1 ? "Off" : "On"] | " - dat += " Send / Receive: [src.toff == 1 ? "Off" : "On"] | " - dat += " Set Ringtone | " - dat += " Messages
    " - - if (istype(src.cartridge, /obj/item/weapon/cartridge/syndicate)) - dat+= "[src.cartridge:shock_charges] detonation charges left.
    " - - if (istype(src.cartridge, /obj/item/weapon/cartridge/clown)) - dat+= "[src.cartridge:honk_charges] viral files left.
    " - - if (istype(src.cartridge, /obj/item/weapon/cartridge/mime)) - dat+= "[src.cartridge:mime_charges] viral files left.
    " - - dat += "

    Detected PDAs

    " - - dat += "
      " - - var/count = 0 - - if (!src.toff) - for (var/obj/item/device/pda/P in world) - if (!P.owner) - continue - else if (P == src) - continue - else if (P.toff) - continue - - dat += "
    • [P]" - - if (istype(src.cartridge, /obj/item/weapon/cartridge/syndicate) && src.cartridge:shock_charges > 0) - dat += " ( *detonate*)" - //Honk.exe is the poor man's detomatix - if (istype(src.cartridge, /obj/item/weapon/cartridge/clown) && (src.cartridge:honk_charges > 0) && P.honkamt < 5) - dat += " ( *Send Virus*)" - if (istype(src.cartridge, /obj/item/weapon/cartridge/mime) && (src.cartridge:mime_charges > 0) && P.mimeamt < 5) - dat += " ( *Send Virus*)" - - - dat += "
    • " - count++ - - dat += "
    " - - if (count == 0) - dat += "None detected.
    " - - else - dat += " Clear | " - dat += " Back
    " - - dat += "

    Messages

    " - - dat += src.tnote - dat += "
    " - + else//Else it links to the cart menu proc. Although, it really uses menu hub 4--menu 4 doesn't really exist as it simply redirects to hub. + dat += cart dat += "" - user << browse(dat, "window=pda") + user << browse(dat, "window=pda;size=400x444;border=1;can_resize=0;can_close=0;can_minimize=0") onclose(user, "pda", src) /obj/item/device/pda/Topic(href, href_list) ..() - - if (usr.contents.Find(src) || usr.contents.Find(src.master) || (istype(src.loc, /turf) && get_dist(src, usr) <= 1)) - if (usr.stat || usr.restrained()) + var/mob/living/U = usr + if (U.contents.Find(src) || U.contents.Find(master) || (istype(loc, /turf) && get_dist(src, U) <= 1)) + if (U.stat || U.restrained()) + U << browse(null, "window=pda") return + else + add_fingerprint(U) + U.machine = src - src.add_fingerprint(usr) - usr.machine = src + switch(href_list["choice"]) - if (href_list["auth"]) - if (src.id) - if (istype(src.loc, /mob)) - var/obj/item/W = src.loc:equipped() - var/emptyHand = (W == null) +//BASIC FUNCTIONS=================================== - if(emptyHand) - src.id.DblClick() - if(!istype(src.id.loc, /obj/item/device/pda)) - - src.id = null - // src.id.loc = src.loc -// else if (istype(src.loc, /turf)) src.id.loc = src.loc - else - src.id.loc = src.loc - src.id = null - - else - var/obj/item/I = usr.equipped() - if (istype(I, /obj/item/weapon/card/id)) - usr.drop_item() - I.loc = src - src.id = I - - - if (href_list["mm"]) - src.mode = "main" - - if (href_list["cart"]) - cartridge.mode = href_list["cart"] - cartridge.unlock() - - else if (href_list["atmos"]) - src.mode = "atmos" - - else if (href_list["note"]) - src.mode = "notes" - - else if (href_list["mess"]) - src.mode = "messenger" - - else if (href_list["pback"]) - src.tmode = !src.tmode - - else if (href_list["flight"]) - src.fon = (!src.fon) - - if (usr.contents.Find(src)) - if (src.fon) - usr.sd_SetLuminosity(usr.luminosity + src.f_lum) - else - usr.sd_SetLuminosity(usr.luminosity - src.f_lum) - else - src.sd_SetLuminosity(src.fon * src.f_lum) - - src.updateUsrDialog() - - else if (href_list["editnote"]) - if (src.mode == "notes") - var/n = input(usr, "Please enter message", src.name, src.note) as message - if (!in_range(src, usr) && src.loc != usr) + if("Close")//Self explanatory + U << browse(null, "window=pda") return - n = copytext(adminscrub(n), 1, MAX_MESSAGE_LEN) - if (src.mode == "notes") - src.note = n - - else if (src.mode == "messenger") - var/t = input(usr, "Please enter message", src.name, null) as text - t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) - if (!t) - return - if (!in_range(src, usr) && src.loc != usr) - return - - var/obj/item/device/pda/P = locate(href_list["editnote"]) - - if (isnull(P)) - return - - if (last_text && world.time < last_text + 5) - return - - if (P.toff || src.toff) - return - - last_text = world.time - - for (var/obj/machinery/message_server/MS in world) - MS.send_pda_message("[P.owner]","[src.owner]","[t]") - - src.tnote += "→ To [P.owner]:
    [t]
    " - P.tnote += "← From [src.owner]:
    [t]
    " - - if (prob(15)) //Give the AI a chance of intercepting the message - for (var/mob/living/silicon/ai/A in world) - A.show_message("Intercepted message from [P:owner]: [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") - - else if (href_list["settone"]) - var/t = input(usr, "Please enter new ringtone", src.name, src.ttone) as text - if (!in_range(src, usr) && src.loc != usr) - return - - if (!t) - return - - if ((src.uplink) && (cmptext(t,src.uplink.lock_code)) && (!src.uplink.active)) - usr << "The PDA softly beeps." - src.uplink.unlock() - else - t = copytext(sanitize(t), 1, 20) - src.ttone = t - - - else if (href_list["refresh"]) - if (mode == "cart") - cartridge.unlock() - else src.updateUsrDialog() - - else if (href_list["close"]) - usr << browse(null, "window=pda") - usr.machine = null - - else if (href_list["set_scanmode"]) - var/smode = (text2num(href_list["set_scanmode"])) - if (src.scanmode == smode) - src.scanmode = 0 - - else if ((smode == 1) && (!isnull(src.cartridge)) && (src.cartridge.access_medical)) - src.scanmode = 1 - - else if ((smode == 2) && (!isnull(src.cartridge)) && (src.cartridge.access_security)) - src.scanmode = 2 - - else if ((smode == 3) && (!isnull(src.cartridge)) && (src.cartridge.access_reagent_scanner)) - src.scanmode = 3 - - src.updateUsrDialog() - - else if (href_list["detonate"] && istype(src.cartridge, /obj/item/weapon/cartridge/syndicate)) - var/obj/item/device/pda/P = locate(href_list["detonate"]) - if(P) - if (!P.toff && src.cartridge:shock_charges > 0) - src.cartridge:shock_charges-- - - var/difficulty = 0 - - if (!isnull(P.cartridge)) - difficulty += P.cartridge.access_medical - difficulty += P.cartridge.access_security - difficulty += P.cartridge.access_engine - difficulty += P.cartridge.access_clown - difficulty += P.cartridge.access_janitor - difficulty += P.cartridge.access_manifest * 2 + if("Refresh")//Refresh, goes to the end of the proc. + if("Return")//Return + if(mode<=9) + mode = 0 else - difficulty += 2 - - if ((prob(difficulty * 12)) || (P.uplink)) - usr.show_message("\red An error flashes on your [src].", 1) - else if (prob(difficulty * 3)) - usr.show_message("\red Energy feeds back into your [src]!", 1) - src.explode() + mode = round(mode/10) + if(mode==4)//Fix for cartridges. Redirects to hub. + mode = 0 + else if(mode==44||mode==45)//Fix for cartridges. Redirects to refresh the menu. + cartridge.mode = mode + cartridge.unlock() + if ("Authenticate")//Checks for ID + if (id) + if (istype(loc, /mob)) + var/obj/item/W = loc:equipped() + var/emptyHand = (W == null) + if(emptyHand) + id.DblClick() + if(!istype(id.loc, /obj/item/device/pda)) + id = null + else + id.loc = loc + id = null else - usr.show_message("\blue Success!", 1) - P.explode() - src.updateUsrDialog() + var/obj/item/I = U.equipped() + if (istype(I, /obj/item/weapon/card/id)) + U.drop_item() + I.loc = src + id = I + if("Eject")//Ejects the cart, only done from hub. + if (!isnull(cartridge)) + var/turf/T = loc + if(ismob(T)) + T = T.loc + cartridge.loc = T + scanmode = 0 + if (cartridge.radio) + cartridge.radio.hostpda = null + cartridge = null - else if (href_list["sendhonk"] && istype(src.cartridge, /obj/item/weapon/cartridge/clown)) - var/obj/item/device/pda/P = locate(href_list["sendhonk"]) - if (!P.toff && src.cartridge:honk_charges > 0) - src.cartridge:honk_charges-- - usr.show_message("\blue Virus sent!", 1) +//MENU FUNCTIONS=================================== - P.honkamt = (rand(15,20)) - src.updateUsrDialog() + if("0")//Hub + mode = 0 + if("1")//Notes + mode = 1 + if("2")//Messenger + mode = 2 + if("21")//Read messeges + mode = 21 + if("22")//Detonate PDAs + mode = 22 + if("23")//Send honk virus + mode = 23 + if("24")//Send silence virus + mode = 24 + if("3")//Atmos scan + mode = 3 + if("4")//Redirects to hub + mode = 0 - else if (href_list["sendmime"] && istype(src.cartridge, /obj/item/weapon/cartridge/mime)) - var/obj/item/device/pda/P = locate(href_list["sendmime"]) - if (!P.toff && src.cartridge:mime_charges > 0) - src.cartridge:mime_charges-- - usr.show_message("\blue Virus sent!", 1) +//MAIN FUNCTIONS=================================== - P.silent = 1 - P.ttone = "silence" - src.updateUsrDialog() + if("Light") + fon = (!fon) + if (contents.Find(src)) + if (fon) + sd_SetLuminosity(U.luminosity + f_lum) + else + sd_SetLuminosity(U.luminosity - f_lum) + else + sd_SetLuminosity(fon * f_lum) + updateUsrDialog() + if("Medical Scan") + if(scanmode == 1) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_medical)) + scanmode = 1 + updateUsrDialog()//What is this even used for? + if("Forensic Scan") + if(scanmode == 2) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_security)) + scanmode = 2 + updateUsrDialog() + if("Reagent Scan") + if(scanmode == 3) + scanmode = 0 + else if((!isnull(cartridge)) && (cartridge.access_reagent_scanner)) + scanmode = 3 + updateUsrDialog() + if("Honk") + if ( !(last_honk && world.time < last_honk + 20) ) + playsound(loc, 'bikehorn.ogg', 50, 1) + last_honk = world.time - else if (href_list["remotedoor"] && !isnull(src.cartridge) && src.cartridge.access_remote_door) - for (var/obj/machinery/door/poddoor/M in machines) - if (M.id != src.cartridge.remote_door_id) - continue - if (M.density) - spawn(0) - M.open() - else - spawn(0) - M.close() +//MESSENGER/NOTE FUNCTIONS=================================== - else if (href_list["rc"] && !isnull(src.cartridge)) - var/turf/T = src.loc - if (ismob(T)) - T = T.loc + if ("Edit") + var/n = input(U, "Please enter message", name, note) as message + if (in_range(src, U) && loc == U) + n = copytext(adminscrub(n), 1, MAX_MESSAGE_LEN) + if (mode == 1) + note = n + else + U << browse(null, "window=pda") + return + if("Toggle Messenger") + toff = !toff + if("Toggle Ringer")//If viewing texts then erase them, if not then toggle silent status + silent = !silent + updateUsrDialog() + if("Clear")//Clears messages + tnote = null + updateUsrDialog() + if("Ringtone") + var/t = input(U, "Please enter new ringtone", name, ttone) as text + if (in_range(src, U) && loc == U) + if (t) + if ((uplink) && (cmptext(t,uplink.lock_code)) && (!uplink.active)) + U << "The PDA softly beeps." + uplink.unlock() + else + t = copytext(sanitize(t), 1, 20) + ttone = t + else + U << browse(null, "window=pda") + return - src.cartridge.loc = T - src.scanmode = 0 - cartridge.mmode = 0 - cartridge.smode = 0 - if (src.cartridge.radio) - src.cartridge.radio.hostpda = null - src.cartridge = null +//SYNDICATE FUNCTIONS=================================== + if("Door") + if(!isnull(cartridge) && cartridge.access_remote_door) + for(var/obj/machinery/door/poddoor/M in machines) + if(M.id == cartridge.remote_door_id) + if(M.density) + spawn(0) + M.open() + else + spawn(0) + M.close() + if("Lock") + if(uplink) + uplink.active = 0 + note = uplink.orignote + updateUsrDialog() - else if (href_list["tfunc"]) //If viewing texts then erase them, if not then toggle silent status - if (src.tmode) - src.tnote = null - src.updateUsrDialog() +//LINK FUNCTIONS=================================== - else if (!src.tmode) - src.silent = !src.silent - src.updateUsrDialog() + else//Else, redirects based on current menu + switch(mode) + if(0)//Cartridge menu linking + mode = text2num(href_list["choice"]) + cartridge.mode = mode + cartridge.unlock() + if(2)//Message people. + var/t = input(U, "Please enter message", name, null) as text + t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN) + if (!t) + return + if (!in_range(src, U) && loc != U) + return - else if (href_list["tonoff"]) //toggle toff - src.toff = !src.toff + var/obj/item/device/pda/P = locate(href_list["choice"]) - else if (href_list["lock_uplink"]) //Lock that uplink!! - if(src.uplink) - src.uplink.active = 0 - src.note = src.uplink.orignote - src.updateUsrDialog() + if (isnull(P)||P.toff || toff) + return - else if (href_list["honk"]) - if (last_honk && world.time < last_honk + 20) - return - playsound(src.loc, 'bikehorn.ogg', 50, 1) - src.last_honk = world.time + if (last_text && world.time < last_text + 5) + return - if (src.mode == "messenger" || src.tmode == 1) - src.overlays = null + last_text = world.time - if ((src.honkamt > 0) && (prob(60))) - src.honkamt-- - playsound(src.loc, 'bikehorn.ogg', 30, 1) + for (var/obj/machinery/message_server/MS in world) + MS.send_pda_message("[P.owner]","[owner]","[t]") - for (var/mob/M in viewers(1, src.loc)) - if (M.client && M.machine == src) - src.attack_self(M) + tnote += "→ To [P.owner]:
    [t]
    " + P.tnote += "← From [owner]:
    [t]
    " + + if (prob(15)) //Give the AI a chance of intercepting the message + for (var/mob/living/silicon/ai/A in world) + A.show_message("Intercepted message from [P:owner]: [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(22)//Detonate PDA + if(istype(cartridge, /obj/item/weapon/cartridge/syndicate)) + var/obj/item/device/pda/P = locate(href_list["choice"]) + if(!isnull(P)) + if (!P.toff && cartridge:shock_charges > 0) + cartridge:shock_charges-- + + var/difficulty = 0 + + if (!isnull(P.cartridge)) + difficulty += P.cartridge.access_medical + difficulty += P.cartridge.access_security + difficulty += P.cartridge.access_engine + difficulty += P.cartridge.access_clown + difficulty += P.cartridge.access_janitor + difficulty += P.cartridge.access_manifest * 2 + else + difficulty += 2 + + if ((prob(difficulty * 12)) || (P.uplink)) + U.show_message("\red An error flashes on your [src].", 1) + else if (prob(difficulty * 3)) + U.show_message("\red Energy feeds back into your [src]!", 1) + explode() + else + U.show_message("\blue Success!", 1) + P.explode() + updateUsrDialog() + else + U << "PDA not found." + else + U << browse(null, "window=pda") + return + if(23)//Honk virus + if(istype(cartridge, /obj/item/weapon/cartridge/clown)) + var/obj/item/device/pda/P = locate(href_list["choice"]) + if(!isnull(P)) + if (!P.toff && cartridge:honk_charges > 0) + cartridge:honk_charges-- + U.show_message("\blue Virus sent!", 1) + P.honkamt = (rand(15,20)) + updateUsrDialog() + else + U << "PDA not found." + else + U << browse(null, "window=pda") + return + if(24)//Silent virus + if(istype(cartridge, /obj/item/weapon/cartridge/mime)) + var/obj/item/device/pda/P = locate(href_list["choice"]) + if(!isnull(P)) + if (!P.toff && cartridge:mime_charges > 0) + cartridge:mime_charges-- + U.show_message("\blue Virus sent!", 1) + P.silent = 1 + P.ttone = "silence" + updateUsrDialog() + else + U << "PDA not found." + else + U << browse(null, "window=pda") + return + +//EXTRA FUNCTIONS=================================== + + if (mode == 2||mode == 21) + overlays = null + + if ((honkamt > 0) && (prob(60))) + honkamt-- + playsound(loc, 'bikehorn.ogg', 30, 1) + + for (var/mob/M in viewers(1, loc)) + if (M.client && M.machine == src) + attack_self(M) +// attack_self(U) + return // access to status display signals - - - /obj/item/device/pda/attackby(obj/item/weapon/C as obj, mob/user as mob) ..() if (istype(C, /obj/item/weapon/cartridge) && isnull(src.cartridge)) @@ -651,7 +651,7 @@ /obj/item/device/pda/attack(mob/C as mob, mob/user as mob) if (istype(C, /mob/living/carbon)) - switch(src.scanmode) + switch(scanmode) if(1) for (var/mob/O in viewers(C, null)) @@ -678,40 +678,41 @@ user << "\blue Blood type: [C:blood_type]\nDNA: [C:blood_DNA]" /obj/item/device/pda/afterattack(atom/A as mob|obj|turf|area, mob/user as mob) - if (src.scanmode == 2) - if (!A.fingerprints) - user << "\blue Unable to locate any fingerprints on [A]!" - else - var/list/L = params2list(A:fingerprints) - user << "\blue Isolated [L.len] fingerprints." - for(var/i in L) - user << "\blue \t [i]" - - else if (src.scanmode == 3) - if(!isnull(A.reagents)) - if(A.reagents.reagent_list.len > 0) - var/reagents_length = A.reagents.reagent_list.len - user << "\blue [reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found." - for (var/re in A.reagents.reagent_list) - user << "\blue \t [re]" + switch(scanmode) + if(2) + if (!A.fingerprints) + user << "\blue Unable to locate any fingerprints on [A]!" else - user << "\blue No active chemical agents found in [A]." - else - user << "\blue No significant chemical agents found in [A]." + var/list/L = params2list(A:fingerprints) + user << "\blue Isolated [L.len] fingerprints." + for(var/i in L) + user << "\blue \t [i]" - else if (!src.scanmode && istype(A, /obj/item/weapon/paper) && src.owner) - if ((!isnull(src.uplink)) && (src.uplink.active)) - src.uplink.orignote = A:info + if(3) + if(!isnull(A.reagents)) + if(A.reagents.reagent_list.len > 0) + var/reagents_length = A.reagents.reagent_list.len + user << "\blue [reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found." + for (var/re in A.reagents.reagent_list) + user << "\blue \t [re]" + else + user << "\blue No active chemical agents found in [A]." + else + user << "\blue No significant chemical agents found in [A]." + + if (!scanmode && istype(A, /obj/item/weapon/paper) && owner) + if ((!isnull(uplink)) && (uplink.active)) + uplink.orignote = A:info else - src.note = A:info + note = A:info user << "\blue Paper scanned." //concept of scanning paper copyright brainoblivion 2009 /obj/item/device/pda/proc/explode() //This needs tuning. var/turf/T = get_turf(src.loc) - if (ismob(src.loc)) - var/mob/M = src.loc + if (ismob(loc)) + var/mob/M = loc M.show_message("\red Your [src] explodes!", 1) if(T) @@ -833,10 +834,4 @@ if(4) new /obj/item/weapon/cartridge/head(src) - new /obj/item/weapon/cartridge/signal/toxins(src) - -/* - *Experimental PDA traitor-uplink stuff - */ - -//Syndicate uplink hidden inside a traitor PDA + new /obj/item/weapon/cartridge/signal/toxins(src) \ No newline at end of file diff --git a/code/game/objects/devices/PDA/cart.dm b/code/game/objects/devices/PDA/cart.dm index 0c78d3948e2..3df5d1a2e53 100644 --- a/code/game/objects/devices/PDA/cart.dm +++ b/code/game/objects/devices/PDA/cart.dm @@ -22,8 +22,6 @@ var/access_hydroponics = 0 var/mode = null var/menu - var/mmode = 0 //medical record viewing mode - var/smode = 0 //Security record viewing mode??? var/datum/data/record/active1 = null //General var/datum/data/record/active2 = null //Medical var/datum/data/record/active3 = null //Security @@ -126,7 +124,7 @@ if (!istype(loc, /obj/item/device/pda)) return - loc:mode = "cart" //Switch right to the notes program +// loc:mode = "cart" //Switch right to the notes program src.generate_menu() src.print_to_host(src.menu) @@ -165,8 +163,25 @@ proc/generate_menu() switch(mode) + if(40) //signaller + menu = "

    Remote Signaling System

    " - if ("crew") //crew manifest + menu += {" +Send Signal
    +Frequency: +- +- +[format_frequency(src.radio:frequency)] ++ ++
    +
    +Code: +- +- +[src.radio:code] ++ ++
    "} + if (41) //crew manifest menu = "

    Crew Manifest

    " menu += "Entries cannot be modified from this terminal.

    " @@ -175,7 +190,21 @@ menu += "[t.fields["name"]] - [t.fields["rank"]]
    " menu += "
    " - if ("power") //Muskets' power monitor + + if (42) //status displays + menu = "

    Station Status Display Interlink

    " + + menu += "\[ Clear \]
    " + menu += "\[ Shuttle ETA \]
    " + menu += "\[ Message \]" + menu += "
    " + menu += "\[ Alert: None |" + menu += " Red Alert |" + menu += " Lockdown |" + menu += " Biohazard \]
    " + + if (43) //Muskets' power monitor menu = "

    Power Monitor

    " if(!powerreport) @@ -203,99 +232,210 @@ menu += "" - if ("medical") //medical records - if (!src.mmode) + if (44) //medical records //This thing only displays a single screen so it's hard to really get the sub-menu stuff working. + menu = "

    Medical Record List

    " + for (var/datum/data/record/R in data_core.general) + menu += "[R.fields["id"]]: [R.fields["name"]]
    " + menu += "
    " + if(441) + menu = "

    Medical Record

    " - menu = "

    Medical Record List

    " - for (var/datum/data/record/R in data_core.general) - menu += "
    [R.fields["id"]]: [R.fields["name"]]
    " - menu += "
    " + if (istype(active1, /datum/data/record) && data_core.general.Find(active1)) + menu += "Name: [active1.fields["name"]] ID: [src.active1.fields["id"]]
    " + menu += "Sex: [active1.fields["sex"]]
    " + menu += "Age: [active1.fields["age"]]
    " + menu += "Fingerprint: [active1.fields["fingerprint"]]
    " + menu += "Physical Status: [active1.fields["p_stat"]]
    " + menu += "Mental Status: [active1.fields["m_stat"]]
    " + else + menu += "Record Lost!
    " - else if (src.mmode) + menu += "
    " - menu = "

    Medical Record

    " + menu += "

    Medical Data

    " + if (istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)) + menu += "Blood Type: [active2.fields["b_type"]]

    " - menu += "
    Back
    " + menu += "Minor Disabilities: [active2.fields["mi_dis"]]
    " + menu += "Details: [active2.fields["mi_dis_d"]]

    " + + menu += "Major Disabilities: [active2.fields["ma_dis"]]
    " + menu += "Details: [active2.fields["ma_dis_d"]]

    " + + menu += "Allergies: [active2.fields["alg"]]
    " + menu += "Details: [active2.fields["alg_d"]]

    " + + menu += "Current Diseases: [active2.fields["cdi"]]
    " + menu += "Details: [active2.fields["cdi_d"]]

    " + + menu += "Important Notes: [active2.fields["notes"]]
    " + else + menu += "Record Lost!
    " + + menu += "
    " + if (45) //security records + menu = "

    Security Record List

    " + + for (var/datum/data/record/R in data_core.general) + menu += "[R.fields["id"]]: [R.fields["name"]]
    " + + menu += "
    " + if(451) + menu = "

    Security Record

    " + + if (istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)) + menu += "Name: [active1.fields["name"]] ID: [src.active1.fields["id"]]
    " + menu += "Sex: [active1.fields["sex"]]
    " + menu += "Age: [active1.fields["age"]]
    " + menu += "Fingerprint: [active1.fields["fingerprint"]]
    " + menu += "Physical Status: [active1.fields["p_stat"]]
    " + menu += "Mental Status: [active1.fields["m_stat"]]
    " + else + menu += "Record Lost!
    " + + menu += "
    " + + menu += "

    Security Data

    " + if (istype(src.active3, /datum/data/record) && data_core.security.Find(src.active3)) + menu += "Criminal Status: [active3.fields["criminal"]]
    " + + menu += "Minor Crimes: [active3.fields["mi_crim"]]
    " + menu += "Details: [active3.fields["mi_crim"]]

    " + + menu += "Major Crimes: [active3.fields["ma_crim"]]
    " + menu += "Details: [active3.fields["ma_crim_d"]]

    " + + menu += "Important Notes:
    " + menu += "[src.active3.fields["notes"]]" + else + menu += "Record Lost!
    " + + menu += "
    " + if (46) //beepsky control + var/obj/item/radio/integrated/beepsky/SC = radio + if(!SC) + menu = "Interlink Error - Please reinsert cartridge." + return + + menu = "

    Securitron Interlink

    " + + if(!SC.active) + // list of bots + if(!SC.botlist || (SC.botlist && SC.botlist.len==0)) + menu += "No bots found.
    " - if (istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)) - menu += "Name: [src.active1.fields["name"]] ID: [src.active1.fields["id"]]
    " - menu += "Sex: [src.active1.fields["sex"]]
    " - menu += "Age: [src.active1.fields["age"]]
    " - menu += "Fingerprint: [src.active1.fields["fingerprint"]]
    " - menu += "Physical Status: [src.active1.fields["p_stat"]]
    " - menu += "Mental Status: [src.active1.fields["m_stat"]]
    " else - menu += "Record Lost!
    " + for(var/obj/machinery/bot/secbot/B in SC.botlist) + menu += "
    [B] at [B.loc.loc]
    " - menu += "
    " + menu += "
    Scan for active bots
    " - menu += "

    Medical Data

    " - if (istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)) - menu += "Blood Type: [src.active2.fields["b_type"]]

    " + else // bot selected, control it - menu += "Minor Disabilities: [src.active2.fields["mi_dis"]]
    " - menu += "Details: [src.active2.fields["mi_dis_d"]]

    " + menu += "[SC.active]
    Status: (refresh)
    " - menu += "Major Disabilities: [src.active2.fields["ma_dis"]]
    " - menu += "Details: [src.active2.fields["ma_dis_d"]]

    " - - menu += "Allergies: [src.active2.fields["alg"]]
    " - menu += "Details: [src.active2.fields["alg_d"]]

    " - - menu += "Current Diseases: [src.active2.fields["cdi"]]
    " - menu += "Details: [src.active2.fields["cdi_d"]]

    " - - menu += "Important Notes: [src.active2.fields["notes"]]
    " + if(!SC.botstatus) + menu += "Waiting for response...
    " else - menu += "Record Lost!
    " - menu += "
    " - if ("security") //security records - if (!src.smode) + menu += "Location: [SC.botstatus["loca"] ]
    " + menu += "Mode: " - menu = "

    Security Record List

    " + switch(SC.botstatus["mode"]) + if(0) + menu += "Ready" + if(1) + menu += "Apprehending target" + if(2,3) + menu += "Arresting target" + if(4) + menu += "Starting patrol" + if(5) + menu += "On patrol" + if(6) + menu += "Responding to summons" - for (var/datum/data/record/R in data_core.general) - menu += "[R.fields["id"]]: [R.fields["name"]]
    " + menu += "
    \[
    Stop Patrol\] " + menu += "\[Start Patrol\] " + menu += "\[Summon Bot\]
    " + menu += "
    Return to bot list" - menu += "
    " + if (47) //quartermaster order records + menu = "

    Supply Record Interlink

    " - else if (src.smode) + menu += "
    Supply shuttle
    " + menu += "Location: [supply_shuttle_moving ? "Moving to station ([supply_shuttle_timeleft] Mins.)":supply_shuttle_at_station ? "Station":"Dock"]
    " + menu += "Current approved orders:
      " + for(var/S in supply_shuttle_shoppinglist) + var/datum/supply_order/SO = S + menu += "
    1. [SO.object.name] approved by [SO.orderedby] [SO.comment ? "([SO.comment])":""]
    2. " + menu += "
    " - menu = "

    Security Record

    " + menu += "Current requests:
      " + for(var/S in supply_shuttle_requestlist) + var/datum/supply_order/SO = S + menu += "
    1. [SO.object.name] requested by [SO.orderedby]
    2. " + menu += "
    Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management." - menu += " Back
    " + if (48) //mulebot control + var/obj/item/radio/integrated/mule/QC = radio + if(!QC) + menu = "Interlink Error - Please reinsert cartridge." + return + + menu = "

    M.U.L.E. bot Interlink V0.8

    " + + if(!QC.active) + // list of bots + if(!QC.botlist || (QC.botlist && QC.botlist.len==0)) + menu += "No bots found.
    " - if (istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)) - menu += "Name: [src.active1.fields["name"]] ID: [src.active1.fields["id"]]
    " - menu += "Sex: [src.active1.fields["sex"]]
    " - menu += "Age: [src.active1.fields["age"]]
    " - menu += "Fingerprint: [src.active1.fields["fingerprint"]]
    " - menu += "Physical Status: [src.active1.fields["p_stat"]]
    " - menu += "Mental Status: [src.active1.fields["m_stat"]]
    " else - menu += "Record Lost!
    " + for(var/obj/machinery/bot/mulebot/B in QC.botlist) + menu += "[B] at [B.loc.loc]
    " - menu += "
    " + menu += "
    Scan for active bots
    " - menu += "

    Security Data

    " - if (istype(src.active3, /datum/data/record) && data_core.security.Find(src.active3)) - menu += "Criminal Status: [src.active3.fields["criminal"]]
    " + else // bot selected, control it - menu += "Minor Crimes: [src.active3.fields["mi_crim"]]
    " - menu += "Details: [src.active3.fields["mi_crim"]]

    " + menu += "[QC.active]
    Status: (refresh)
    " - menu += "Major Crimes: [src.active3.fields["ma_crim"]]
    " - menu += "Details: [src.active3.fields["ma_crim_d"]]

    " - - menu += "Important Notes:
    " - menu += "[src.active3.fields["notes"]]" + if(!QC.botstatus) + menu += "Waiting for response...
    " else - menu += "Record Lost!
    " - menu += "
    " + menu += "Location: [QC.botstatus["loca"] ]
    " + menu += "Mode: " - if ("janitor") //janitorial locator + switch(QC.botstatus["mode"]) + if(0) + menu += "Ready" + if(1) + menu += "Loading/Unloading" + if(2) + menu += "Navigating to Delivery Location" + if(3) + menu += "Navigating to Home" + if(4) + menu += "Waiting for clear path" + if(5,6) + menu += "Calculating navigation path" + if(7) + menu += "Unable to locate destination" + var/obj/crate/C = QC.botstatus["load"] + menu += "
    Current Load: [ !C ? "none" : "[C.name] (unload)" ]
    " + menu += "Destination: [!QC.botstatus["dest"] ? "none" : QC.botstatus["dest"] ] (set)
    " + menu += "Power: [QC.botstatus["powr"]]%
    " + menu += "Home: [!QC.botstatus["home"] ? "none" : QC.botstatus["home"] ]
    " + menu += "Auto Return Home: [QC.botstatus["retn"] ? "On Off" : "(On) Off"]
    " + menu += "Auto Pickup Crate: [QC.botstatus["pick"] ? "On Off" : "(On) Off"]

    " + + menu += "\[Stop\] " + menu += "\[Proceed\] " + menu += "\[Return Home\]
    " + menu += "
    Return to bot list" + + if (49) //janitorial locator menu = "

    Persistent Custodial Object Locator

    " var/turf/cl = get_turf(src) @@ -353,206 +493,41 @@ else menu += "ERROR: Unable to determine current location." - if("signal") //signaller - menu = "

    Remote Signaling System

    " - - menu += {" -Send Signal
    -Frequency: -- -- -[format_frequency(src.radio:frequency)] -+ -+
    -
    -Code: -- -- -[src.radio:code] -+ -+
    "} - - if ("status") //status displays - menu = "

    Station Status Display Interlink

    " - - menu += "\[ Clear \]
    " - menu += "\[ Shuttle ETA \]
    " - menu += "\[ Message \]" - menu += "
    " - menu += "\[ Alert: None |" - menu += " Red Alert |" - menu += " Lockdown |" - menu += " Biohazard \]
    " - - if ("qm") //quartermaster order records - menu = "

    Supply Record Interlink

    " - - menu += "
    Supply shuttle
    " - menu += "Location: [supply_shuttle_moving ? "Moving to station ([supply_shuttle_timeleft] Mins.)":supply_shuttle_at_station ? "Station":"Dock"]
    " - menu += "Current approved orders:
      " - for(var/S in supply_shuttle_shoppinglist) - var/datum/supply_order/SO = S - menu += "
    1. [SO.object.name] approved by [SO.orderedby] [SO.comment ? "([SO.comment])":""]
    2. " - menu += "
    " - - menu += "Current requests:
      " - for(var/S in supply_shuttle_requestlist) - var/datum/supply_order/SO = S - menu += "
    1. [SO.object.name] requested by [SO.orderedby]
    2. " - menu += "
    Upgrade NOW to Space Parts & Space Vendors PLUS for full remote order control and inventory management." - - if ("mule") //mulebot control - var/obj/item/radio/integrated/mule/QC = radio - if(!QC) - menu = "Interlink Error - Please reinsert cartridge." - return - - menu = "

    M.U.L.E. bot Interlink V0.8

    " - - if(!QC.active) - // list of bots - if(!QC.botlist || (QC.botlist && QC.botlist.len==0)) - menu += "No bots found.
    " - - else - for(var/obj/machinery/bot/mulebot/B in QC.botlist) - menu += "[B] at [B.loc.loc]
    " - - - - menu += "
    Scan for active bots
    " - - else // bot selected, control it - - - menu += "[QC.active]
    Status: (refresh)
    " - - if(!QC.botstatus) - menu += "Waiting for response...
    " - else - - menu += "Location: [QC.botstatus["loca"] ]
    " - menu += "Mode: " - - switch(QC.botstatus["mode"]) - if(0) - menu += "Ready" - if(1) - menu += "Loading/Unloading" - if(2) - menu += "Navigating to Delivery Location" - if(3) - menu += "Navigating to Home" - if(4) - menu += "Waiting for clear path" - if(5,6) - menu += "Calculating navigation path" - if(7) - menu += "Unable to locate destination" - var/obj/crate/C = QC.botstatus["load"] - menu += "
    Current Load: [ !C ? "none" : "[C.name] (unload)" ]
    " - menu += "Destination: [!QC.botstatus["dest"] ? "none" : QC.botstatus["dest"] ] (set)
    " - menu += "Power: [QC.botstatus["powr"]]%
    " - menu += "Home: [!QC.botstatus["home"] ? "none" : QC.botstatus["home"] ]
    " - menu += "Auto Return Home: [QC.botstatus["retn"] ? "On Off" : "(On) Off"]
    " - menu += "Auto Pickup Crate: [QC.botstatus["pick"] ? "On Off" : "(On) Off"]

    " - - menu += "\[Stop\] " - menu += "\[Proceed\] " - menu += "\[Return Home\]
    " - menu += "
    Return to bot list" - - if ("beepsky") //beepsky control - var/obj/item/radio/integrated/beepsky/SC = radio - if(!SC) - menu = "Interlink Error - Please reinsert cartridge." - return - - menu = "

    Securitron Interlink

    " - - if(!SC.active) - // list of bots - if(!SC.botlist || (SC.botlist && SC.botlist.len==0)) - menu += "No bots found.
    " - - else - for(var/obj/machinery/bot/secbot/B in SC.botlist) - menu += "[B] at [B.loc.loc]
    " - - - - menu += "
    Scan for active bots
    " - - else // bot selected, control it - - - menu += "[SC.active]
    Status: (refresh)
    " - - if(!SC.botstatus) - menu += "Waiting for response...
    " - else - - menu += "Location: [SC.botstatus["loca"] ]
    " - menu += "Mode: " - - switch(SC.botstatus["mode"]) - if(0) - menu += "Ready" - if(1) - menu += "Apprehending target" - if(2,3) - menu += "Arresting target" - if(4) - menu += "Starting patrol" - if(5) - menu += "On patrol" - if(6) - menu += "Responding to summons" - - menu += "
    \[Stop Patrol\] " - menu += "\[Start Patrol\] " - menu += "\[Summon Bot\]
    " - menu += "
    Return to bot list" - /obj/item/weapon/cartridge/Topic(href, href_list) ..() - if (usr.stat || usr.restrained() || !in_range(src.loc, usr)) + if (usr.stat || usr.restrained() || !in_range(loc, usr)) return if (href_list["d_rec"]) + var/datum/data/record/R = locate(href_list["d_rec"]) var/datum/data/record/M = locate(href_list["d_rec"]) var/datum/data/record/S = locate(href_list["d_rec"]) - if (data_core.general.Find(R)) - for (var/datum/data/record/E in data_core.medical) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - M = E - break - - for (var/datum/data/record/E in data_core.security) - if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) - S = E - break - - src.active1 = R - src.active2 = M - src.active3 = S - - if (src.mode == "medical") - src.mmode = 1 - else - src.smode = 1 - - else if (href_list["pback"]) - if (src.mode == "medical") - src.mmode = 0 - if (src.mode == "security") - src.smode = 0 - loc:tmode = !loc:tmode - + switch(mode) + if(44) + loc:mode = 441 + mode = 441 + if (data_core.general.Find(R)) + for (var/datum/data/record/E in data_core.medical) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + M = E + break + active1 = R + active2 = M + active3 = S + if(45) + loc:mode = 451 + mode = 451 + if (data_core.general.Find(R)) + for (var/datum/data/record/E in data_core.security) + if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"])) + S = E + break + active1 = R + active2 = M + active3 = S else if ((href_list["ssend"]) && (istype(src,/obj/item/weapon/cartridge/signal))) for(var/obj/item/assembly/r_i_ptank/R in world) //Bomblist stuff @@ -567,10 +542,10 @@ Code: src.radio:set_frequency(new_frequency) else if ((href_list["scode"]) && (istype(src,/obj/item/weapon/cartridge/signal))) - src.radio:code += text2num(href_list["scode"]) - src.radio:code = round(src.radio:code) - src.radio:code = min(100, src.radio:code) - src.radio:code = max(1, src.radio:code) + radio:code += text2num(href_list["scode"]) + radio:code = round(src.radio:code) + radio:code = min(100, src.radio:code) + radio:code = max(1, src.radio:code) else if (href_list["statdisp"] && access_status_display) @@ -590,4 +565,4 @@ Code: post_status(href_list["statdisp"]) src.generate_menu() - src.print_to_host(src.menu) + src.print_to_host(menu) diff --git a/code/game/objects/devices/PDA/radio.dm b/code/game/objects/devices/PDA/radio.dm index 8cd587dac5d..50c535d9e0a 100644 --- a/code/game/objects/devices/PDA/radio.dm +++ b/code/game/objects/devices/PDA/radio.dm @@ -100,7 +100,6 @@ if("botlist") active = null - if("stop", "go") post_signal(control_freq, "command", href_list["op"], "active", active, s_filter = RADIO_SECBOT) post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_SECBOT) diff --git a/code/game/objects/devices/PDA/uplink.dm b/code/game/objects/devices/PDA/uplink.dm index 3fa00db07ed..7cba2caf95e 100644 --- a/code/game/objects/devices/PDA/uplink.dm +++ b/code/game/objects/devices/PDA/uplink.dm @@ -65,7 +65,7 @@ src.orignote = src.hostpda.note src.active = 1 - src.hostpda.mode = "notes" //Switch right to the notes program + src.hostpda.mode = 1 //Switch right to the notes program src.generate_menu() src.print_to_host(src.menu_message) diff --git a/code/game/objects/items/clothing.dm b/code/game/objects/items/clothing.dm index a6d135d0ec5..2850e0f9198 100644 --- a/code/game/objects/items/clothing.dm +++ b/code/game/objects/items/clothing.dm @@ -8,9 +8,6 @@ SWAT SUIT CHAMELEON JUMPSUIT DEATH COMMANDO GAS MASK THERMAL GLASSES -NINJA SUIT -NINJA GLOVES -NINJA MASK */ @@ -308,801 +305,4 @@ NINJA MASK M.disabilities |= 1 spawn(100) M.disabilities &= ~1 - ..() - -//SPESS NINJA STUFF - -//SUIT - -/obj/item/clothing/suit/space/space_ninja/New() - ..() - src.verbs += /obj/item/clothing/suit/space/space_ninja/proc/init//suit initialize verb - 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(480)//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", 80) - reagents.add_reagent("nutriment", 80) - -/obj/item/clothing/suit/space/space_ninja/proc/ntick(var/mob/living/carbon/human/U as mob) - set hidden = 1 - set background = 1 - - spawn while(initialize&&charge>=0)//Suit on and has power. - if(!initialize) return//When turned off the proc stops. - var/A = 5//Energy cost each tick. - if(!kamikaze) - if(istype(U.get_active_hand(), /obj/item/weapon/blade))//Sword check. - if(charge<=0)//If no charge left. - U.drop_item()//Sword is dropped from active hand (and deleted). - else A += 20//Otherwise, more energy consumption. - else if(istype(U.get_inactive_hand(), /obj/item/weapon/blade)) - if(charge<=0) - U.swap_hand()//swap hand - U.drop_item()//drop sword - else A += 20 - if(active) - A += 25 - else - A = 100 - charge-=A - if(charge<0) - if(kamikaze) - U.say("I DIE TO LIVE AGAIN!") - U.death() - return - charge=0 - active=0 - 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 = "Object" - - if(usr.mind&&usr.mind.special_role=="Space Ninja"&&usr:wear_suit==src&&!src.initialize) - var/mob/living/carbon/human/U = usr - 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." - U.head:canremove=0 - U.shoes:canremove=0 - U.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 - 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: [src.charge]." - sleep(40) - U << "\blue All systems operational. Welcome to SpiderOS, [U.real_name]." - U.verbs += /mob/proc/ninjashift - U.verbs += /mob/proc/ninjajaunt - U.verbs += /mob/proc/ninjasmoke - U.verbs += /mob/proc/ninjaboost - U.verbs += /mob/proc/ninjapulse - U.verbs += /mob/proc/ninjablade - U.verbs += /mob/proc/ninjastar - U.mind.special_verbs += /mob/proc/ninjashift - U.mind.special_verbs += /mob/proc/ninjajaunt - U.mind.special_verbs += /mob/proc/ninjasmoke - U.mind.special_verbs += /mob/proc/ninjaboost - U.mind.special_verbs += /mob/proc/ninjapulse - U.mind.special_verbs += /mob/proc/ninjablade - U.mind.special_verbs += /mob/proc/ninjastar - verbs += /obj/item/clothing/suit/space/space_ninja/proc/deinit - verbs += /obj/item/clothing/suit/space/space_ninja/proc/spideros - U.gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/drain_wire - U.gloves.verbs += /obj/item/clothing/gloves/space_ninja/proc/toggled - initialize=1 - affecting=U - slowdown=0 - U.shoes:slowdown-- - ntick(usr) - else - if(usr.mind&&usr.mind.special_role=="Space Ninja") - usr << "\red You do not understand how this suit functions." - else if(usr:wear_suit!=src) - usr << "\red You must be wearing the suit to use this function." - else if(initialize) - usr << "\red The suit is already functioning." - else - usr << "\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 = "Object" - - if(!initialize) - usr << "\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 - - var/mob/living/carbon/human/U = usr - 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" - U.verbs -= /mob/proc/ninjaslayer - U.verbs -= /mob/proc/ninjawalk - U.verbs -= /mob/proc/ninjamirage - U.mind.special_verbs -= /mob/proc/ninjaslayer - U.mind.special_verbs -= /mob/proc/ninjawalk - U.mind.special_verbs -= /mob/proc/ninjamirage - kamikaze = 0 - unlock = 0 - U.incorporeal_move = 0 - U.density = 1 - icon_state = "s-ninja" - spideros = 0 - sleep(40) - U.verbs -= /mob/proc/ninjashift - U.verbs -= /mob/proc/ninjajaunt - U.verbs -= /mob/proc/ninjasmoke - U.verbs -= /mob/proc/ninjaboost - U.verbs -= /mob/proc/ninjapulse - U.verbs -= /mob/proc/ninjablade - U.verbs -= /mob/proc/ninjastar - U.mind.special_verbs -= /mob/proc/ninjashift - U.mind.special_verbs -= /mob/proc/ninjajaunt - U.mind.special_verbs -= /mob/proc/ninjasmoke - U.mind.special_verbs -= /mob/proc/ninjaboost - U.mind.special_verbs -= /mob/proc/ninjapulse - U.mind.special_verbs -= /mob/proc/ninjablade - U.mind.special_verbs -= /mob/proc/ninjastar - 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(active)//Shutdowns stealth. - active=0 - 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(istype(U.head, /obj/item/clothing/head/helmet/space/space_ninja)) - U.head.canremove=1 - if(istype(U.shoes, /obj/item/clothing/shoes/space_ninja)) - U.shoes:canremove=1 - U.shoes:slowdown++ - if(istype(U.gloves, /obj/item/clothing/gloves/space_ninja)) - U.gloves.icon_state = "s-ninja" - U.gloves.item_state = "s-ninja" - U.gloves:canremove=1 - U.gloves:candrain=0 - U.gloves:draining=0 - U.gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/drain_wire - U.gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled - U.update_clothing() - canremove=1 - U << "\blue Unsecuring external locking mechanism...\nNeural-net abolished.\nOperation status: FINISHED." - verbs += /obj/item/clothing/suit/space/space_ninja/proc/init - initialize=0 - affecting=null - slowdown=1 - return - -/obj/item/clothing/suit/space/space_ninja/proc/spideros() - set name = "Display SpiderOS" - set desc = "Utilize built-in computer system." - set category = "Object" - - var/mob/living/carbon/human/U = usr - var/dat = "SpiderOS" - /*Here is where you would create a link for the cartridge used if the item has one. - As noted below, it's not worth the effort to make the cartridge removable unless it's done from the hub.*/ - if(spideros==0) - dat += " Refresh" - dat += " | Close" - 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(charge/100)]%
    " - dat += " Smoke Bombs: [sbombs]
    " - dat += "
    " - - /* - HOW TO USE OR ADAPT THIS CODE: - The menu structure should not need to be altered to add new entries. Simply place them after what is already there. - As an exception, if there are multiple-tiered windows, for instance, going into medical alerts and then to DNA testing or something, - those menus should be added below their parents but have a greater value. The second sub-menu of menu 2 would have the number 22. - Another sub-menu of menu 2 would be 23, then 24, and up to 29. If those menus have their own sub-menus a similar format follows. - Sub-menu 1 of sub-menu 2(of menu 2) would be 221. Sub-menu 5 of sub-menu 2(of menu 2) would be 225. Menu 0 is a special case (it's the menu hub); you are free to use menus 1-9 - to create your own data paths. - The Return button, when used, simply removes the final number and navigates to the menu prior. Menu 334, the fourth sub-menu of sub-menu - 3, in menu 3, would navigate to sub menu 3 in menu 3. Or 33. - It is possible to go to a different menu/sub-menu from anywhere. When creating new menus don't forget to add them to Topic proc or else the game - will interpret you using the messenger function (the else clause in the switch). - Other buttons and functions should be named according to what they do.*/ - switch(spideros) - if(0) - /* - For items that use cartridges (PDAs), simply switch() their hub function based on the cartridge inserted. - For ease of use, allow the removal of the cartidge only on the hub. - */ - 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:

    "//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(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.
    " - //dat += " Send Virus - 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.
    • " - dat += "
    • *Changeling Hivemind: extremely dangerous and to be killed on sight.
    • " - dat += "
    • *Xeno Hivemind: their skulls make interesting kitchen decorations and are challenging to best, especially in larger nests.
    • " - 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, 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: powers that are activated through the suit and powers that are activated through the verb panel. Passive powers are always on. Active powers must be turned on and remain active only when there is energy to do so. All verb powers are active and their cost is listed next to them." - dat += "Powers of the suit: 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.
    • " - dat += "
    • Stealth, when activated, drains more battery charge and works similarly to a syndicate cloak.
    • " - 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.
    • " - dat += "
    " - dat += "Verbpowers:" - 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 10 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.
    • " - 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 sword 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 += "
    • *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 += "
    " - dat += "That is all you will need to know. The rest will come with practice and talent. Good luck!" - dat += "

    Master /N

    " -/* - //Sub-menu testing stuff. - dat += "
  • To sub-menu 49
  • " - if(31) - dat += "

    Send Virus:

    " - 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(49) - dat += "

    Other Functions 49:

    " - dat += " To sub-menu 491" - if(491) - dat += "

    Other Functions 491:

    " - dat += " To main menu" -*/ - 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 = usr - if(U.stat||U.wear_suit!=src||!initialize)//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(unlock)//To unlock Kamikaze mode. Irrelevant elsewhere. - if(0) - if(href_list["choice"]=="Stealth"&&spideros==0) unlock++ - if(1) - if(href_list["choice"]=="2"&&spideros==0) unlock++ - else if(href_list["choice"]=="Return") - else unlock=0 - if(2) - if(href_list["choice"]=="3"&&spideros==0) unlock++ - else if(href_list["choice"]=="Return") - else unlock=0 - if(3) - if(href_list["choice"]=="Stealth"&&spideros==0) unlock++ - else if(href_list["choice"]=="Return") - else unlock=0 - if(4) - if(href_list["choice"]=="1"&&spideros==0) unlock++ - else if(href_list["choice"]=="Return") - else unlock=0 - if(5) - if(href_list["choice"]=="1"&&spideros==0) unlock++ - else if(href_list["choice"]=="Return") - else unlock=0 - if(6) - if(href_list["choice"]=="4"&&spideros==0) unlock++ - else if(href_list["choice"]=="Return") - else unlock=0 - if(7)//once unlocked, stays unlocked until deactivated. - else - 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") - if(active) - spawn(0) - anim(usr.loc,'mob.dmi',usr,"uncloak") - active=0 - U << "\blue You are now visible." - for(var/mob/O in oviewers(usr, null)) - O << "[usr.name] appears from thin air!" - else - spawn(0) - anim(usr.loc,'mob.dmi',usr,"cloak") - active=1 - U << "\blue You are now invisible to normal detection." - for(var/mob/O in oviewers(usr, null)) - O << "[usr.name] vanishes into thin air!" - 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 - /*Sub-menu testing stuff. - if("31") - spideros=31 - if("49") - spideros=49 - if("491") - spideros=491 */ - if("Unlock Kamikaze") - if(input(U)=="Divine Wind") - if( !(U.stat||U.wear_suit!=src||!initialize) ) - U << "\blue Engaging mode...\n\blackCODE NAME: \red KAMIKAZE" - 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 prevent engaging kamikaze and de-initializing at the same time. - kamikaze = 1 - active = 0 - icon_state = "s-ninjak" - if(istype(U.gloves, /obj/item/clothing/gloves/space_ninja)) - U.gloves.icon_state = "s-ninjak" - U.gloves.item_state = "s-ninjak" - U.gloves:candrain = 0 - U.gloves:draining = 0 - U.gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/drain_wire - U.gloves.verbs -= /obj/item/clothing/gloves/space_ninja/proc/toggled - U.update_clothing() - U.verbs -= /mob/proc/ninjashift - U.verbs -= /mob/proc/ninjajaunt - U.verbs -= /mob/proc/ninjapulse - U.verbs -= /mob/proc/ninjastar - U.mind.special_verbs -= /mob/proc/ninjashift - U.mind.special_verbs -= /mob/proc/ninjajaunt - U.mind.special_verbs -= /mob/proc/ninjapulse - U.mind.special_verbs -= /mob/proc/ninjastar - - U.verbs += /mob/proc/ninjaslayer - U.verbs += /mob/proc/ninjawalk - U.verbs += /mob/proc/ninjamirage - U.mind.special_verbs += /mob/proc/ninjaslayer - U.mind.special_verbs += /mob/proc/ninjawalk - U.mind.special_verbs += /mob/proc/ninjamirage - verbs -= /obj/item/clothing/suit/space/space_ninja/proc/spideros - U.ninjablade() - else - U << "Nevermind, you cheater." - U << browse(null, "window=spideros") - return - else - U << "\red ERROR: WRONG PASSWORD!" - unlock = 0 - spideros = 0 - 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", amount_per_transfer_from_this) - 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", amount_per_transfer_from_this) - 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", amount_per_transfer_from_this) - 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", amount_per_transfer_from_this) - 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." - - else - /*Leaving this for the messenger because it's an awesome solution. For switch to work, the variable has to be static. - Not the case when P is a specific object. The downside, of course, is that there is only one slot. - The following switch moves data to the appropriate function based on what screen it was clicked on. For now only uses screen 3. - As an example, I added screen 31 to send the silence virus to people in the commented bits. - You can do the same with functions that require dynamic tracking. - */ - switch(spideros) - if(3) - var/obj/item/device/pda/P = locate(href_list["choice"]) - 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||!initialize)//Wow, another one of these. Man... - 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(31) - var/obj/item/device/pda/P = locate(href_list["choice"]) - if (!P.toff) - U.show_message("\blue Virus sent!", 1) - P.silent = 1 - P.ttone = "silence" */ - - spideros()//Refreshes the screen by calling it again (which replaces current screen with new screen). - return - -/obj/item/clothing/suit/space/space_ninja/examine() - set src in view() - ..() - if(initialize) - usr << "All systems operational. Current energy capacity: [src.charge]." - if(!kamikaze) - if(active) - usr << "The CLOAK-tech device is active." - else - usr << "The CLOAK-tech device is inactive." - else - usr << "\red KAMIKAZE MODE ENGAGED!" - usr << "There are [sbombs] smoke bombs remaining." - usr << "There are [aboost] adrenaline boosters remaining." - -//GLOVES -/obj/item/clothing/gloves/space_ninja/proc/toggled() - set name = "Toggle Drain" - set desc = "Toggles the energy drain mechanism on or off." - set category = "Object" - if(!candrain) - candrain=1 - usr << "You enable the energy drain mechanism." - else - candrain=0 - usr << "You disable the energy drain mechanism." - -/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 = "Object" - - var/obj/cable/attached - var/mob/living/carbon/human/U = usr - 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 Now charging battery, stand still..." - draining = 1 - if(do_after(U,100)&&!isnull(attached)) - processp(attached) - else - draining = 0 - U << "\red Procedure interrupted. Protocol terminated." - return - -/obj/item/clothing/gloves/space_ninja/proc/processp(var/obj/cable/attached) -//A lot of this comes from the powersink code. - var/mob/living/carbon/human/U = usr - var/obj/item/clothing/suit/space/space_ninja/S = U.wear_suit - var/obj/item/clothing/gloves/space_ninja/G = U.gloves - var/drain = 0 - var/maxcapacity = 0 - var/totaldrain = 0 - var/datum/powernet/PN = attached.get_powernet() - while(candrain&&!maxcapacity&&!isnull(attached)) - drain = (round((rand(G.mindrain,G.maxdrain))/2)) - var/drained = 0 - if(PN&&do_after(U,10)) - drained = min (drain, PN.avail) - PN.newload += drained - if(drained < drain)//if no power on net, drain apcs - for(var/obj/machinery/power/terminal/T in PN.nodes) - if(istype(T.master, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/A = T.master - if(A.operating && A.cell && A.cell.charge>0) - A.cell.charge = max(0, A.cell.charge - 5) - drained += 5 - else break - S.charge += drained - if(S.charge>S.maxcharge) - totaldrain += (drained-(S.charge-S.maxcharge)) - S.charge = S.maxcharge - maxcapacity = 1 - else - totaldrain += drained - S.spark_system.start() - if(drained==0) break - draining = 0 - U << "\blue Gained [totaldrain] energy from the power network." - return - -/obj/item/clothing/gloves/space_ninja/examine() - set src in view() - ..() - if(!canremove) - if(candrain) - usr << "The energy drain mechanism is: active." - else - usr << "The energy drain mechanism is: inactive." - -//MASK -/obj/item/clothing/mask/gas/voice/space_ninja/New() - verbs += /obj/item/clothing/mask/gas/voice/space_ninja/proc/togglev - verbs += /obj/item/clothing/mask/gas/voice/space_ninja/proc/switchm - -/obj/item/clothing/mask/gas/voice/space_ninja/proc/togglev() - set name = "Toggle Voice" - set desc = "Toggles the voice synthesizer on or off." - set category = "Object" - var/vchange = (alert("Would you like to synthesize a new name or turn off the voice synthesizer?",,"New Name","Turn Off")) - if(vchange=="New Name") - var/chance = rand(1,100) - switch(chance) - if(1 to 50)//High chance of a regular name. - var/g = pick(0,1) - var/first = null - var/last = pick(last_names) - if(g==0) - first = pick(first_names_female) - else - first = pick(first_names_male) - voice = "[first] [last]" - if(51 to 80)//Smaller chance of a clown name. - var/first = pick(clown_names) - voice = "[first]" - if(81 to 90)//Small chance of a wizard name. - var/first = pick(wizard_first) - var/last = pick(wizard_second) - voice = "[first] [last]" - if(91 to 100)//Small chance of an existing crew name. - var/list/names = new() - for(var/mob/living/carbon/human/M in world) - if(M==usr||!M.client||!M.real_name) continue - names.Add(M) - if(!names.len) - voice = "Cuban Pete"//Smallest chance to be the man. - else - var/mob/picked = pick(names) - voice = picked.real_name - usr << "You are now mimicking [voice]." - return - else - if(voice!="Unknown") - usr << "You deactivate the voice synthesizer." - voice = "Unknown" - else - usr << "The voice synthesizer is already deactivated." - return - -/obj/item/clothing/mask/gas/voice/space_ninja/proc/switchm() - set name = "Switch Mode" - set desc = "Switches between Night Vision, Meson, or Thermal vision modes." - set category = "Object" - //Have to reset these manually since life.dm is retarded like that. Go figure. - switch(mode) - if(1) - mode=2 - usr.see_in_dark = 2 - usr << "Switching mode to Thermal Scanner." - if(2) - mode=3 - usr.see_invisible = 0 - usr.sight &= ~SEE_MOBS - usr << "Switching mode to Meson Scanner." - if(3) - mode=1 - usr.sight &= ~SEE_TURFS - usr << "Switching mode to Night Vision." - -/obj/item/clothing/mask/gas/voice/space_ninja/examine() - set src in view() - ..() - var/mode = "Night Vision" - var/voice = "inactive" - switch(mode) - if(1) - mode = "Night Vision" - if(2) - mode = "Thermal Scanner" - if(3) - mode = "Meson Scanner" - if(vchange==0) - voice = "inactive" - else - voice = "active" - usr << "[mode] is active." - usr << "Voice mimicking algorithm is set to [voice]." \ No newline at end of file + ..() \ No newline at end of file diff --git a/code/modules/admin/verbs/striketeam.dm b/code/modules/admin/verbs/striketeam.dm index c26389ee6b7..6e3a66961e4 100644 --- a/code/modules/admin/verbs/striketeam.dm +++ b/code/modules/admin/verbs/striketeam.dm @@ -118,11 +118,11 @@ var/global/sent_strike_team = 0 new_commando.equip_if_possible(new /obj/item/weapon/sword(new_commando), new_commando.slot_l_store) new_commando.equip_if_possible(new /obj/item/weapon/flashbang(new_commando), new_commando.slot_r_store) - new_commando.equip_if_possible(new /obj/item/weapon/tank/emergency_oxygen(new_commando), new_commando.slot_belt) + new_commando.equip_if_possible(new /obj/item/weapon/tank/emergency_oxygen(new_commando), new_commando.slot_s_store) var/obj/item/weapon/gun/revolver/GUN = new /obj/item/weapon/gun/revolver/mateba(new_commando) GUN.bullets = 7 - new_commando.equip_if_possible(GUN, new_commando.slot_s_store) + new_commando.equip_if_possible(GUN, new_commando.slot_belt) // new_commando.equip_if_possible(new /obj/item/weapon/gun/energy/pulse_rifle(new_commando), new_commando.slot_l_hand) /*Commented out because Commandos now have their rifles spawn in front of them, along with operation manuals. Useful for copy pasta since I'm lazy.*/ @@ -138,6 +138,8 @@ Useful for copy pasta since I'm lazy.*/ G = pick(commandos) new_commando.mind.key = G.key//For mind stuff. new_commando.client = G.client + new_commando.internal = new_commando.s_store + new_commando.internals.icon_state = "internal1" del(G) else new_commando.key = "null" @@ -169,514 +171,4 @@ Useful for copy pasta since I'm lazy.*/ del(BOMB) message_admins("\blue [key_name_admin(usr)] has spawned a CentCom strike squad.", 1) - log_admin("[key_name(usr)] used Spawn Death Squad.") - -//SPACE NINJAS============================= -/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 attitude." - if(!src.authenticated || !src.holder) - src << "Only administrators may use this command." - return - if(!ticker.mode)//Apparently, this doesn't actually prevent anything. Huh - alert("The game hasn't started yet!") - return - if(alert("Are you sure you want to send in a space ninja?",,"Yes","No")=="No") - return - - TRYAGAIN - var/input = input(usr, "Please specify which mission the space ninja shall undertake.", "Specify Mission", "") - if(!input) - goto TRYAGAIN - - var/list/LOCLIST = list() - for(var/obj/landmark/X in world) - if (X.name == "carpspawn") - LOCLIST.Add(X) - if(!LOCLIST.len) - alert("No spawn location could be found. Aborting.") - return - - var/obj/landmark/STARTLOC = pick(LOCLIST) - - var/mob/living/carbon/human/new_ninja = new(STARTLOC.loc) - var/ninja_title = pick(ninja_titles) - var/ninja_name = pick(ninja_names) - new_ninja.gender = pick(MALE, FEMALE) - new_ninja.real_name = "[ninja_title] [ninja_name]" - new_ninja.age = rand(17,45) - new_ninja.b_type = pick("A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-") - new_ninja.dna.ready_dna(new_ninja) - new_ninja.mind = new - new_ninja.mind.current = new_ninja - new_ninja.mind.assigned_role = "Space Ninja" - new_ninja.mind.special_role = "Space Ninja" - new_ninja.mind.store_memory("Mission: \red [input].") - new_ninja.resistances += "alien_embryo" - - var/obj/item/device/radio/R = new /obj/item/device/radio/headset(new_ninja) - new_ninja.equip_if_possible(R, new_ninja.slot_ears) - new_ninja.equip_if_possible(new /obj/item/clothing/under/color/black(new_ninja), new_ninja.slot_w_uniform) - new_ninja.equip_if_possible(new /obj/item/clothing/shoes/space_ninja(new_ninja), new_ninja.slot_shoes) - new_ninja.equip_if_possible(new /obj/item/clothing/suit/space/space_ninja(new_ninja), new_ninja.slot_wear_suit) - new_ninja.equip_if_possible(new /obj/item/clothing/gloves/space_ninja(new_ninja), new_ninja.slot_gloves) - new_ninja.equip_if_possible(new /obj/item/clothing/head/helmet/space/space_ninja(new_ninja), new_ninja.slot_head) - new_ninja.equip_if_possible(new /obj/item/clothing/mask/gas/voice/space_ninja(new_ninja), new_ninja.slot_wear_mask) - new_ninja.equip_if_possible(new /obj/item/device/flashlight(new_ninja), new_ninja.slot_belt) - new_ninja.equip_if_possible(new /obj/item/weapon/plastique(new_ninja), new_ninja.slot_r_store) - new_ninja.equip_if_possible(new /obj/item/weapon/plastique(new_ninja), new_ninja.slot_l_store) - var/obj/item/weapon/tank/emergency_oxygen/OXYTANK = new /obj/item/weapon/tank/emergency_oxygen(new_ninja) - new_ninja.equip_if_possible(OXYTANK, new_ninja.slot_s_store) - - var/admin_name = src//In case admins want to spawn themselves as ninjas. Badmins - - var/mob/dead/observer/G - var/list/candidates = list() - for(G in world) - if(G.client) - if(((G.client.inactivity/10)/60) <= 5) - candidates.Add(G) - if(candidates.len) - G = input("Pick character to spawn as the Space Ninja", "Active Players", G) in candidates//It will auto-pick a person when there is only one candidate. - new_ninja.mind.key = G.key - new_ninja.client = G.client - del(G) - else - alert("Could not locate a suitable ghost. Aborting.") - del(new_ninja) - return - - new_ninja.internal = OXYTANK //So the poor ninja has something to breath when they spawn in spess. - new_ninja.internals.icon_state = "internal1" - - 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]" - - 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.") - - -//ABILITIES============================= - -/*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. -*/ -/mob/proc/ninjacost(var/C as num,var/X as num) - var/mob/living/carbon/human/U = src - var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit - if(U.stat||U.incorporeal_move) - U << "\red You must be conscious and solid to do this." - return 0 - else if(C&&S.charge[S.sbombs] smoke bombs remaining." - var/datum/effects/system/bad_smoke_spread/smoke = new /datum/effects/system/bad_smoke_spread() - smoke.set_up(10, 0, loc) - smoke.start() - playsound(loc, 'bamf.ogg', 50, 2) - return - -//9-10 Tile Teleport -//Click to to teleport 9-10 tiles in direction facing. -/mob/proc/ninjajaunt() - set name = "Phase Jaunt" - set desc = "Utilizes the internal VOID-shift device to rapidly transit in direction facing." - set category = "Ninja" - - var/C = 100 - if(ninjacost(C,1)) - var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit - var/list/turfs = new/list() - var/turf/picked - var/turf/mobloc = get_turf(loc) - var/safety = 0 - switch(dir)//This can be done better but really isn't worth it in my opinion. - if(NORTH) - //highest Y - //X the same - for(var/turf/T in orange(10)) - if(T.density) continue - if(T.x>world.maxx || T.x<1) continue - if(T.y>world.maxy || T.y<1) continue - if((T.y-mobloc.y)<9 || ((T.x+mobloc.x+1)-(mobloc.x*2))>2) continue - turfs += T - if(SOUTH) - //lowest Y - //X the same - for(var/turf/T in orange(10)) - if(T.density) continue - if(T.x>world.maxx || T.x<1) continue - if(T.y>world.maxy || T.y<1) continue - if((mobloc.y-T.y)<9 || ((T.x+mobloc.x+1)-(mobloc.x*2))>2) continue - turfs += T - if(EAST) - //highest X - //Y the same - for(var/turf/T in orange(10)) - if(T.density) continue - if(T.x>world.maxx || T.x<1) continue - if(T.y>world.maxy || T.y<1) continue - if((T.x-mobloc.x)<9 || ((T.y+mobloc.y+1)-(mobloc.y*2))>2) continue - turfs += T - if(WEST) - //lowest X - //Y the same - for(var/turf/T in orange(10)) - if(T.density) continue - if(T.x>world.maxx || T.x<1) continue - if(T.y>world.maxy || T.y<1) continue - if((mobloc.x-T.x)<9 || ((T.y+mobloc.y+1)-(mobloc.y*2))>2) continue - turfs += T - else - safety = 1 - if(turfs.len&&!safety)//Cancels the teleportation if no valid turf is found. Usually when teleporting near map edge. - picked = pick(turfs) - spawn(0) - playsound(loc, "sparks", 50, 1) - anim(mobloc,'mob.dmi',src,"phaseout") - - loc = picked - - spawn(0) - S.spark_system.start() - playsound(loc, 'Deconstruct.ogg', 50, 1) - playsound(loc, "sparks", 50, 1) - anim(loc,'mob.dmi',src,"phasein") - - spawn(0)//Any living mobs in teleport area are gibbed. - for(var/mob/living/M in picked) - if(M==src) continue - M.gib() - S.charge-=(C*10) - else - src << "\red The VOID-shift device is malfunctioning, teleportation failed." - return - -//Right Click Teleport -//Right click to teleport somewhere, almost exactly like admin jump to turf. -/mob/proc/ninjashift(var/turf/T in oview()) - set name = "Phase Shift" - set desc = "Utilizes the internal VOID-shift device to rapidly transit to a destination in view." - set category = null//So it does not show up on the panel but can still be right-clicked. - - var/C = 200 - if(ninjacost(C,1)) - var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit - if(!T.density) - var/turf/mobloc = get_turf(loc) - spawn(0) - playsound(loc, 'sparks4.ogg', 50, 1) - anim(mobloc,'mob.dmi',src,"phaseout") - - loc = T - - spawn(0) - S.spark_system.start() - playsound(loc, 'Deconstruct.ogg', 50, 1) - playsound(loc, 'sparks2.ogg', 50, 1) - anim(loc,'mob.dmi',src,"phasein") - - spawn(0)//Any living mobs in teleport area are gibbed. - for(var/mob/living/M in T) - if(M==src) continue - M.gib() - S.charge-=(C*10) - else - src << "\red You cannot teleport into solid walls." - return - -//EMP Pulse -//Disables nearby tech equipment. -/mob/proc/ninjapulse() - set name = "EM Burst" - set desc = "Disable any nearby technology with a electro-magnetic pulse." - set category = "Ninja" - - var/C = 250 - if(ninjacost(C,1)) - var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit - playsound(loc, 'EMPulse.ogg', 60, 2) - empulse(src, 4, 6) //Procs sure are nice. Slightly weaker than wizard's disable tch. - S.charge-=(C*10) - return - -//Summon Energy Blade -//Summons a blade of energy in active hand. -/mob/proc/ninjablade() - set name = "Energy Blade" - set desc = "Create a focused beam of energy in your active hand." - set category = "Ninja" - - var/C = 50 - if(ninjacost(C)) - var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit - if(!S.kamikaze) - if(!get_active_hand()&&!istype(get_inactive_hand(), /obj/item/weapon/blade)) - var/obj/item/weapon/blade/W = new() - W.spark_system.start() - playsound(src.loc, "sparks", 50, 1) - put_in_hand(W) - S.charge-=(C*10) - else - src << "\red You can only summon one blade. Try dropping an item first." - else//Else you can run around with TWO energy blades. I don't know why you'd want to but cool factor remains. - if(!get_active_hand()) - var/obj/item/weapon/blade/W = new() - put_in_hand(W) - if(!get_inactive_hand()) - var/obj/item/weapon/blade/W = new() - put_in_inactive_hand(W) - S.spark_system.start() - playsound(src.loc, "sparks", 50, 1) - return - -//Shoot Ninja Stars -//Shoots ninja stars at random people. -//This could be a lot better but I'm too tired atm. -/mob/proc/ninjastar() - set name = "Energy Star" - set desc = "Launches an energy star at a random living target." - set category = "Ninja" - - var/C = 30 - if(ninjacost(C)) - var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit - var/targets[]//So yo can shoot while yo throw dawg - targets = new() - for(var/mob/living/M in oview(7)) - if(M.stat==2) continue//Doesn't target corpses. - targets.Add(M) - if(targets.len) - var/mob/living/target=pick(targets)//The point here is to pick a random, living mob in oview to shoot stuff at. - - var/turf/curloc = loc - var/atom/targloc = get_turf(target) - if (!targloc || !istype(targloc, /turf) || !curloc) - return - if (targloc == curloc) - return - var/obj/bullet/neurodart/A = new /obj/bullet/neurodart(loc) - A.current = curloc - A.yo = targloc.y - curloc.y - A.xo = targloc.x - curloc.x - S.charge-=(C*10) - A.process() - else - src << "\red There are no targets in view." - 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. -/mob/proc/ninjaboost() - set name = "Adrenaline Boost" - set desc = "Inject a secret chemical that will counteract all movement-impairing effects." - set category = "Ninja" - - if(ninjacost(,3)) - var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit - //Wouldn't need to track adrenaline boosters if there was a miracle injection to get rid of paralysis and the like instantly. - //For now, adrenaline boosters ARE the miracle injection. Well, radium, really. - paralysis = 0 - stunned = 0 - weakened = 0 - spawn(30) - say(pick("A CORNERED FOX IS MORE DANGEROUS THAN A JACKAL!","HURT ME MOOORRREEE!","IMPRESSIVE!")) - spawn(70) - S.reagents.reaction(src, 2) - S.reagents.trans_id_to(src, "radium", S.amount_per_transfer_from_this) - src << "\red You are beginning to feal the after-effects of the injection." - S.aboost-- - return - -//KAMIKAZE============================= -//Or otherwise known as anime mode. Which also happens to be ridiculously powerful. - -//Allows for incorporeal movement. -//Also makes you move like you're on crack. -/mob/proc/ninjawalk() - set name = "Shadow Walk" - set desc = "Combines the VOID-shift and CLOAK-tech devices to freely move between solid matter. Toggle on or off." - set category = "Ninja" - - if(!usr.incorporeal_move) - incorporeal_move = 1 - density = 0 - src << "\blue You will now phase through solid matter." - else - incorporeal_move = 0 - density = 1 - src << "\blue You will no-longer phase through solid matter." - return - -/* -Added click-spam protection of 1 second. -Allows to gib up to five squares in a straight line. Seriously.*/ -/mob/proc/ninjaslayer() - set name = "Phase Slayer" - set desc = "Utilizes the internal VOID-shift device to mutilate creatures in a straight line." - set category = "Ninja" - - if(ninjacost()) - var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit - var/locx - var/locy - var/turf/mobloc = get_turf(loc) - var/safety = 0 - - switch(dir) - if(NORTH) - locx = mobloc.x - locy = (mobloc.y+5) - if(locy>world.maxy) - safety = 1 - if(SOUTH) - locx = mobloc.x - locy = (mobloc.y-5) - if(locy<1) - safety = 1 - if(EAST) - locy = mobloc.y - locx = (mobloc.x+5) - if(locx>world.maxx) - safety = 1 - if(WEST) - locy = mobloc.y - locx = (mobloc.x-5) - if(locx<1) - safety = 1 - else safety = 1 - if(!safety)//Cancels the teleportation if no valid turf is found. Usually when teleporting near map edge. - say("Ai Satsugai!") - verbs -= /mob/proc/ninjaslayer - var/turf/picked = locate(locx,locy,mobloc.z) - spawn(0) - playsound(loc, "sparks", 50, 1) - anim(mobloc,'mob.dmi',src,"phaseout") - - spawn(0) - for(var/turf/T in getline(mobloc, picked)) - spawn(0) - for(var/mob/living/M in T) - if(M==src) continue - spawn(0) - M.gib() - if(T==mobloc||T==picked) continue - spawn(0) - anim(T,'mob.dmi',src,"phasein") - - loc = picked - - spawn(0) - S.spark_system.start() - playsound(loc, 'Deconstruct.ogg', 50, 1) - playsound(loc, "sparks", 50, 1) - anim(loc,'mob.dmi',src,"phasein") - spawn(10) - verbs += /mob/proc/ninjaslayer - else - src << "\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. -/mob/proc/ninjamirage() - set name = "Spider Mirage" - set desc = "Utilizes the internal VOID-shift device to create decoys and teleport behind a random target." - set category = "Ninja" - - if(ninjacost())//Simply checks for stat. - var/obj/item/clothing/suit/space/space_ninja/S = src:wear_suit - var/targets[] - targets = new() - for(var/mob/living/M in oview(6)) - if(M.stat==2) continue//Doesn't target corpses. - targets.Add(M) - if(targets.len) - var/mob/living/target=pick(targets) - var/locx - var/locy - var/turf/mobloc = get_turf(target.loc) - var/safety = 0 - switch(target.dir) - if(NORTH) - locx = mobloc.x - locy = (mobloc.y-1) - if(locy<1) - safety = 1 - if(SOUTH) - locx = mobloc.x - locy = (mobloc.y+1) - if(locy>world.maxy) - safety = 1 - if(EAST) - locy = mobloc.y - locx = (mobloc.x-1) - if(locx<1) - safety = 1 - if(WEST) - locy = mobloc.y - locx = (mobloc.x+1) - if(locx>world.maxx) - safety = 1 - else safety=1 - - if(!safety) - say("Kumo no Shinkiro!") - verbs -= /mob/proc/ninjamirage - var/turf/picked = locate(locx,locy,mobloc.z) - spawn(0) - playsound(loc, "sparks", 50, 1) - anim(mobloc,'mob.dmi',src,"phaseout") - - spawn(0) - var/limit = 4 - for(var/turf/T in oview(5)) - if(prob(20)) - spawn(0) - anim(T,'mob.dmi',src,"phasein") - limit-- - if(limit<=0) break - - loc = picked - dir = target.dir - - spawn(0) - S.spark_system.start() - playsound(loc, 'Deconstruct.ogg', 50, 1) - playsound(loc, "sparks", 50, 1) - anim(loc,'mob.dmi',src,"phasein") - - spawn(10) - verbs += /mob/proc/ninjamirage - else - src << "\red The VOID-shift device is malfunctioning, teleportation failed." - else - src << "\red There are no targets in view." - return \ No newline at end of file + log_admin("[key_name(usr)] used Spawn Death Squad.") \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 8f0c2e42aa7..896caa782de 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -597,39 +597,10 @@ src.updateicon() if(ishuman(user)) - var/mob/living/carbon/human/U = user - if(istype(U.gloves, /obj/item/clothing/gloves/space_ninja)&&U.gloves:candrain&&!U.gloves:draining) - var/obj/item/clothing/suit/space/space_ninja/S = U.wear_suit - var/obj/item/clothing/gloves/space_ninja/G = U.gloves - user << "\blue Now charging battery..." - src << "\red Warning: Unauthorized access through sub-route 12, block C, detected." - G.draining = 1 - if(cell&&cell.charge) - var/drain = 0 - var/maxcapacity = 0 - var/totaldrain = 0 - while(G.candrain&&cell.charge>0&&!maxcapacity) - drain = rand(G.mindrain,G.maxdrain) - if(cell.chargeS.maxcharge) - drain = S.maxcharge-S.charge - maxcapacity = 1 - if (do_after(U,10)) - spark_system.start() - playsound(src.loc, "sparks", 50, 1) - cell.charge-=drain - S.charge+=drain - totaldrain+=drain - else break - U << "\blue Gained [totaldrain] energy from [src]." - G.draining = 0 - return - else - U << "\red Their battery has run dry of power. You must find another source." + 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)("CYBORG",src,user:wear_suit,user:gloves) return - /mob/living/silicon/robot/proc/allowed(mob/M) //check if it doesn't require any access at all if(src.check_access(null)) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index bc0e73bd40c..3896950da65 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -455,42 +455,8 @@ if(stat & (BROKEN|MAINT)) return if(ishuman(user)) - var/mob/living/carbon/human/U = user - if(istype(U.gloves, /obj/item/clothing/gloves/space_ninja)&&U.gloves:candrain&&!U.gloves:draining) - var/obj/item/clothing/suit/space/space_ninja/S = U.wear_suit - var/obj/item/clothing/gloves/space_ninja/G = U.gloves - user << "\blue Now charging battery..." - if(cell&&cell.charge) - var/drain = 0//To drain from battery. - var/maxcapacity = 0//Safety check for full battery. - var/totaldrain = 0//Total energy drained. - G.draining = 1 - var/datum/effects/system/spark_spread/spark_system = new /datum/effects/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - while(G.candrain&&cell.charge>0&&!maxcapacity) - drain = rand(G.mindrain,G.maxdrain) - if(cell.chargeS.maxcharge) - drain = S.maxcharge-S.charge - maxcapacity = 1//Reached maximum battery capacity. - if (do_after(U,10)) - spark_system.start() - playsound(src.loc, "sparks", 50, 1) - cell.charge-=drain - S.charge+=drain - totaldrain+=drain - else break - U << "\blue Gained [totaldrain] energy from the APC." - G.draining = 0 - if(!emagged) - flick("apc-spark", src) - emagged = 1 - locked = 0 - updateicon() - return - else - U << "\red This APC has run dry of power. You must find another source." + 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)("APC",src,user:wear_suit,user:gloves) return // do APC interaction user.machine = src diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index b3ae36f188c..8c4dce7f814 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -184,37 +184,8 @@ if(stat & BROKEN) return if(ishuman(user)) - var/mob/living/carbon/human/U = user - if(istype(U.gloves, /obj/item/clothing/gloves/space_ninja)&&U.gloves:candrain&&!U.gloves:draining) - var/obj/item/clothing/suit/space/space_ninja/S = U.wear_suit - var/obj/item/clothing/gloves/space_ninja/G = U.gloves - user << "\blue Now charging battery..." - if(charge) - G.draining = 1 - var/drain = 0 - var/maxcapacity = 0 - var/totaldrain = 0 - var/datum/effects/system/spark_spread/spark_system = new /datum/effects/system/spark_spread() - spark_system.set_up(5, 0, src.loc) - while(G.candrain&&charge>0&&!maxcapacity) - drain = rand(G.mindrain,G.maxdrain) - if(chargeS.maxcharge) - drain = S.maxcharge-S.charge - maxcapacity = 1 - if (do_after(U,10)) - spark_system.start() - playsound(src.loc, "sparks", 50, 1) - charge-=drain - S.charge+=drain - totaldrain+=drain - else break - U << "\blue Gained [totaldrain] energy from the SMES cell." - G.draining = 0 - return - else - U << "\red This SMES cell has run dry of power. You must find another source." + 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)("SMES",src,user:wear_suit,user:gloves) return interact(user) diff --git a/tgstation.dme b/tgstation.dme index c8feaed2c9d..e5482c3cbf3 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -35,6 +35,7 @@ #define FILE_DIR "code/game/gamemodes/cult" #define FILE_DIR "code/game/gamemodes/events" #define FILE_DIR "code/game/gamemodes/extended" +#define FILE_DIR "code/game/gamemodes/extra" #define FILE_DIR "code/game/gamemodes/malfunction" #define FILE_DIR "code/game/gamemodes/meteor" #define FILE_DIR "code/game/gamemodes/nuclear" @@ -327,6 +328,9 @@ #include "code\game\gamemodes\events\clang.dm" #include "code\game\gamemodes\events\dust.dm" #include "code\game\gamemodes\extended\extended.dm" +#include "code\game\gamemodes\extra\ninja_abilities.dm" +#include "code\game\gamemodes\extra\ninja_equipment.dm" +#include "code\game\gamemodes\extra\space_ninja.dm" #include "code\game\gamemodes\malfunction\Malf_Modules.dm" #include "code\game\gamemodes\malfunction\malfunction.dm" #include "code\game\gamemodes\meteor\meteor.dm" @@ -790,5 +794,5 @@ #include "code\WorkInProgress\recycling\scrap.dm" #include "code\WorkInProgress\recycling\sortingmachinery.dm" #include "interface\skin.dmf" -#include "maps\tgstation.2.0.7.dmm" +#include "maps\test_map.dmm" // END_INCLUDE