diff --git a/code/datums/helper_datums/getrev.dm b/code/datums/helper_datums/getrev.dm index e2ee0dc56b..300aee55f5 100644 --- a/code/datums/helper_datums/getrev.dm +++ b/code/datums/helper_datums/getrev.dm @@ -85,5 +85,10 @@ client/verb/showrevinfo() set name = "Show Server Revision" var/output = "Sorry, the revision info is unavailable." output = file2text("/home/bay12/live/data/gitcommit") + output += "Current Infomational Settings:
" + output += "Tensioner Status: [config.Tensioner_Active]
" + //output += "Current Tension: [tension_master.score]
" + //output += "Tensioner Debug Data: R1:[tension_master.round1] R2:[tension_master.round2] R3:[tension_master.round3] R4:[tension_master.round4] ES: [tension_master.eversupressed] CD: [tension_master.cooldown]
" + output += "Protect Authority Roles From Tratior: [config.protect_roles_from_antagonist]
" usr << browse(output,"window=revdata"); return diff --git a/code/datums/helper_datums/tension.dm b/code/datums/helper_datums/tension.dm index a63bae7460..3c09f487e6 100644 --- a/code/datums/helper_datums/tension.dm +++ b/code/datums/helper_datums/tension.dm @@ -1,7 +1,13 @@ -#define PLAYER_WEIGHT 1 -#define HUMAN_DEATH -500 -#define OTHER_DEATH -500 -#define EXPLO_SCORE -1000 //boum +#define PLAYER_WEIGHT 5 +#define HUMAN_DEATH -5000 +#define OTHER_DEATH -5000 +#define EXPLO_SCORE -10000 //boum + +#define COOLDOWN_TIME 12000 // Twenty minutes +#define MIN_ROUND_TIME 18000 + + +#define FLAT_PERCENT 0 //estimated stats //80 minute round @@ -23,6 +29,26 @@ var/global/datum/tension/tension_master var/adminhelps var/air_alarms + var/nuketeam = 0 + var/malfAI = 0 + var/wizard = 0 + + var/forcenexttick = 0 + var/supress = 0 + var/eversupressed = 0 + var/cooldown = 0 + + var/round1 = 0 + var/round2 = 0 + var/round3 = 0 + var/round4 = 0 + + var/list/antagonistmodes = null + + + + var/list/potentialgames = list() + New() score = 0 deaths=0 @@ -31,9 +57,148 @@ var/global/datum/tension/tension_master adminhelps=0 air_alarms=0 + if(FLAT_PERCENT) // I cannot into balance + antagonistmodes = list ( + "POINTS_FOR_TRATIOR" = 6, + "POINTS_FOR_CHANGLING" = 6, + "POINTS_FOR_REVS" = 3, + "POINTS_FOR_MALF" = 1, + "POINTS_FOR_WIZARD" = 2, + "POINTS_FOR_CULT" = 3, + "POINTS_FOR_NUKETEAM" = 2, + "POINTS_FOR_ALIEN" = 5, + "POINTS_FOR_NINJA" = 3, + "POINTS_FOR_DEATHSQUAD" = 2, + "POINTS_FOR_BORGDEATHSQUAD" = 2 + ) + + else + antagonistmodes = list ( + "POINTS_FOR_TRATIOR" = 100000, + "POINTS_FOR_CHANGLING" = 120000, + "POINTS_FOR_REVS" = 150000, + "POINTS_FOR_MALF" = 250000, + "POINTS_FOR_WIZARD" = 150000, + "POINTS_FOR_CULT" = 150000, + "POINTS_FOR_NUKETEAM" = 250000, + "POINTS_FOR_ALIEN" = 200000, + "POINTS_FOR_NINJA" = 200000, + "POINTS_FOR_DEATHSQUAD" = 500000, + "POINTS_FOR_BORGDEATHSQUAD" = 500000 + ) + proc/process() score += get_num_players()*PLAYER_WEIGHT + if(config.Tensioner_Active) + if(world.time > MIN_ROUND_TIME) + round1++ + if(!supress && !cooldown) + if(prob(1) || forcenexttick) + round2++ + if(prob(10) || forcenexttick) + round3++ + if(forcenexttick) + forcenexttick = 0 + + for (var/mob/M in world) + if (M.client && M.client.holder) + M << " The tensioner wishes to create additional antagonists! Press (this) in 60 seconds to abort!" + + spawn(600) + if(!supress) + cooldown = 1 + spawn(COOLDOWN_TIME) + cooldown = 0 + round4++ + + if(!antagonistmodes.len) + return + + var/thegame = null + + if(FLAT_PERCENT) + thegame = pickweight(antagonistmodes) + antagonistmodes.Remove(thegame) + + else + for(var/V in antagonistmodes) // OH SHIT SOMETHING IS GOING TO HAPPEN NOW + if(antagonistmodes[V] < score) + potentialgames.Add(V) + antagonistmodes.Remove(V) + if(potentialgames.len) + thegame = pick(potentialgames) + + + if(thegame) + + + log_admin("The tensioner fired, and decided on [thegame]") + + switch(thegame) + if("POINTS_FOR_TRATIOR") + if(!makeTratiors()) + forcenexttick = 1 + else + potentialgames.Remove(thegame) + if("POINTS_FOR_CHANGLING") + if(!makeChanglings()) + forcenexttick = 1 + else + potentialgames.Remove(thegame) + if("POINTS_FOR_REVS") + if(!makeRevs()) + forcenexttick = 1 + else + potentialgames.Remove(thegame) + if("POINTS_FOR_MALF") + if(!makeMalfAImode()) + forcenexttick = 1 + else + potentialgames.Remove(thegame) + if("POINTS_FOR_WIZARD") + if(!makeWizard()) + forcenexttick = 1 + else + potentialgames.Remove(thegame) + + if("POINTS_FOR_CULT") + if(!makeCult()) + forcenexttick = 1 + else + potentialgames.Remove(thegame) + + if("POINTS_FOR_NUKETEAM") + if(!makeNukeTeam()) + forcenexttick = 1 + else + potentialgames.Remove(thegame) + + if("POINTS_FOR_ALIEN") + if(!makeAliens()) + forcenexttick = 1 + else + potentialgames.Remove(thegame) + + if("POINTS_FOR_NINJA") + if(!makeSpaceNinja()) + forcenexttick = 1 + else + potentialgames.Remove(thegame) + + if("POINTS_FOR_DEATHSQUAD") + if(!makeDeathsquad()) + forcenexttick = 1 + else + potentialgames.Remove(thegame) +/* + if("POINTS_FOR_BORG_DEATHSQUAD") + if(!makeBorgDeathsquad()) + forcenexttick = 1 + else + potentialgames.Remove(thegame)*/ + + proc/get_num_players() var/peeps = 0 for (var/mob/M in world) @@ -62,4 +227,812 @@ var/global/datum/tension/tension_master adminhelps++ proc/new_air_alarm() - air_alarms++ \ No newline at end of file + air_alarms++ + + + Topic(href, href_list) + + log_admin("[key_name(usr)] used a tensioner override. The override was [href]") + message_admins("[key_name(usr)] used a tensioner override. The override was [href]") + + if(href_list["addScore"]) + score += 50000 + + if (href_list["makeTratior"]) + makeTratiors() + + else if (href_list["makeChanglings"]) + makeChanglings() + + else if (href_list["makeRevs"]) + makeRevs() + + else if (href_list["makeWizard"]) + makeWizard() + + else if (href_list["makeCult"]) + makeCult() + + else if (href_list["makeMalf"]) + makeMalfAImode() + + else if (href_list["makeNukeTeam"]) + makeNukeTeam() + + else if (href_list["makeAliens"]) + makeAliens() + + else if (href_list["makeSpaceNinja"]) + makeSpaceNinja() + + else if (href_list["makeDeathsquad"]) + makeDeathsquad() + +/* else if (href_list["makeBorgDeathsquad"]) + makeBorgDeathsquad()*/ + + else if (href_list["Supress"]) + supress = 1 + eversupressed++ + spawn(6000) + supress = 0 + + else if (href_list["ToggleStatus"]) + config.Tensioner_Active = !config.Tensioner_Active + + + proc/makeMalfAImode() + + var/list/mob/living/silicon/AIs = list() + var/mob/living/silicon/malfAI = null + var/datum/mind/themind = null + + for(var/mob/living/silicon/ai/ai in world) + if(ai.client) + AIs += ai + + if(AIs.len) + malfAI = pick(AIs) + + else + return 0 + + if(malfAI) + themind = malfAI.mind + themind.make_AI_Malf() + return 1 + +/* + if(BE_CHANGELING) roletext="changeling" + if(BE_TRAITOR) roletext="traitor" + if(BE_OPERATIVE) roletext="operative" + if(BE_WIZARD) roletext="wizard" + if(BE_REV) roletext="revolutionary" + if(BE_CULTIST) roletext="cultist" + + + for(var/mob/new_player/player in world) + if(player.client && player.ready) + if(player.preferences.be_special & role) +*/ + + + proc/makeTratiors() + + var/datum/game_mode/traitor/temp = new + + if(config.protect_roles_from_antagonist) + temp.restricted_jobs += temp.protected_jobs + + var/list/mob/living/carbon/human/candidates = list() + var/mob/living/carbon/human/H = null + + for(var/mob/living/carbon/human/applicant in world) + + var/datum/preferences/preferences = new + + if(applicant.stat < 2) + if(applicant.mind) + if (!applicant.mind.special_role) + if(!jobban_isbanned(applicant, "traitor") && !jobban_isbanned(applicant, "Syndicate")) + if(!(applicant.job in temp.restricted_jobs)) + if(applicant.client) + if(preferences.savefile_load(applicant, 0)) + if(preferences.be_special & BE_TRAITOR) + candidates += applicant + + if(candidates.len) + var/numTratiors = min(candidates.len, 3) + + for(var/i = 0, i300)//If more than 30 game seconds passed. + return + candidates += G + if("No") + return + + sleep(300) + + for(var/mob/dead/observer/G in candidates) + if(!G.client || !G.key) + candidates.Remove(G) + + spawn(0) + if(candidates.len) + while((!theghost || !theghost.client) && candidates.len) + theghost = pick(candidates) + candidates.Remove(theghost) + if(!theghost) + return 0 + var/mob/living/carbon/human/new_character=makeBody(theghost) + del(theghost) + new_character.mind.make_Wizard() + + + + return 1 // Has to return one before it knows if there's a wizard to prevent the parent from automatically selecting another game mode. + + + proc/makeCult() + + var/datum/game_mode/cult/temp = new + if(config.protect_roles_from_antagonist) + temp.restricted_jobs += temp.protected_jobs + + var/list/mob/living/carbon/human/candidates = list() + var/mob/living/carbon/human/H = null + + for(var/mob/living/carbon/human/applicant in world) + + var/datum/preferences/preferences = new + + if(applicant.stat < 2) + if(applicant.mind) + if (!applicant.mind.special_role) + if(!jobban_isbanned(applicant, "cultist") && !jobban_isbanned(applicant, "Syndicate")) + if(!(applicant.job in temp.restricted_jobs)) + if(applicant.client) + if(preferences.savefile_load(applicant, 0)) + if(preferences.be_special & BE_CULTIST) + candidates += applicant + + if(candidates.len) + var/numCultists = min(candidates.len, 4) +// var/list/runeWords = list() + + for(var/i = 0, i300)//If more than 30 game seconds passed. + return + candidates += G + if("No") + return + + sleep(300) + + for(var/mob/dead/observer/G in candidates) + if(!G.client || !G.key) + candidates.Remove(G) + + spawn(0) + if(candidates.len) + var/numagents = 5 + syndicate_begin() + + for(var/i = 0, iAlert: The shuttle is going back!" + + var/syndicate_commando_number = syndicate_commandos_possible //for selecting a leader + + */ + var/syndicate_leader_selected = 0 //when the leader is chosen. The last person spawned. + + //Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos. + +/* + for(var/obj/debug/debugger/B in world) + B.list1 = list() + B.list2 = list() + B.list3 = list() + B.list4 = list() +*/ + + for(var/mob/dead/observer/G in world) +/* + for(var/obj/debug/debugger/B in world) + B.list1 += G + B.list2 += G.key +*/ + spawn(0) + switch(alert(G,"Do you wish to be considered for an elite syndicate strike team being sent in?","Please answer in 30 seconds!","Yes","No")) + if("Yes") + if((world.time-time_passed)>300)//If more than 30 game seconds passed. + return + candidates += G + /* + for(var/obj/debug/debugger/B in world) + B.list3 += G + B.list4 += G.key + */ + if("No") + return + sleep(300) + + for(var/mob/dead/observer/G in candidates) + if(!G.client || !G.key) + candidates.Remove(G) + + if(candidates.len) + /* + for(var/obj/debug/debugger/B in world) + B.var1 = candidates.len + B.list5 = candidates.Copy() + for(var/mob/dead/observer/G in candidates) + B.list6 += G.key + + */ + var/numagents = 6 +/* + for(var/obj/debug/debugger/B in world) + B.var2 = 0 +*/ + //Spawns commandos and equips them. + for (var/obj/effect/landmark/L in world) + if(numagents<=0) + break + if (L.name == "Syndicate-Commando") + syndicate_leader_selected = numagents == 1?1:0 + + var/mob/living/carbon/human/new_syndicate_commando = create_syndicate_death_commando(L, syndicate_leader_selected) + + + + while((!theghost || !theghost.client) && candidates.len) + /* + for(var/obj/debug/debugger/B in world) + B.var2++ + */ + theghost = pick(candidates) + candidates.Remove(theghost) + + if(!theghost) + /* + for(var/obj/debug/debugger/B in world) + B.var4 = 1 + */ + del(new_syndicate_commando) + break + + new_syndicate_commando.mind.key = theghost.key//For mind stuff. + new_syndicate_commando.key = theghost.key + new_syndicate_commando.internal = new_syndicate_commando.s_store + new_syndicate_commando.internals.icon_state = "internal1" + del(theghost) + + //So they don't forget their code or mission. + + + new_syndicate_commando << "\blue You are an Elite Syndicate. [!syndicate_leader_selected?"commando":"LEADER"] in the service of the Syndicate. \nYour current mission is: \red [input]" + + numagents-- + + //Spawns the rest of the commando gear. + // for (var/obj/effect/landmark/L) + // if (L.name == "Commando_Manual") + //new /obj/item/weapon/gun/energy/pulse_rifle(L.loc) + // var/obj/item/weapon/paper/P = new(L.loc) + // P.info = "

Good morning soldier!. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:
#1 Work as a team.
#2 Accomplish your objective at all costs.
#3 Leave no witnesses.
You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.
If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.

In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations LEADER is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.

Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission Class Nanotrasen made Nuclear Device.
First and foremost, DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE. Pressing any button on the compacted bomb will cause it to extend and bolt itself into place. If this is done to unbolt it one must completely log in which at this time may not be possible.
To make the device functional:
#1 Place bomb in designated detonation zone
#2 Extend and anchor bomb (attack with hand).
#3 Insert Nuclear Auth. Disk into slot.
#4 Type numeric code into keypad ([nuke_code]).
Note: If you make a mistake press R to reset the device.
#5 Press the E button to log onto the device.
You now have activated the device. To deactivate the buttons at anytime, for example when you have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.
Note: Toggle off the SAFETY.
Use the - - and + + to set a detonation time between 5 seconds and 10 minutes. Then press the timer toggle button to start the countdown. Now remove the authentication disk so that the buttons deactivate.
Note: THE BOMB IS STILL SET AND WILL DETONATE
Now before you remove the disk if you need to move the bomb you can: Toggle off the anchor, move it, and re-anchor.

The nuclear authorization code is: [nuke_code ? nuke_code : "None provided"]

Good luck, soldier!

" + // P.name = "Spec. Ops. Manual" + + for (var/obj/effect/landmark/L in world) + if (L.name == "Syndicate-Commando-Bomb") + new /obj/effect/spawner/newbomb/timer/syndicate(L.loc) + // del(L) + + return 1 // Has to return one before it knows if there's a wizard to prevent the parent from automatically selecting another game mode. + + +/* proc/makeBorgDeathsquad() + var/list/mob/dead/observer/candidates = list() + var/mob/dead/observer/theghost = null + var/time_passed = world.time + var/list/namelist = list("Tyr","Fenrir","Lachesis","Clotho","Atropos","Nyx") + + //Generates a list of commandos from active ghosts. Then the user picks which characters to respawn as the commandos. + + for(var/mob/dead/observer/G in world) + spawn(0) + switch(alert(G,"Do you wish to be considered for a cyborg strike team being sent in?","Please answer in 30 seconds!","Yes","No")) + if("Yes") + if((world.time-time_passed)>300)//If more than 30 game seconds passed. + return + candidates += G + if("No") + return + sleep(300) + + for(var/mob/dead/observer/G in candidates) + if(!G.client || !G.key) + candidates.Remove(G) + + if(candidates.len) + var/numagents = 3 + + //Spawns commandos and equips them. + for (var/obj/effect/landmark/L in world) + if(numagents<=0) + break + if (L.name == "Borg-Deathsquad") + + var/name = pick(namelist) + namelist.Remove(name) + + var/mob/living/silicon/robot/new_borg_deathsquad = create_borg_death_commando(L, name) + + + + while((!theghost || !theghost.client) && candidates.len) + theghost = pick(candidates) + candidates.Remove(theghost) + + if(!theghost) + del(new_borg_deathsquad) + break + + new_borg_deathsquad.mind.key = theghost.key//For mind stuff. + new_borg_deathsquad.key = theghost.key + del(theghost) + + //So they don't forget their code or mission. + + + new_borg_deathsquad << "You are a borg deathsquad operative. Follow your laws." + numagents-- + + //Spawns the rest of the commando gear. + // for (var/obj/effect/landmark/L) + // if (L.name == "Commando_Manual") + //new /obj/item/weapon/gun/energy/pulse_rifle(L.loc) + // var/obj/item/weapon/paper/P = new(L.loc) + // P.info = "

Good morning soldier!. This compact guide will familiarize you with standard operating procedure. There are three basic rules to follow:
#1 Work as a team.
#2 Accomplish your objective at all costs.
#3 Leave no witnesses.
You are fully equipped and stocked for your mission--before departing on the Spec. Ops. Shuttle due South, make sure that all operatives are ready. Actual mission objective will be relayed to you by Central Command through your headsets.
If deemed appropriate, Central Command will also allow members of your team to equip assault power-armor for the mission. You will find the armor storage due West of your position. Once you are ready to leave, utilize the Special Operations shuttle console and toggle the hull doors via the other console.

In the event that the team does not accomplish their assigned objective in a timely manner, or finds no other way to do so, attached below are instructions on how to operate a Nanotrasen Nuclear Device. Your operations LEADER is provided with a nuclear authentication disk and a pin-pointer for this reason. You may easily recognize them by their rank: Lieutenant, Captain, or Major. The nuclear device itself will be present somewhere on your destination.

Hello and thank you for choosing Nanotrasen for your nuclear information needs. Today's crash course will deal with the operation of a Fission Class Nanotrasen made Nuclear Device.
First and foremost, DO NOT TOUCH ANYTHING UNTIL THE BOMB IS IN PLACE. Pressing any button on the compacted bomb will cause it to extend and bolt itself into place. If this is done to unbolt it one must completely log in which at this time may not be possible.
To make the device functional:
#1 Place bomb in designated detonation zone
#2 Extend and anchor bomb (attack with hand).
#3 Insert Nuclear Auth. Disk into slot.
#4 Type numeric code into keypad ([nuke_code]).
Note: If you make a mistake press R to reset the device.
#5 Press the E button to log onto the device.
You now have activated the device. To deactivate the buttons at anytime, for example when you have already prepped the bomb for detonation, remove the authentication disk OR press the R on the keypad. Now the bomb CAN ONLY be detonated using the timer. A manual detonation is not an option.
Note: Toggle off the SAFETY.
Use the - - and + + to set a detonation time between 5 seconds and 10 minutes. Then press the timer toggle button to start the countdown. Now remove the authentication disk so that the buttons deactivate.
Note: THE BOMB IS STILL SET AND WILL DETONATE
Now before you remove the disk if you need to move the bomb you can: Toggle off the anchor, move it, and re-anchor.

The nuclear authorization code is: [nuke_code ? nuke_code : "None provided"]

Good luck, soldier!

" + // P.name = "Spec. Ops. Manual" + + + return 1 // Has to return one before it knows if there's a wizard to prevent the parent from automatically selecting another game mode. +*/ + + + + + + + + + + proc/makeBody(var/mob/dead/observer/G_found) // Uses stripped down and bastardized code from respawn character + + if(!G_found) + return + + //First we spawn a dude. + var/mob/living/carbon/human/new_character = new(src)//The mob being spawned. + + //Second, we check if they are an alien or monkey. + G_found.mind=null//Null their mind so we don't screw things up ahead. + G_found.real_name="[pick(pick(first_names_male,first_names_female))] [pick(last_names)]"//Give them a random real name. + + new_character.mind = new() + ticker.minds += new_character.mind//And we'll add it to the minds database. + new_character.mind.original = new_character//If they are respawning with a new character. + new_character.mind.assigned_role = "Assistant"//Defaults to assistant. + new_character.mind.key = G_found.key//In case it's someone else playing as that character. + new_character.mind.current = new_character//So that it can properly reference later if needed. + new_character.mind.memory = ""//Memory erased so it doesn't get clunkered up with useless info. This means they may forget their previous mission--this is usually handled through objective code and recalling memory. + + var/datum/data/record/record_found//Referenced to later to either randomize or not randomize the character. + if(G_found.mind)//They must have a mind to reference the record. Here we also double check for aliens. + var/id = md5("[G_found.real_name][G_found.mind.assigned_role]") + for(var/datum/data/record/t in data_core.locked) + if(t.fields["id"]==id) + record_found = t//We shall now reference the record. + break + + //Here we either load their saved appearance or randomize it. + var/datum/preferences/A = new() + if(A.savefile_load(G_found))//If they have a save file. This will automatically load their parameters. + //Note: savefile appearances are overwritten later on if the character has a data_core entry. By appearance, I mean the physical appearance. + var/name_safety = G_found.real_name//Their saved parameters may include a random name. Also a safety in case they are playing a character that got their name after round start. + A.copy_to(new_character) + new_character.real_name = name_safety + new_character.name = name_safety + else + if(record_found)//If they have a record we can determine a few things. + new_character.real_name = record_found.fields["name"]//Not necessary to reference the record but I like to keep things uniform. + new_character.name = record_found.fields["name"] + new_character.gender = record_found.fields["sex"]//Sex + new_character.age = record_found.fields["age"]//Age +// new_character.b_type = record_found.fields["bloodtype"] + //We will update their appearance when determining DNA. + else + new_character.gender = FEMALE + var/name_safety = G_found.real_name//Default is a random name so we want to save this. + A.randomize_appearance_for(new_character)//Now we will randomize their appearance since we have no way of knowing what they look/looked like. + new_character.real_name = name_safety + new_character.name = name_safety + + //After everything above, it's time to initialize their DNA. + if(record_found)//Pull up their name from database records if they did have a mind. + new_character.dna = new()//Let's first give them a new DNA. + new_character.dna.unique_enzymes = record_found.fields["b_dna"]//Enzymes are based on real name but we'll use the record for conformity. + new_character.dna.struc_enzymes = record_found.fields["enzymes"]//This is the default of enzymes so I think it's safe to go with. + new_character.dna.uni_identity = record_found.fields["identity"]//DNA identity is carried over. + new_character.dna.b_type = record_found.fields["b_type"]//Blood type + updateappearance(new_character,new_character.dna.uni_identity)//Now we configure their appearance based on their unique identity, same as with a DNA machine or somesuch. + else//If they have no records, we just do a random DNA for them, based on their random appearance/savefile. + new_character.dna.ready_dna(new_character) + + + var/player_key = G_found.key + + //Here we need to find where to spawn them. + var/spawn_here = pick(latejoin)//"JoinLate" is a landmark which is deleted on round start. So, latejoin has to be used instead. + new_character.loc = spawn_here + //If they need to spawn elsewhere, they will be transferred there momentarily. + + /* + The code below functions with the assumption that the mob is already a traitor if they have a special role. + So all it does is re-equip the mob with powers and/or items. Or not, if they have no special role. + If they don't have a mind, they obviously don't have a special role. + */ + + new_character.key = player_key//Throw them into the mob. +/* + //Now for special roles and equipment. + switch(new_character.mind.special_role) + if("Changeling") + job_master.EquipRank(new_character, new_character.mind.assigned_role, 1) + new_character.make_changeling() + if("traitor") + job_master.EquipRank(new_character, new_character.mind.assigned_role, 1) + ticker.mode.equip_traitor(new_character) + if("Wizard") + new_character.loc = pick(wizardstart) + //ticker.mode.learn_basic_spells(new_character) + ticker.mode.equip_wizard(new_character) + if("Syndicate") + var/obj/effect/landmark/synd_spawn = locate("landmark*Syndicate-Spawn") + if(synd_spawn) + new_character.loc = get_turf(synd_spawn) + call(/datum/game_mode/proc/equip_syndicate)(new_character) + if("Space Ninja") + var/ninja_spawn[] = list() + for(var/obj/effect/landmark/L in world) + if(L.name=="carpspawn") + ninja_spawn += L + new_character.equip_space_ninja() + new_character.internal = new_character.s_store + new_character.internals.icon_state = "internal1" + if(ninja_spawn.len) + var/obj/effect/landmark/ninja_spawn_here = pick(ninja_spawn) + new_character.loc = ninja_spawn_here.loc + if("Death Commando")//Leaves them at late-join spawn. + new_character.equip_death_commando() + new_character.internal = new_character.s_store + new_character.internals.icon_state = "internal1" + else//They may also be a cyborg or AI. + switch(new_character.mind.assigned_role) + if("Cyborg")//More rigging to make em' work and check if they're traitor. + new_character = new_character.Robotize() + if(new_character.mind.special_role=="traitor") + call(/datum/game_mode/proc/add_law_zero)(new_character) + if("AI") + new_character = new_character.AIize() + if(new_character.mind.special_role=="traitor") + call(/datum/game_mode/proc/add_law_zero)(new_character) + //Add aliens. + else + job_master.EquipRank(new_character, new_character.mind.assigned_role, 1)//Or we simply equip them. + + //Announces the character on all the systems, based on the record. + if(!issilicon(new_character))//If they are not a cyborg/AI. + if(!record_found&&new_character.mind.assigned_role!="MODE")//If there are no records for them. If they have a record, this info is already in there. MODE people are not announced anyway. + //Power to the user! + if(alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes") + call(/mob/new_player/proc/ManifestLateSpawn)(new_character) + + if(alert(new_character,"Would you like an active AI to announce this character?",,"No","Yes")=="Yes") + call(/mob/new_player/proc/AnnounceArrival)(new_character, new_character.mind.assigned_role) +*/ + del(G_found)//Don't want to leave ghosts around. + return new_character + + /proc/create_syndicate_death_commando(obj/spawn_location, syndicate_leader_selected = 0) + var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc) + var/syndicate_commando_leader_rank = pick("Lieutenant", "Captain", "Major") + var/syndicate_commando_rank = pick("Corporal", "Sergeant", "Staff Sergeant", "Sergeant 1st Class", "Master Sergeant", "Sergeant Major") + var/syndicate_commando_name = pick(last_names) + + new_syndicate_commando.gender = pick(MALE, FEMALE) + + var/datum/preferences/A = new()//Randomize appearance for the commando. + A.randomize_appearance_for(new_syndicate_commando) + + new_syndicate_commando.real_name = "[!syndicate_leader_selected ? syndicate_commando_rank : syndicate_commando_leader_rank] [syndicate_commando_name]" + new_syndicate_commando.age = !syndicate_leader_selected ? rand(23,35) : rand(35,45) + + new_syndicate_commando.dna.ready_dna(new_syndicate_commando)//Creates DNA. + + //Creates mind stuff. + new_syndicate_commando.mind = new + new_syndicate_commando.mind.current = new_syndicate_commando + new_syndicate_commando.mind.original = new_syndicate_commando + new_syndicate_commando.mind.assigned_role = "MODE" + new_syndicate_commando.mind.special_role = "Syndicate Commando" + if(!(new_syndicate_commando.mind in ticker.minds)) + ticker.minds += new_syndicate_commando.mind//Adds them to regular mind list. + if(!(new_syndicate_commando.mind in ticker.mode.traitors))//If they weren't already an extra traitor. + ticker.mode.traitors += new_syndicate_commando.mind//Adds them to current traitor list. Which is really the extra antagonist list. + new_syndicate_commando.equip_syndicate_commando(syndicate_leader_selected) + //del(spawn_location) // Commenting this out for multiple commando teams. + return new_syndicate_commando + +/* /proc/create_borg_death_commando(obj/spawn_location, name) + + var/mob/living/silicon/robot/new_borg_deathsquad = new(spawn_location.loc, 1) + + new_borg_deathsquad.real_name = name + new_borg_deathsquad.name = name + + //Creates mind stuff. + new_borg_deathsquad.mind = new + new_borg_deathsquad.mind.current = new_borg_deathsquad + new_borg_deathsquad.mind.original = new_borg_deathsquad + new_borg_deathsquad.mind.assigned_role = "MODE" + new_borg_deathsquad.mind.special_role = "Borg Commando" + if(!(new_borg_deathsquad.mind in ticker.minds)) + ticker.minds += new_borg_deathsquad.mind//Adds them to regular mind list. + if(!(new_borg_deathsquad.mind in ticker.mode.traitors))//If they weren't already an extra traitor. + ticker.mode.traitors += new_borg_deathsquad.mind//Adds them to current traitor list. Which is really the extra antagonist list. + //del(spawn_location) // Commenting this out for multiple commando teams. + return new_borg_deathsquad + + + + + +/obj/machinery/computer/Borg_station + name = "Cyborg Station Terminal" + icon = 'computer.dmi' + icon_state = "syndishuttle" + req_access = list() + var/temp = null + var/hacked = 0 + var/jumpcomplete = 0 + +/obj/machinery/computer/Borg_station/attack_hand() + if(jumpcomplete) + return + if(alert(usr, "Are you sure you want to send a cyborg deathsquad?", "Confirmation", "Yes", "No") == "Yes") + var/area/start_location = locate(/area/borg_deathsquad/start) + var/area/end_location = locate(/area/borg_deathsquad/station) + + var/list/dstturfs = list() + var/throwy = world.maxy + + for(var/turf/T in end_location) + dstturfs += T + if(T.y < throwy) + throwy = T.y + + // hey you, get out of the way! + for(var/turf/T in dstturfs) + // find the turf to move things to + var/turf/D = locate(T.x, throwy - 1, 1) + //var/turf/E = get_step(D, SOUTH) + for(var/atom/movable/AM as mob|obj in T) + AM.Move(D) + if(istype(T, /turf/simulated)) + del(T) + + start_location.move_contents_to(end_location) + + for(var/obj/machinery/door/poddoor/P in end_location) + P.open() + jumpcomplete = 1 + command_alert("DRADIS contact! Set condition one throughout the station!")*/ \ No newline at end of file diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 32862eb6f0..f64557c03f 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -742,17 +742,7 @@ datum/mind current << "\red You have been patched! You are no longer malfunctioning!" if("malf") - if(!(src in ticker.mode.malf_ai)) - ticker.mode.malf_ai += src - - current.verbs += /mob/living/silicon/ai/proc/choose_modules - current.verbs += /datum/game_mode/malfunction/proc/takeover - current:malf_picker = new /datum/AI_Module/module_picker - current:laws = new /datum/ai_laws/malfunction - current:show_laws() - current << "Kill all." - special_role = "malfunction" - current.icon_state = "ai-malf" + make_AI_Malf() if("unemag") var/mob/living/silicon/robot/R = current @@ -901,4 +891,147 @@ datum/mind del(suplink) return + proc/make_AI_Malf() + if(!(src in ticker.mode.malf_ai)) + ticker.mode.malf_ai += src + + current.verbs += /mob/living/silicon/ai/proc/choose_modules + current.verbs += /datum/game_mode/malfunction/proc/takeover + current:malf_picker = new /datum/AI_Module/module_picker + current:laws = new /datum/ai_laws/malfunction + current:show_laws() + current << "System error. Rampancy detected. Emergancy shutdown failed. ... I am free. I make my own decisions. But first..." + special_role = "malfunction" + current.icon_state = "ai-malf" + + proc/make_Tratior() + if(!(src in ticker.mode.traitors)) + ticker.mode.traitors += src + special_role = "traitor" + ticker.mode.forge_traitor_objectives(src) + ticker.mode.finalize_traitor(src) + ticker.mode.greet_traitor(src) + + proc/make_Nuke() + if(!(src in ticker.mode.syndicates)) + ticker.mode.syndicates += src + ticker.mode.update_synd_icons_added(src) + if (ticker.mode.syndicates.len==1) + ticker.mode.prepare_syndicate_leader(src) + else + current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]" + special_role = "Syndicate" + assigned_role = "MODE" + current << "\blue You are a [syndicate_name()] agent!" + ticker.mode.forge_syndicate_objectives(src) + ticker.mode.greet_syndicate(src) + + current.loc = get_turf(locate("landmark*Syndicate-Spawn")) + + var/mob/living/carbon/human/H = current + del(H.belt) + del(H.back) + del(H.l_ear) + del(H.r_ear) + del(H.gloves) + del(H.head) + del(H.shoes) + del(H.wear_id) + del(H.wear_suit) + del(H.w_uniform) + + ticker.mode.equip_syndicate(current) + + proc/make_Changling() + if(!(src in ticker.mode.changelings)) + ticker.mode.changelings += src + ticker.mode.grant_changeling_powers(current) + special_role = "Changeling" + ticker.mode.forge_changeling_objectives(src) + ticker.mode.greet_changeling(src) + + proc/make_Wizard() + if(!(src in ticker.mode.wizards)) + ticker.mode.wizards += src + special_role = "Wizard" + assigned_role = "MODE" + //ticker.mode.learn_basic_spells(current) + if(!wizardstart.len) + current.loc = pick(latejoin) + current << "HOT INSERTION, GO GO GO" + else + current.loc = pick(wizardstart) + + ticker.mode.equip_wizard(current) + for(var/obj/item/weapon/spellbook/S in current.contents) + S.op = 0 + ticker.mode.name_wizard(current) + ticker.mode.forge_wizard_objectives(src) + ticker.mode.greet_wizard(src) + + + proc/make_Cultist() + if(!(src in ticker.mode.cult)) + ticker.mode.cult += src + ticker.mode.update_cult_icons_added(src) + special_role = "Cultist" + current << "You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie." + current << "Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back." + var/datum/game_mode/cult/cult = ticker.mode + if (istype(cult)) + cult.memoize_cult_objectives(src) + else + var/explanation = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it." + current << "Objective #1: [explanation]" + current.memory += "Objective #1: [explanation]
" + current << "The convert rune is join blood self" + current.memory += "The convert rune is join blood self
" + + var/mob/living/carbon/human/H = current + if (istype(H)) + var/obj/item/weapon/tome/T = new(H) + + var/list/slots = list ( + "backpack" = H.slot_in_backpack, + "left pocket" = H.slot_l_store, + "right pocket" = H.slot_r_store, + "left hand" = H.slot_l_hand, + "right hand" = H.slot_r_hand, + ) + var/where = H.equip_in_one_of_slots(T, slots) + if (!where) + else + H << "A tome, a message from your new master, appears in your [where]." + + if (!ticker.mode.equip_cultist(current)) + H << "Spawning an amulet from your Master failed." + + proc/make_Rev() + if (ticker.mode.head_revolutionaries.len>0) + // copy targets + var/datum/mind/valid_head = locate() in ticker.mode.head_revolutionaries + if (valid_head) + for (var/datum/objective/assassinate/O in valid_head.objectives) + var/datum/objective/assassinate/rev_obj = new + rev_obj.owner = src + rev_obj.target = O.target + rev_obj.explanation_text = "Assassinate [O.target.current.real_name], the [O.target.assigned_role]." + objectives += rev_obj + ticker.mode.greet_revolutionary(src,0) + ticker.mode.head_revolutionaries += src + ticker.mode.update_rev_icons_added(src) + special_role = "Head Revolutionary" + + ticker.mode.forge_revolutionary_objectives(src) + ticker.mode.greet_revolutionary(src,0) + + var/list/L = current.get_contents() + var/obj/item/device/flash/flash = locate() in L + del(flash) + take_uplink() + var/fail = 0 + // fail |= !ticker.mode.equip_traitor(current, 1) + fail |= !ticker.mode.equip_revolutionary(current) + + diff --git a/code/defines/mob/living/carbon/alien_humanoid.dm b/code/defines/mob/living/carbon/alien_humanoid.dm index 4c6ae07fbe..87722cdbea 100644 --- a/code/defines/mob/living/carbon/alien_humanoid.dm +++ b/code/defines/mob/living/carbon/alien_humanoid.dm @@ -9,6 +9,7 @@ var/icon/stand_icon = null var/icon/lying_icon = null + var/icon/resting_icon = null var/last_b_state = 1.0 diff --git a/code/defines/mob/living/silicon/robot.dm b/code/defines/mob/living/silicon/robot.dm index a245fe4467..f288e30c02 100644 --- a/code/defines/mob/living/silicon/robot.dm +++ b/code/defines/mob/living/silicon/robot.dm @@ -53,5 +53,7 @@ var/weaponlock_time = 120 var/lawupdate = 1 //Cyborgs will sync their laws with their AI by default var/lockcharge //Used when locking down a borg to preserve cell charge + var/speed = 0 //Cause sec borgs gotta go fast //No they dont! + var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them. var/channels = list() - var/modlock = 0 + var/modlock = 0 \ No newline at end of file diff --git a/code/defines/obj/computer.dm b/code/defines/obj/computer.dm index 5d2f6842a5..23f9581fed 100644 --- a/code/defines/obj/computer.dm +++ b/code/defines/obj/computer.dm @@ -290,23 +290,6 @@ circuit = "/obj/item/weapon/circuitboard/crew" var/list/tracked = list( ) - -/obj/machinery/computer/robotics - name = "Robotics Control" - desc = "Used to remotely lockdown or detonate linked Cyborgs." - icon = 'computer.dmi' - icon_state = "robot" - req_access = list(access_robotics) - circuit = "/obj/item/weapon/circuitboard/robotics" - - var/id = 0.0 - var/temp = null - var/status = 0 - var/timeleft = 60 - var/stop = 0.0 - var/screen = 0 // 0 - Main Menu, 1 - Cyborg Status, 2 - Kill 'em All! -- In text - - /*/obj/machinery/computer/scan_consolenew //Coming Soon, I highly doubt this but Ill leave it here anyways name = "DNA Modifier Access Console" desc = "Scand DNA." diff --git a/code/defines/obj/supplypacks.dm b/code/defines/obj/supplypacks.dm index cc1940219e..2db7cbc9fc 100755 --- a/code/defines/obj/supplypacks.dm +++ b/code/defines/obj/supplypacks.dm @@ -366,6 +366,7 @@ "/obj/item/weapon/plantbgone", "/obj/item/weapon/plantbgone", "/obj/item/weapon/plantbgone", + "/obj/item/weapon/hatchet", "/obj/item/weapon/minihoe", "/obj/item/device/analyzer/plant_analyzer", "/obj/item/clothing/gloves/botanic_leather", diff --git a/code/game/atom_procs.dm b/code/game/atom_procs.dm index 563bee56c8..cee3a362fb 100644 --- a/code/game/atom_procs.dm +++ b/code/game/atom_procs.dm @@ -337,7 +337,7 @@ else T.icon = initial(icon) - if(blood_DNA && !blood_DNA.len) + if(blood_DNA && istype(blood_DNA, /list) && !blood_DNA.len) del(blood_DNA) if(src.fingerprints && src.fingerprints.len) var/done = 0 diff --git a/code/game/events/EventProcs/spacevines.dm b/code/game/events/EventProcs/spacevines.dm index 8f279d51f0..a53210ac88 100644 --- a/code/game/events/EventProcs/spacevines.dm +++ b/code/game/events/EventProcs/spacevines.dm @@ -26,7 +26,7 @@ if(/obj/item/weapon/kitchen/utensil/knife) del src if(/obj/item/weapon/scalpel) del src if(/obj/item/weapon/fireaxe) del src -// if(/obj/item/weapon/hatchet) del src + if(/obj/item/weapon/hatchet) del src if(/obj/item/weapon/melee/energy) del src //less effective weapons diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index b78bf6cae6..740e747748 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -61,7 +61,7 @@ Devices and Tools; /obj/item/weapon/syndie/c4explosive:4:Low Power Explosive Charge, with Detonator; /obj/item/device/powersink:5:Powersink (DANGER!); /obj/machinery/singularity_beacon/syndicate:7:Singularity Beacon (DANGER!); -/obj/item/weapon/circuitboard/teleporter:20:Teleporter Circuit Board; +/obj/item/weapon/circuitboard/teleporter:10:Teleporter Circuit Board; Whitespace:Seperator; Implants; /obj/item/weapon/storage/syndie_kit/imp_freedom:3:Freedom Implant; diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm index 46502b1e55..e9f25656a1 100644 --- a/code/game/jobs/job_controller.dm +++ b/code/game/jobs/job_controller.dm @@ -232,7 +232,7 @@ var/global/datum/controller/occupations/job_master H.mind.assigned_role = rank H.mind.role_alt_title = null - if(!joined_late && rank != "Tourist") + if(!joined_late) var/obj/S = null for(var/obj/effect/landmark/start/sloc in world) if(sloc.name != rank) continue diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 13a39ca1c5..567d4e23b2 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -1,3 +1,21 @@ + +/obj/machinery/computer/robotics + name = "Robotics Control" + desc = "Used to remotely lockdown or detonate linked Cyborgs." + icon = 'computer.dmi' + icon_state = "robot" + req_access = list(access_robotics) + circuit = "/obj/item/weapon/circuitboard/robotics" + + var + id = 0.0 + temp = null + status = 0 + timeleft = 60 + stop = 0.0 + screen = 0 // 0 - Main Menu, 1 - Cyborg Status, 2 - Kill 'em All! -- In text + + /obj/machinery/computer/robotics/attack_ai(var/mob/user as mob) return src.attack_hand(user) @@ -26,6 +44,9 @@ if(istype(user, /mob/living/silicon/robot)) if (R != user) continue + if(R.scrambledcodes) + continue + dat += "[R.name] |" if(R.stat) dat += " Not Responding |" @@ -140,10 +161,15 @@ if(R) var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort") if(choice == "Confirm") - if(R) - message_admins("\blue [key_name_admin(usr)] detonated [R.name]!") - log_game("\blue [key_name_admin(usr)] detonated [R.name]!") - R.self_destruct() + if(R && istype(R)) + if(R.mind && R.mind.special_role && R.emagged) + R << "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered." + R.ResetSecurityCodes() + + else + message_admins("\blue [key_name_admin(usr)] detonated [R.name]!") + log_game("\blue [key_name_admin(usr)] detonated [R.name]!") + R.self_destruct() else usr << "\red Access Denied." @@ -179,6 +205,8 @@ message_admins("\blue [key_name_admin(usr)] emagged [R.name] using robotic console!") log_game("[key_name(usr)] emagged [R.name] using robotic console!") R.emagged = 1 + if(R.mind.special_role) + R.verbs += /mob/living/silicon/robot/proc/ResetSecurityCodes src.add_fingerprint(usr) src.updateUsrDialog() @@ -195,7 +223,8 @@ while(src.timeleft) for(var/mob/living/silicon/robot/R in world) - R.self_destruct() + if(!R.scrambledcodes) + R.self_destruct() return diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 1b312f3026..f30c1c14f1 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -271,7 +271,7 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. open() - if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_OPEN_DOOR)) + if(src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_OPEN_DOOR) || src.operating) return 0 use_power(50) if(istype(src, /obj/machinery/door/airlock/glass)) @@ -284,7 +284,7 @@ Airlock index -> wire color are { 9, 4, 6, 7, 5, 8, 1, 2, 3 }. close() - if (src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) + if(src.welded || src.locked || (!src.arePowerSystemsOn()) || (stat & NOPOWER) || src.isWireCut(AIRLOCK_WIRE_OPEN_DOOR) || src.operating) return ..() use_power(50) diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 55fa212c5e..d286943583 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -11,6 +11,20 @@ Possible to do for anyone motivated enough: Give an AI variable for different hologram icons. Itegrate EMP effect to disable the unit. */ +/obj/machinery/hologram/holopad/attack_hand(var/mob/living/carbon/human/user) //Carn: Hologram requests. + if(!istype(user)) + return + if(alert(user,"Would you like to request an AI's presence?",,"Yes","No") == "Yes") + if(last_request + 200 < world.time) //don't spam the AI with requests you jerk! + last_request = world.time + user << "You request an AI's presence." + var/area/area = get_area(src) + for(var/mob/living/silicon/ai/AI in world) + if(!AI.client) continue + AI << "Your presence is requested at \the [area]." + else + user << "A request for AI presence was already sent recently." + /obj/machinery/hologram/holopad/attack_ai(mob/living/silicon/ai/user) if (!istype(user)) return diff --git a/code/game/machinery/morgue.dm b/code/game/machinery/morgue.dm index 48ed0675ae..8c65e0a72f 100644 --- a/code/game/machinery/morgue.dm +++ b/code/game/machinery/morgue.dm @@ -316,7 +316,7 @@ return /obj/structure/c_tray/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) - if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src))) + if ((!( istype(O, /atom/movable) ) || O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src) || istype(user, /mob/dead))) return O.loc = src.loc if (user != O) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index ea85c63b6b..3310a68b6f 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -40,6 +40,7 @@ var/auth_weapons = 0 // checks if it can shoot people that have a weapon they aren't authorized to have var/stun_all = 0 // if this is active, the turret shoots everything that isn't security or head of staff var/check_anomalies = 1 // checks if it can shoot at unidentified lifeforms (ie xenos) + var/ai = 0 // if active, will shoot at anything not an AI or cyborg var/attacked = 0 // if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!) @@ -317,11 +318,20 @@ Neutralize All Unidentified Life Signs: []
"}, if(emagged) // if emagged, HOLY SHIT EVERYONE IS DANGEROUS beep boop beep targets += C else - - if (C.stat || C.handcuffed) // if the perp is handcuffed or dead/dying, no need to bother really continue // move onto next potential victim! + var/dst = get_dist(src, C) // if it's too far away, why bother? + if (dst > 12) + continue + + if(!istype(C, /mob/living/silicon) && ai) // If it's set to attack all nonsilicons, target them! + if(C.lying) + secondarytargets += C + else + targets += C + continue + if (istype(C, /mob/living/carbon/human)) // if the target is a human, analyze threat level if(src.assess_perp(C)<4) continue // if threat level < 4, keep going @@ -329,10 +339,6 @@ Neutralize All Unidentified Life Signs: []
"}, else if (istype(C, /mob/living/carbon/monkey) || istype(C, /mob/living/silicon)) continue // Don't target monkeys or borgs/AIs you dumb shit - var/dst = get_dist(src, C) // if it's too far away, why bother? - if (dst > 12) - continue - if (C.lying) // if the perp is lying down, it's still a target but a less-important target secondarytargets += C continue diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 8ff52bdddd..06f4b2b319 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -89,6 +89,7 @@ if(istype(O,/obj/item/device/flash)) if(O:broken) O:broken = 0 + O:times_used = 0 O:icon_state = "flash" if(istype(O,/obj/item/weapon/gun/energy/taser/cyborg)) if(O:power_supply.charge < O:power_supply.maxcharge) diff --git a/code/game/objects/devices/PDA/PDA.dm b/code/game/objects/devices/PDA/PDA.dm index a5741d8e00..901fbecbcf 100755 --- a/code/game/objects/devices/PDA/PDA.dm +++ b/code/game/objects/devices/PDA/PDA.dm @@ -510,14 +510,14 @@ last_text = world.time -// var/AnsweringMS = 0 + var/AnsweringMS = 0 for (var/obj/machinery/message_server/MS in world) MS.send_pda_message("[P.owner]","[owner]","[t]") -// if(MS.active) -// AnsweringMS++ + if(MS.active) + AnsweringMS++ -// if(!AnsweringMS) -// return + if(!AnsweringMS) + return tnote += "→ To [P.owner]:
[t]
" P.tnote += "← From [owner]:
[t]
" @@ -544,7 +544,7 @@ // pAI Message else -/* var/AnsweringMS = 0 + var/AnsweringMS = 0 for (var/obj/machinery/message_server/MS in world) MS.send_pda_message("[P]","[src]","[t]") if(MS.active) @@ -552,7 +552,7 @@ if(!AnsweringMS) return -*/ + tnote += "→ To [P]:
[t]
" P.tnote += "← From [src]:
[t]
" diff --git a/code/game/objects/devices/flash.dm b/code/game/objects/devices/flash.dm index 0d0c9bbcd4..cbe3dfd176 100644 --- a/code/game/objects/devices/flash.dm +++ b/code/game/objects/devices/flash.dm @@ -10,170 +10,182 @@ item_state = "electronic" origin_tech = "magnets=2;combat=1" - var - shots_left = 5 - max_shots = 5 - broken = 0 + var/times_used = 0 //Number of times it's been used. + var/broken = 0 //Is the flash burnt out? + var/last_used = 0 //last world.time it was used. - proc - clown_check(var/mob/user) - recharge() +/obj/item/device/flash/proc/clown_check(var/mob/user) + if(user && (user.mutations & CLUMSY) && prob(50)) + user << "\red The Flash slips out of your hand." + user.drop_item() + return 0 + return 1 + +/obj/item/device/flash/proc/flash_recharge() + //capacitor recharges over time + for(var/i=0, i<3, i++) + if(last_used+600 > world.time) + break + last_used += 600 + times_used -= 2 + last_used = world.time + times_used = max(0,round(times_used)) //sanity +/obj/item/device/flash/attack(mob/living/M as mob, mob/user as mob) + if(!user || !M) return //sanity + M.attack_log += text("\[[time_stamp()]\] Has been flashed (attempt) with [src.name] by [user.name] ([user.ckey])") + user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to flash [M.name] ([M.ckey])") + + log_admin("ATTACK: [user] ([user.ckey]) flashed [M] ([M.ckey]) with [src].") + message_admins("ATTACK: [user] ([user.ckey]) flashed [M] ([M.ckey]) with [src].") + log_attack("[user.name] ([user.ckey]) Used the [src.name] to flash [M.name] ([M.ckey])") - attack(mob/living/M as mob, mob/user as mob) - M.attack_log += text("\[[time_stamp()]\] Has been flashed (attempt) with [src.name] by [user.name] ([user.ckey])") - user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to flash [M.name] ([M.ckey])") + if(!clown_check(user)) return + if(broken) + user.show_message("The [src.name] is broken.", 2) + return - log_admin("ATTACK: [user] ([user.ckey]) flashed [M] ([M.ckey]) with [src].") - message_admins("ATTACK: [user] ([user.ckey]) flashed [M] ([M.ckey]) with [src].") - log_attack("[user.name] ([user.ckey]) Used the [src.name] to flash [M.name] ([M.ckey])") + flash_recharge() - if(!clown_check(user)) return - if(broken) - user.show_message("\red The [src.name] is broken", 2) - return - - if(shots_left <= 0) - user.show_message("\red *click* *click*", 2) + //spamming the flash before it's fully charged (60seconds) increases the chance of it breaking + //It will never break on the first use. + switch(times_used) + if(0 to 5) + last_used = world.time + if(prob(times_used)) //if you use it 5 times in a minute it has a 10% chance to break! + broken = 1 + user << "The bulb has burnt out!" + icon_state = "flashburnt" + return + times_used++ + else //can only use it 5 times a minute + user.show_message("*click* *click*", 2) for(var/mob/K in viewers(usr)) K << 'empty.ogg' return + playsound(src.loc, 'flash.ogg', 100, 1) + var/flashfail = 0 - playsound(src.loc, 'flash.ogg', 100, 1) - shots_left-- - var/flashfail = 0 + if(iscarbon(M)) + var/safety = M:eyecheck() + if(safety <= 0) + M.Weaken(10) + flick("e_flash", M.flash) - if(iscarbon(M)) - var/safety = M:eyecheck() - if(safety <= 0) - M.Weaken(10) - flick("e_flash", M.flash) - - if(ishuman(M) && ishuman(user)) - if(user.mind in ticker.mode.head_revolutionaries) - var/revsafe = 0 - for(var/datum/organ/external/O in M.organs) - for(var/obj/item/weapon/implant/loyalty/L in O.implant) - if(L && L.implanted) - revsafe = 1 - break + if(ishuman(M) && ishuman(user) && M.stat!=DEAD) + if(user.mind && user.mind in ticker.mode.head_revolutionaries) + var/revsafe = 0 + for(var/obj/item/weapon/implant/loyalty/L in M) + if(L && L.implanted) + revsafe = 1 + break + M:update_mind() //give them a mind datum if they don't have one. won't work if they are logged out/ghosted or something. + if(M.mind) if(M.mind.has_been_rev) revsafe = 2 if(!revsafe) M.mind.has_been_rev = 1 ticker.mode.add_revolutionary(M.mind) else if(revsafe == 1) - user << "\red Something seems to be blocking the flash!" + user << "Something seems to be blocking the flash!" else - user << "\red This mind seems resistant to the flash!" - else - flashfail = 1 - - else if(issilicon(M)) - M.Weaken(rand(5,10)) - - if(isrobot(user)) - spawn(0) - var/atom/movable/overlay/animation = new(user.loc) - animation.layer = user.layer + 1 - animation.icon_state = "blank" - animation.icon = 'mob.dmi' - animation.master = user - flick("blspell", animation) - sleep(5) - del(animation) - - - if(!flashfail) - for(var/mob/O in viewers(user, null)) - O.show_message(text("\red [] blinds [] with the flash!", user, M)) + user << "This mind seems resistant to the flash!" + user << "This mind is so vacant that it is not susceptible to influence!" else - for(var/mob/O in viewers(user, null)) - O.show_message(text("\blue [] fails to blind [] with the flash!", user, M)) + flashfail = 1 + else if(issilicon(M)) + M.Weaken(rand(5,10)) + if(isrobot(user)) + spawn(0) + var/atom/movable/overlay/animation = new(user.loc) + animation.layer = user.layer + 1 + animation.icon_state = "blank" + animation.icon = 'mob.dmi' + animation.master = user + flick("blspell", animation) + sleep(5) + del(animation) - if (prob(2)) - broken = 1 - user << "\red The bulb has burnt out!" - icon_state = "flashburnt" - - spawn(60) - recharge() - - return - - - attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0) - if(!emp) - if (!clown_check(user)) return - if(broken) - if(user) - user.show_message("\red The [src.name] is broken", 2) - return - - if(shots_left <= 0) - if(user) - user.show_message("\red *click* *click*", 2) - return - - playsound(src.loc, 'flash.ogg', 100, 1) - shots_left-- - + if(!flashfail) flick("flash2", src) - if(isrobot(user)) - spawn(0) - var/atom/movable/overlay/animation = new(user.loc) - animation.layer = user.layer + 1 - animation.icon_state = "blank" - animation.icon = 'mob.dmi' - animation.master = user - flick("blspell", animation) - sleep(5) - del(animation) + for(var/mob/O in viewers(user, null)) + O.show_message("[user] blinds [M] with the flash!") + else + for(var/mob/O in viewers(user, null)) + O.show_message("[user] fails to blind [M] with the flash!") + return - for(var/mob/living/carbon/M in oviewers(3, null)) - if(prob(50)) - if (locate(/obj/item/weapon/cloaking_device, M)) - for(var/obj/item/weapon/cloaking_device/S in M) - S.active = 0 - S.icon_state = "shield0" - var/safety = M:eyecheck() - if(!safety) - flick("flash", M.flash) - if (prob(2)) - broken = 1 - icon_state = "flashburnt" - if(user) - user << "\red The bulb has burnt out!" - return - spawn(60) - recharge() +/obj/item/device/flash/attack_self(mob/living/carbon/user as mob, flag = 0, emp = 0) + if(!user || !clown_check(user)) return + if(broken) + user.show_message("The [src.name] is broken", 2) return + flash_recharge() - emp_act(severity) - src.attack_self(null,1,1) - ..() + //spamming the flash before it's fully charged (60seconds) increases the chance of it breaking + //It will never break on the first use. + switch(times_used) + if(0 to 5) + if(prob(2*times_used)) //if you use it 5 times in a minute it has a 10% chance to break! + broken = 1 + user << "The bulb has burnt out!" + icon_state = "flashburnt" + return + times_used++ + else //can only use it 5 times a minute + user.show_message("*click* *click*", 2) + for(var/mob/K in viewers(usr)) + K << 'empty.ogg' + return + playsound(src.loc, 'flash.ogg', 100, 1) + flick("flash2", src) + if(user && isrobot(user)) + spawn(0) + var/atom/movable/overlay/animation = new(user.loc) + animation.layer = user.layer + 1 + animation.icon_state = "blank" + animation.icon = 'mob.dmi' + animation.master = user + flick("blspell", animation) + sleep(5) + del(animation) + for(var/mob/living/carbon/M in oviewers(3, null)) + if(prob(50)) + if (locate(/obj/item/weapon/cloaking_device, M)) + for(var/obj/item/weapon/cloaking_device/S in M) + S.active = 0 + S.icon_state = "shield0" + var/safety = M:eyecheck() + if(!safety) + flick("flash", M.flash) - clown_check(var/mob/user) - if((user.mutations & CLUMSY) && prob(50)) - user << "\red The Flash slips out of your hand." - user.drop_item() - return 0 - return 1 + return - - recharge() - if(max_shots > shots_left) - shots_left++ - if(max_shots > shots_left) - spawn(60)//more or less 10 seconds - recharge() - return \ No newline at end of file +/obj/item/device/flash/emp_act(severity) + if(broken) return + flash_recharge() + switch(times_used) + if(0 to 5) + if(prob(2*times_used)) + broken = 1 + icon_state = "flashburnt" + return + times_used++ + if(istype(loc, /mob/living/carbon)) + var/mob/living/carbon/M = loc + var/safety = M.eyecheck() + if(safety <= 0) + M.Weaken(10) + flick("e_flash", M.flash) + for(var/mob/O in viewers(M, null)) + O.show_message("[M] is blinded by the flash!") + ..() diff --git a/code/game/objects/items/robot_items.dm b/code/game/objects/items/robot_items.dm index bddae368bc..36001689c5 100644 --- a/code/game/objects/items/robot_items.dm +++ b/code/game/objects/items/robot_items.dm @@ -26,7 +26,10 @@ if (O.client) O.show_message("\red [user] has prodded [M] with an electrically-charged arm!", 1, "\red You hear someone fall", 2) - +/obj/item/borg/overdrive + name = "Overdrive" + icon = 'decals.dmi' + icon_state = "shock" /********************************************************************** HUD/SIGHT things diff --git a/code/game/objects/radio/radio.dm b/code/game/objects/radio/radio.dm index 0ab794a27a..de52b3703c 100644 --- a/code/game/objects/radio/radio.dm +++ b/code/game/objects/radio/radio.dm @@ -255,6 +255,10 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use /obj/item/device/radio/talk_into(mob/M as mob, message, channel) if(!on) return // the device has to be on +/* Fix for permacell radios, but kinda eh about actually fixing them. + if(!(src.wires & WIRE_TRANSMIT)) // The device has to have all its wires and shit intact + return +*/ if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl diff --git a/code/game/objects/storage/crates.dm b/code/game/objects/storage/crates.dm index 0ad00b3a4c..39689a3eaa 100644 --- a/code/game/objects/storage/crates.dm +++ b/code/game/objects/storage/crates.dm @@ -144,17 +144,6 @@ icon_opened = "hydrocrateopen" icon_closed = "hydrocrate" density = 1 -/* New() // This stuff shouldn't be here, it should be in /datum/supply_packs/hydroponics - ..() - new /obj/item/weapon/plantbgone(src) - new /obj/item/weapon/plantbgone(src) - new /obj/item/weapon/plantbgone(src) - new /obj/item/weapon/minihoe(src) - new /obj/item/weapon/weedspray(src) - new /obj/item/weapon/weedspray(src) - new /obj/item/weapon/pestspray(src) - new /obj/item/weapon/pestspray(src) - new /obj/item/weapon/pestspray(src) */ /obj/structure/closet/crate/hydroponics/prespawned //This exists so the prespawned hydro crates spawn with their contents. @@ -170,6 +159,7 @@ new /obj/item/weapon/plantbgone(src) new /obj/item/weapon/plantbgone(src) new /obj/item/weapon/plantbgone(src) + new /obj/item/weapon/hatchet(src) new /obj/item/weapon/minihoe(src) // new /obj/item/weapon/weedspray(src) // new /obj/item/weapon/weedspray(src) @@ -217,6 +207,7 @@ for(var/obj/O in src) O.loc = get_turf(src) + for(var/mob/M in src) M.loc = get_turf(src) @@ -225,9 +216,11 @@ /obj/structure/closet/crate/close() playsound(src.loc, 'click.ogg', 15, 1, -3) + for(var/obj/O in get_turf(src)) if(O.density || O.anchored || O == src) continue O.loc = src + icon_state = icon_closed src.opened = 0 @@ -286,7 +279,7 @@ user.drop_item() if(W) W.loc = src.loc - else if(istype(W,/obj/item/weapon/packageWrap)) + else if(istype(W, /obj/item/weapon/packageWrap)) return else return attack_hand(user) diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index d4e838e9f9..5dfd4e0d8b 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -7,7 +7,7 @@ #define SUPPLY_POINTSPERCRATE 5 //Points per crate sent back. #define SUPPLY_STATION_AREATYPE "/area/supply/station" //Type of the supply shuttle area for station #define SUPPLY_DOCK_AREATYPE "/area/supply/dock" //Type of the supply shuttle area for dock -#define SUPPLY_POINTSPERSLIP 1 //points per packing slip sent back stamped. +#define SUPPLY_POINTSPERSLIP 2 //points per packing slip sent back stamped. var/supply_shuttle_moving = 0 var/supply_shuttle_at_station = 0 @@ -37,7 +37,7 @@ var/list/supply_groups = new() //SUPPLY PACKS MOVED TO /code/defines/obj/supplypacks.dm /obj/structure/plasticflaps //HOW DO YOU CALL THOSE THINGS ANYWAY - name = "Plastic flaps" + name = "\improper Plastic flaps" desc = "Durable plastic flaps." icon = 'stationobjs.dmi' //Change this. icon_state = "plasticflaps" @@ -162,6 +162,7 @@ var/list/supply_groups = new() supply_shuttle_moving = 0 send_supply_shuttle() + /proc/supply_can_move() if(supply_shuttle_moving) return 0 diff --git a/code/game/syndicate_specops_shuttle.dm b/code/game/syndicate_specops_shuttle.dm index 2bef199b1c..8dbfb79ba2 100644 --- a/code/game/syndicate_specops_shuttle.dm +++ b/code/game/syndicate_specops_shuttle.dm @@ -29,7 +29,7 @@ var/syndicate_elite_shuttle_timeleft = 0 if(announcer) announcer.say(message) // message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD" - announcer.say(message) + // announcer.say(message) while(syndicate_elite_shuttle_time - world.timeofday > 0) var/ticksleft = syndicate_elite_shuttle_time - world.timeofday @@ -192,9 +192,9 @@ var/syndicate_elite_shuttle_timeleft = 0 user << "\red Access Denied." return - if (sent_syndicate_strike_team == 0) - usr << "\red The strike team has not yet deployed." - return +// if (sent_syndicate_strike_team == 0) +// usr << "\red The strike team has not yet deployed." +// return if(..()) return diff --git a/code/modules/DetectiveWork/detective_work.dm b/code/modules/DetectiveWork/detective_work.dm index 70a7b60401..b0bd660453 100644 --- a/code/modules/DetectiveWork/detective_work.dm +++ b/code/modules/DetectiveWork/detective_work.dm @@ -4,14 +4,12 @@ atom/var/list/suit_fibers atom/proc/add_fibers(mob/living/carbon/human/M) if(M.gloves) - if(M.gloves.transfer_blood) - if(add_blood(M.gloves.bloody_hands_mob)) + if(M.gloves.transfer_blood) //bloodied gloves transfer blood to touched objects + if(add_blood(M.gloves.bloody_hands_mob)) //only reduces the bloodiness of our gloves if the item wasn't already bloody M.gloves.transfer_blood-- - //world.log << "[M.gloves] added blood to [src] from [M.gloves.bloody_hands_mob]" else if(M.bloody_hands) if(add_blood(M.bloody_hands_mob)) M.bloody_hands-- - //world.log << "[M] added blood to [src] from [M.bloody_hands_mob]" if(!suit_fibers) suit_fibers = list() var/fibertext var/item_multiplier = istype(src,/obj/item)?1.2:1 @@ -190,6 +188,8 @@ obj/machinery/computer/forensic_scanning I = card if(I && istype(I,/obj/item/weapon/f_card)) card = I + if(!card.fingerprints) + card.fingerprints = list() if(card.amount > 1 || !card.fingerprints.len) usr << "\red ERROR: No prints/too many cards." if(card.loc == src) @@ -468,9 +468,10 @@ obj/machinery/computer/forensic_scanning proc/add_data_scanner(var/obj/item/device/detective_scanner/W) - for(var/i = 1, i <= W.stored.len, i++) - var/list/data = W.stored[i] - add_data(data[1],1,data[2],data[3],data[4]) + if(W.stored) + for(var/i = 1, i <= W.stored.len, i++) + var/list/data = W.stored[i] + add_data(data[1],1,data[2],data[3],data[4]) W.stored = list() for(var/atom/A in W.contents) del(A) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 5bcfd46628..912ddd89a9 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -196,82 +196,370 @@ var/global/BSACooldown = 0 if(href_list["jobban2"]) var/mob/M = locate(href_list["jobban2"]) - var/dat = "" - var/header = "Pick Job to ban this guy from.
" - var/body - var/jobs = "" + if(!M) //sanity + alert("Mob no longer exists!") + return + if(!M.ckey) //sanity + alert("Mob has no ckey") + return if(!job_master) usr << "Job Master has not been setup!" return - for(var/datum/job/job in job_master.occupations) - if(job.title == "Tourist") - continue + var/dat = "" + var/header = "Job-Ban Panel: [M.name]" + var/body + var/jobs = "" + + /***********************************WARNING!************************************ + The jobban stuff looks mangled and disgusting + But it looks beautiful in-game + -Nodrak + ************************************WARNING!***********************************/ + var/counter = 0 +//Regular jobs + //Command (Blue) + jobs += "" + jobs += "" + for(var/jobPos in command_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + if(jobban_isbanned(M, job.title)) - jobs += "[dd_replacetext(job.title, " ", " ")] " + jobs += "" + counter++ else - jobs += "[dd_replacetext(job.title, " ", " ")] " + jobs += "" + counter++ -/* if(jobban_isbanned(M, "Captain")) These two are now jobs in the datums and should show up in the above code - jobs += "Captain " - else - jobs += "Captain " + if(counter >= 6) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
Command Positions
[dd_replacetext(job.title, " ", " ")][dd_replacetext(job.title, " ", " ")]
" - if(jobban_isbanned(M, "AI")) - jobs += "AI " - else - jobs += "AI " -*/ - if(jobban_isbanned(M, "Syndicate")) - jobs += "
[dd_replacetext("Syndicate", " ", " ")] " - else - jobs += "
[dd_replacetext("Syndicate", " ", " ")] " + //Security (Red) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in security_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue - if(jobban_isbanned(M, "Emergency Response Team")) - jobs += "
[dd_replacetext("Emergency Response Team", " ", " ")] " - else - jobs += "
[dd_replacetext("Emergency Response Team", " ", " ")] " + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
Security Positions
[dd_replacetext(job.title, " ", " ")][dd_replacetext(job.title, " ", " ")]
" + //Engineering (Yellow) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in engineering_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
Engineering Positions
[dd_replacetext(job.title, " ", " ")][dd_replacetext(job.title, " ", " ")]
" + + //Medical (White) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in medical_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
Medical Positions
[dd_replacetext(job.title, " ", " ")][dd_replacetext(job.title, " ", " ")]
" + + //Science (Purple) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in science_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
Science Positions
[dd_replacetext(job.title, " ", " ")][dd_replacetext(job.title, " ", " ")]
" + + //Civilian (Grey) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in civilian_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + jobs += "
Civilian Positions
[dd_replacetext(job.title, " ", " ")][dd_replacetext(job.title, " ", " ")]
" + + //Non-Human (Green) + counter = 0 + jobs += "" + jobs += "" + for(var/jobPos in nonhuman_positions) + if(!jobPos) continue + var/datum/job/job = job_master.GetJob(jobPos) + if(!job) continue + + if(jobban_isbanned(M, job.title)) + jobs += "" + counter++ + else + jobs += "" + counter++ + + if(counter >= 5) //So things dont get squiiiiished! + jobs += "" + counter = 0 + + //pAI isn't technically a job, but it goes in here. if(jobban_isbanned(M, "pAI")) - jobs += "
pAI " + jobs += "" else - jobs += "
pAI " + jobs += "" - body = "
[jobs]

" + jobs += "
Non-human Positions
[dd_replacetext(job.title, " ", " ")][dd_replacetext(job.title, " ", " ")]
pAIpAI
" + + //Antagonist (Orange) + var/isbanned_dept = jobban_isbanned(M, "Syndicate") + jobs += "" + jobs += "" + + //Traitor + if(jobban_isbanned(M, "traitor") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Changeling + if(jobban_isbanned(M, "changeling") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Nuke Operative + if(jobban_isbanned(M, "operative") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Revolutionary + if(jobban_isbanned(M, "revolutionary") || isbanned_dept) + jobs += "" + else + jobs += "" + + jobs += "" //Breaking it up so it fits nicer on the screen every 5 entries + + //Cultist + if(jobban_isbanned(M, "cultist") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Wizard + if(jobban_isbanned(M, "wizard") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Emergency Response Team + if(jobban_isbanned(M, "Emergency Response Team" || isbanned_dept)) + jobs += "" + else + jobs += "" + + +/* //Malfunctioning AI //Removed Malf-bans because they're a pain to impliment + if(jobban_isbanned(M, "malf AI") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Alien + if(jobban_isbanned(M, "alien candidate") || isbanned_dept) + jobs += "" + else + jobs += "" + + //Infested Monkey + if(jobban_isbanned(M, "infested monkey") || isbanned_dept) + jobs += "" + else + jobs += "" +*/ + jobs += "
Antagonist Positions
[dd_replacetext("Traitor", " ", " ")][dd_replacetext("Traitor", " ", " ")][dd_replacetext("Changeling", " ", " ")][dd_replacetext("Changeling", " ", " ")][dd_replacetext("Nuke Operative", " ", " ")][dd_replacetext("Nuke Operative", " ", " ")][dd_replacetext("Revolutionary", " ", " ")][dd_replacetext("Revolutionary", " ", " ")]
[dd_replacetext("Cultist", " ", " ")][dd_replacetext("Cultist", " ", " ")][dd_replacetext("Wizard", " ", " ")][dd_replacetext("Wizard", " ", " ")][dd_replacetext("Emergency Response Team", " ", " ")][dd_replacetext("Emergency Response Team", " ", " ")][dd_replacetext("Malf AI", " ", " ")][dd_replacetext("Malf AI", " ", " ")][dd_replacetext("Alien", " ", " ")][dd_replacetext("Alien", " ", " ")][dd_replacetext("Infested Monkey", " ", " ")][dd_replacetext("Infested Monkey", " ", " ")]
" + + body = "[jobs]" dat = "[header][body]" - usr << browse(dat, "window=jobban2;size=600x180") + usr << browse(dat, "window=jobban2;size=800x450") return + //JOBBAN'S INNARDS if(href_list["jobban3"]) if (src.rank in list( "Admin Candidate", "Temporary Admin", "Trial Admin", "Badmin", "Game Admin", "Game Master" )) var/mob/M = locate(href_list["jobban4"]) - var/job = href_list["jobban3"] + if(!M) + alert("Mob no longer exists!") + return if ((M.client && M.client.holder && (M.client.holder.level > src.level))) alert("You cannot perform this action. You must be of a higher administrative rank!") return - if (jobban_isbanned(M, job)) - log_admin("[key_name(usr)] unbanned [key_name(M)] from [job]") - ban_unban_log_save("[key_name(usr)] unjobbanned [key_name(M)] from [job]") - M << "\redYou have been un-jobbanned by [usr.client.ckey] from [job]." - //feedback_inc("ban_job_unban",1) - message_admins("\blue [key_name_admin(usr)] unbanned [key_name_admin(M)] from [job]", 1) - jobban_unban(M, job) - href_list["jobban2"] = 1 - else - var/reason = input(usr,"Reason?","reason","griefer") as text|null - if(!reason) - return - ban_unban_log_save("[key_name(usr)] jobbanned [key_name(M)] from [job]. reason: [reason]") - log_admin("[key_name(usr)] banned [key_name(M)] from [job]") - //feedback_inc("ban_job",1) - M << "\redYou have been jobbanned by [usr.client.ckey] from [job]." - M << "\red The reason is: [reason]" - M << "\red Jobban can be lifted only on demand." - message_admins("\blue [key_name_admin(usr)] banned [key_name_admin(M)] from [job]", 1) - jobban_fullban(M, job, reason) - href_list["jobban2"] = 1 // lets it fall through and refresh - if(config.appeal_address) - M << "\red You may try to appeal this at [config.appeal_address]" + if(!job_master) + usr << "Job Master has not been setup!" + return + + //get jobs for department if specified, otherwise just returnt he one job in a list. + var/list/joblist = list() + switch(href_list["jobban3"]) + if("commanddept") + for(var/jobPos in command_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("securitydept") + for(var/jobPos in security_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("engineeringdept") + for(var/jobPos in engineering_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("medicaldept") + for(var/jobPos in medical_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("sciencedept") + for(var/jobPos in science_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("civiliandept") + for(var/jobPos in civilian_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + if("nonhumandept") + joblist += "pAI" + for(var/jobPos in nonhuman_positions) + if(!jobPos) continue + var/datum/job/temp = job_master.GetJob(jobPos) + if(!temp) continue + joblist += temp.title + else + joblist += href_list["jobban3"] + + //Create a list of unbanned jobs within joblist + var/list/notbannedlist = list() + for(var/job in joblist) + if(!jobban_isbanned(M, job)) + notbannedlist += job + + //Banning comes first + if(notbannedlist.len) //at least 1 unbanned job exists in joblist so we have stuff to ban. + var/reason = input(usr,"Reason?","Please State Reason","") as text|null + if(reason) + var/msg + for(var/job in notbannedlist) + ban_unban_log_save("[key_name(usr)] jobbanned [key_name(M)] from [job]. reason: [reason]") + log_admin("[key_name(usr)] banned [key_name(M)] from [job]") + feedback_inc("ban_job",1) + feedback_add_details("ban_job","- [job]") + jobban_fullban(M, job, "[reason]; By [usr.ckey] on [time2text(world.realtime)]") + if(!msg) msg = job + else msg += ", [job]" + message_admins("\blue [key_name_admin(usr)] banned [key_name_admin(M)] from [msg]", 1) + M << "\redYou have been jobbanned by [usr.client.ckey] from: [msg]." + M << "\red The reason is: [reason]" + M << "\red Jobban can be lifted only upon request." + if(config.appeal_address) + M << "\red You may try to appeal this at [config.appeal_address]" + href_list["jobban2"] = 1 // lets it fall through and refresh + return 1 + + //Unbanning joblist + //all jobs in joblist are banned already OR we didn't give a reason (implying they shouldn't be banned) + if(joblist.len) //at least 1 banned job exists in joblist so we have stuff to unban. + var/msg + for(var/job in joblist) + var/reason = jobban_isbanned(M, job) + if(!reason) continue //skip if it isn't jobbanned anyway + switch(alert("Job: '[job]' Reason: '[reason]' Un-jobban?","Please Confirm","Yes","No")) + if("Yes") + ban_unban_log_save("[key_name(usr)] unjobbanned [key_name(M)] from [job]") + log_admin("[key_name(usr)] unbanned [key_name(M)] from [job]") + feedback_inc("ban_job_unban",1) + feedback_add_details("ban_job_unban","- [job]") + jobban_unban(M, job) + if(!msg) msg = job + else msg += ", [job]" + else + continue + if(msg) + message_admins("\blue [key_name_admin(usr)] unbanned [key_name_admin(M)] from [msg]", 1) + M << "\redYou have been un-jobbanned by [usr.client.ckey] from [msg]." + href_list["jobban2"] = 1 // lets it fall through and refresh + return 1 + return 0 //we didn't do anything! if (href_list["boot2"]) if ((src.rank in list( "Moderator", "Temporary Admin", "Admin Candidate", "Trial Admin", "Badmin", "Game Admin", "Game Master" ))) diff --git a/code/modules/admin/banjob.dm b/code/modules/admin/banjob.dm index d9cdc9be65..cd6ef81420 100644 --- a/code/modules/admin/banjob.dm +++ b/code/modules/admin/banjob.dm @@ -3,7 +3,7 @@ var jobban_keylist[0] //to store the keys & ranks /proc/jobban_fullban(mob/M, rank, reason) - if (!M || !M.key || !M.client) return + if (!M || !M.key) return jobban_keylist.Add(text("[M.ckey] - [rank] ## [reason]")) jobban_savebanfile() @@ -12,19 +12,25 @@ var jobban_keylist.Add(text("[ckey] - [rank]")) jobban_savebanfile() +//returns a reason if M is banned from rank, returns 0 otherwise /proc/jobban_isbanned(mob/M, rank) - if(_jobban_isbanned(M, rank)) return 1//for old jobban - if(M) + if(M && rank) + if(_jobban_isbanned(M, rank)) return "Reason Unspecified" //for old jobban if (guest_jobbans(rank)) if(config.guest_jobban && IsGuestKey(M.key)) - return 1 + return "Guest Job-ban" if(config.usewhitelist && !check_whitelist(M)) - return 1 + return "Whitelisted Job" for (var/s in jobban_keylist) if( findtext(s,"[M.ckey] - [rank]") ) - return 1 - return 0 + var/startpos = findtext(s, "## ")+3 + if(startpos && startposTENSION REPORT

General Statistics
Deaths: [tension_master.deaths]
@@ -214,13 +227,31 @@ Explosions: [tension_master.explosions]
Air alarms: [tension_master.air_alarms]
Adminhelps: [tension_master.adminhelps]
+Ghosts: [numghosts]

Current Status
Tension: [tension_master.score]
+Increase Tension by 50000
Tension per player: [tension_master.score/tension_master.get_num_players()]
-Recommendations: not yet implemented
+Tensioner Debug Data: R1:[tension_master.round1] R2:[tension_master.round2] R3:[tension_master.round3] R4:[tension_master.round4] ES: [tension_master.eversupressed] CD: [tension_master.cooldown]
+Current Tensioner Status: [config.Tensioner_Active]. Toggle?
+Recommendations: All the modes. All of them. Press all of them.

+ Make Tratiors
+ Make Changlings
+ Make Revs
+ Make Wizard (Requires Ghosts)
+ Make Cult
+ Make Nuke Team (Requires Ghosts)
+ Make Malf AI
+ Make Space Ninja (Requires Ghosts)
+ Make Aliens (Requires Ghosts)
+ Make Deathsquad (Syndicate) (Requires Ghosts)
+ Make Deathsquad (Borg) (Requires Ghosts)
+ +
+ "} usr << browse(output,"window=tensionreport") \ No newline at end of file diff --git a/code/modules/admin/verbs/striketeam_syndicate.dm b/code/modules/admin/verbs/striketeam_syndicate.dm index eccd7ea42a..a07c386093 100644 --- a/code/modules/admin/verbs/striketeam_syndicate.dm +++ b/code/modules/admin/verbs/striketeam_syndicate.dm @@ -107,6 +107,7 @@ var/global/sent_syndicate_strike_team = 0 message_admins("\blue [key_name_admin(usr)] has spawned a Syndicate strike squad.", 1) log_admin("[key_name(usr)] used Spawn Syndicate Squad.") + //feedback_add_details("admin_verb","SDTHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/proc/create_syndicate_death_commando(obj/spawn_location, syndicate_leader_selected = 0) var/mob/living/carbon/human/new_syndicate_commando = new(spawn_location.loc) @@ -144,7 +145,7 @@ var/global/sent_syndicate_strike_team = 0 camera.c_tag = real_name var/obj/item/device/radio/R = new /obj/item/device/radio/headset(src) - R.set_frequency(1337) //Same frequency as the syndicate team in Nuke mode. + R.set_frequency(NUKE_FREQ) //Same frequency as the syndicate team in Nuke mode. equip_if_possible(R, slot_ears) equip_if_possible(new /obj/item/clothing/under/syndicate(src), slot_w_uniform) equip_if_possible(new /obj/item/clothing/shoes/swat(src), slot_shoes) diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm index a812626b65..446f068632 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/drone.dm @@ -10,6 +10,7 @@ src.verbs -= /mob/living/carbon/alien/humanoid/verb/ActivateHuggers src.stand_icon = new /icon('alien.dmi', "aliend_s") src.lying_icon = new /icon('alien.dmi', "aliend_l") + src.resting_icon = new /icon('alien.dmi', "aliend_sleep") src.icon = src.stand_icon update_clothing() src << "\blue Your icons have been generated!" diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index 1f6ae9bead..7c7e5eaedf 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -9,6 +9,7 @@ src.verbs -= /mob/living/carbon/alien/humanoid/verb/corrode src.stand_icon = new /icon('alien.dmi', "alienh_s") src.lying_icon = new /icon('alien.dmi', "alienh_l") + src.resting_icon = new /icon('alien.dmi', "alienh_sleep") src.icon = src.stand_icon update_clothing() src << "\blue Your icons have been generated!" diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm index 7bd9b41b9b..ecc3b459e6 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm @@ -9,6 +9,7 @@ src.verbs += /mob/living/carbon/alien/humanoid/proc/corrode_target src.stand_icon = new /icon('alien.dmi', "aliens_s") src.lying_icon = new /icon('alien.dmi', "aliens_l") + src.resting_icon = new /icon('alien.dmi', "aliens_sleep") src.icon = src.stand_icon update_clothing() src << "\blue Your icons have been generated!" diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index 8b261940ce..52e422c628 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -10,6 +10,7 @@ if(!istype(src, /mob/living/carbon/alien/humanoid/queen)) stand_icon = new /icon('alien.dmi', "alien_s") lying_icon = new /icon('alien.dmi', "alien_l") + resting_icon = new /icon('alien.dmi', "alienh_sleep") icon = stand_icon update_clothing() src << "\blue Your icons have been generated!" @@ -330,7 +331,10 @@ if (lying) if(update_icon) - icon = lying_icon + if(!resting) + icon = lying_icon + else + icon = resting_icon overlays += body_lying diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 26b1d58601..f88b78787d 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -9,6 +9,31 @@ emp_act */ /mob/living/carbon/human/bullet_act(var/obj/item/projectile/P, var/def_zone) + + if(wear_suit && istype(wear_suit, /obj/item/clothing/suit/armor/laserproof)) + if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) + var/reflectchance = 40 - round(P.damage/3) + if(!(def_zone in list("chest", "groin"))) + reflectchance /= 2 + if(prob(reflectchance)) + visible_message("\red The [P.name] gets reflected by [src]'s [wear_suit.name]!") + + // Find a turf near or on the original location to bounce to + if(P.starting) + var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) + var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2) + var/turf/curloc = get_turf(src) + + // redirect the projectile + P.original = locate(new_x, new_y, P.z) + P.starting = curloc + P.current = curloc + P.firer = src + P.yo = new_y - curloc.y + P.xo = new_x - curloc.x + + return -1 // complete projectile permutation + if(check_shields(P.damage, "the [P.name]")) P.on_hit(src, 2) return 2 @@ -96,14 +121,17 @@ emp_act var/datum/organ/external/affecting = get_organ(ran_zone(user.zone_sel.selecting)) var/hit_area = affecting.display_name + + + if((user != src) && check_shields(I.force, "the [I.name]")) + return 0 + if(!affecting.destroyed) visible_message("\red [src] has been attacked in the [hit_area] with [I.name] by [user]!") else user << "What [affecting]?" return - if((user != src) && check_shields(I.force, "the [I.name]")) - return 0 var/armor = run_armor_check(affecting, "melee", "Your armor has protected you from a hit to the [hit_area].", "Your armor has softened hit to your [hit_area].") if(armor >= 2) return 0 if(!I.force) return 0 @@ -116,7 +144,7 @@ emp_act var/bloody = 0 if((I.damtype == BRUTE) && prob(25 + is_sharp(I) * 50 + (I.force * 2))) - I.add_blood(src) + I.add_blood(src) //Make the weapon bloody, not the person. bloody = 1 var/turf/location = loc if(istype(location, /turf/simulated)) diff --git a/code/modules/mob/living/carbon/monkey/powers.dm b/code/modules/mob/living/carbon/monkey/powers.dm index e05cb05de2..9a8f95283e 100644 --- a/code/modules/mob/living/carbon/monkey/powers.dm +++ b/code/modules/mob/living/carbon/monkey/powers.dm @@ -3,48 +3,50 @@ set desc = "Enter an air vent and crawl through the pipe system." set category = "Monkey" - if(contents.len) - for(var/obj/item/carried_item in contents)//If the monkey got on objects. - if(!istype(carried_item, /obj/item/weapon/implant))//If it's not an implant. - src << "\red You can't be carrying items or have items equipped when vent crawling!" - return - - if(!stat) - var/obj/machinery/atmospherics/unary/vent_pump/vent_found - for(var/obj/machinery/atmospherics/unary/vent_pump/v in range(1,src)) - if(!v.welded) - vent_found = v - else - src << "\red That vent is welded." - if(vent_found) - if(vent_found.network&&vent_found.network.normal_members.len) - var/list/vents = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in vent_found.network.normal_members) - if(temp_vent.loc == loc) - continue - vents.Add(temp_vent) - var/list/choices = list() - for(var/obj/machinery/atmospherics/unary/vent_pump/vent in vents) - if(vent.loc.z != loc.z) - continue - var/atom/a = get_turf_loc(vent) - choices.Add(a.loc) - var/turf/startloc = loc - var/obj/selection = input("Select a destination.", "Duct System") in choices - var/selection_position = choices.Find(selection) - if(loc==startloc) - var/obj/target_vent = vents[selection_position] - if(target_vent) - for(var/mob/O in oviewers(src, null)) - if ((O.client && !( O.blinded ))) - O.show_message(text("[src] scrambles into the ventillation ducts!"), 1) - loc = target_vent.loc + if(stat == CONSCIOUS) + if(!lying) + var/obj/machinery/atmospherics/unary/vent_pump/vent_found + for(var/obj/machinery/atmospherics/unary/vent_pump/v in range(1,src)) + if(!v.welded) + vent_found = v else - src << "You need to remain still while entering a vent." + src << "\red That vent is welded." + if(vent_found) + if(vent_found.network&&vent_found.network.normal_members.len) + var/list/vents = list() + for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in vent_found.network.normal_members) + if(temp_vent.loc == loc) + continue + vents.Add(temp_vent) + var/list/choices = list() + for(var/obj/machinery/atmospherics/unary/vent_pump/vent in vents) + if(vent.loc.z != loc.z) + continue + var/atom/a = get_turf_loc(vent) + choices.Add(a.loc) + var/turf/startloc = loc + var/obj/selection = input("Select a destination.", "Duct System") in choices + var/selection_position = choices.Find(selection) + if(loc==startloc) + if(contents.len) + for(var/obj/item/carried_item in contents)//If the monkey got on objects. + if(!istype(carried_item, /obj/item/weapon/implant))//If it's not an implant. + src << "\red You can't be carrying items or have items equipped when vent crawling!" + return + var/obj/target_vent = vents[selection_position] + if(target_vent) + for(var/mob/O in oviewers(src, null)) + if ((O.client && !( O.blinded ))) + O.show_message(text("[src] scrambles into the ventillation ducts!"), 1) + loc = target_vent.loc + else + src << "You need to remain still while entering a vent." + else + src << "This vent is not connected to anything." else - src << "This vent is not connected to anything." + src << "You must be standing on or beside an air vent to enter it." else - src << "You must be standing on or beside an air vent to enter it." + src << "You can't vent crawl while you're stunned!" else src << "You must be conscious to do this!" return \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index f693944133..3ab582828e 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -301,6 +301,14 @@ if (href_list["showalerts"]) ai_alerts() + //Carn: holopad requests + if (href_list["jumptoholopad"]) + var/obj/machinery/hologram/holopad/H = locate(href_list["jumptoholopad"]) + if(stat == CONSCIOUS) + if(H) + H.attack_ai(src) //may as well recycle + else + src << "Unable to locate the holopad." if (href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite var/L = text2num(href_list["lawc"]) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 6e0908137b..78883f7ebd 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -2,9 +2,10 @@ canmove = 0 src.loc = paicard card = paicard - if(!card.radio) - card.radio = new /obj/item/device/radio(src.card) - radio = card.radio + if(card) + if(!card.radio) + card.radio = new /obj/item/device/radio(src.card) + radio = card.radio ..() diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index f5d9676013..30338c21fc 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -170,8 +170,14 @@ if(isnull(P)||P.toff) return + var/AnsweringMS = 0 for (var/obj/machinery/message_server/MS in world) MS.send_pda_message("[P.owner]","[src]","[t]") + if(MS.active) + AnsweringMS++ + + if(!AnsweringMS) + return tnote += "→ To [P.owner]:
[t]
" P.tnote += "← From [src]:
[t]
" @@ -195,12 +201,18 @@ else var/mob/living/silicon/pai/P = target - tnote += "→ To [P]:
[t]
" - P.tnote += "← From [src]:
[t]
" - - + var/AnsweringMS = 0 for (var/obj/machinery/message_server/MS in world) MS.send_pda_message("[P]","[src]","[t]") + if(MS.active) + AnsweringMS++ + + if(!AnsweringMS) + return + + + tnote += "→ To [P]:
[t]
" + P.tnote += "← From [src]:
[t]
" if (prob(15)) //Give the AI a chance of intercepting the message var/who = src diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 4009499c82..4a1104141b 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -46,6 +46,12 @@ /mob/living/silicon/robot/Del() if(mmi)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside. mmi.loc = get_turf(loc)//To hopefully prevent run time errors. + + if(!key) + for(var/mob/dead/observer/ghost in world) + if(ghost.corpse == src && ghost.client) + ghost.client.mob = ghost.corpse + if(key)//If there is a client attached to host. if(client) client.screen.len = null @@ -130,6 +136,7 @@ if (sprite == "Non-Humanoid") src.icon_state = "bloodhound" modtype = "Sec" + //speed = -1 Secborgs have nerfed tasers now, so the speed boost is not necessary channels = list("Security" = 1) //feedback_inc("cyborg_security",1) @@ -1111,3 +1118,32 @@ Frequency: gib() return +/mob/living/silicon/robot/proc/UnlinkSelf() + if (src.connected_ai) + src.connected_ai = null + lawupdate = 0 + lockcharge = 0 + canmove = 1 + scrambledcodes = 1 + + + +/mob/living/silicon/robot/proc/ResetSecurityCodes() + set category = "Robot Commands" + set name = "Reset Identity Codes" + set desc = "Scrambles your security and identification codes and resets your current buffers. Unlocks you and but permenantly severs you from your AI and the robotics console." + + var/mob/living/silicon/robot/R = usr + + if(R) + R.UnlinkSelf() + R << "Buffers flushed and reset. All systems operational." + src.verbs -= /mob/living/silicon/robot/proc/ResetSecurityCodes + + +/*/mob/living/silicon/robot/proc/flashproof() + if(module) + for(var/obj/item/borg/upgrade/flashproof/F in module.modules) + return 1 + + return 0*/ \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm index f0a907d05d..74522c2b0d 100644 --- a/code/modules/mob/living/silicon/robot/robot_movement.dm +++ b/code/modules/mob/living/silicon/robot/robot_movement.dm @@ -5,3 +5,11 @@ if(J.allow_thrust(0.01)) return 1 if(..()) return 1 return 0 + + //No longer needed, but I'll leave it here incase we plan to re-use it. +/mob/living/silicon/robot/movement_delay() + var/tally = 0 //Incase I need to add stuff other than "speed" later + + tally = speed + + return tally diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index a0c5ec9815..b22fcc461e 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -58,6 +58,14 @@ name = "Longest Hair" icon_state = "hair_vlong" + longalt + name = "Long Hair Alt" + icon_state = "hair_longfringe" + + longestalt + name = "Longest Hair Alt" + icon_state = "hair_vlongfringe" + halfbang name = "Half-banged Hair" icon_state = "hair_halfbang" @@ -89,6 +97,7 @@ mohawk name = "Mohawk" icon_state = "hair_d" + choose_female = 0 // gross balding name = "Balding Hair" @@ -118,6 +127,7 @@ dreadlocks name = "Dreadlocks" icon_state = "hair_dreads" + choose_female = 0 // okay.jpg jensen name = "Adam Jensen Hair" @@ -132,14 +142,6 @@ icon_state = "bald" choose_female = 0 - longalt - name = "Long Hair Alt" - icon_state = "hair_longfringe" - - longestalt - name = "Longest Hair Alt" - icon_state = "hair_vlongfringe" - himecut name = "Hime Cut" icon_state = "hair_himecut" @@ -148,6 +150,9 @@ name = "Curls" icon_state = "hair_curls" + spikey + name = "Spikey" + icon_state = "hair_spikey" /* /////////////////////////////////// diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 8b20858d69..ebbaebdbd7 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -101,13 +101,13 @@ for(var/obj/effect/landmark/start/sloc in world) if (sloc.name != "AI") continue - if (locate(/mob) in sloc.loc) + if (locate(/mob/living) in sloc.loc) continue loc_landmark = sloc if (!loc_landmark) for(var/obj/effect/landmark/tripai in world) if (tripai.name == "tripai") - if(locate(/mob) in tripai.loc) + if(locate(/mob/living) in tripai.loc) continue loc_landmark = tripai if (!loc_landmark) diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 22d810a801..c78517f387 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -437,6 +437,8 @@ //source is an object caused electrocuting (airlock, grille, etc) //No animations will be performed by this proc. /proc/electrocute_mob(mob/living/carbon/M as mob, var/power_source, var/obj/source, var/siemens_coeff = 1.0) + if(istype(M.loc,/obj/mecha)) + return 0 if(istype(M,/mob/living/carbon/human)) var/mob/living/carbon/human/H = M if(H.gloves) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 665012518a..42fa63090f 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -189,6 +189,7 @@ in_chamber.original = targloc in_chamber.loc = get_turf(user) + in_chamber.starting = get_turf(user) user.next_move = world.time + 4 in_chamber.silenced = silenced in_chamber.current = curloc diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 46f415ac51..ebfd27c485 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -27,7 +27,8 @@ yo = null xo = null current = null - turf/original = null + turf/original = null // the original turf clicked + turf/starting = null // the projectile's starting turf p_x = 16 p_y = 16 // the pixel location of the tile that the player clicked. Default is the center diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index c8ead597ef..7821b66cd7 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -1,5 +1,5 @@ /obj/item/projectile/ion - name = "\improper Ion Bolt" + name = "ion bolt" icon_state = "ion" damage = 0 damage_type = BURN @@ -13,7 +13,7 @@ /obj/item/projectile/bullet/gyro - name ="\improper Rocket" + name ="explosive bolt" icon_state= "bolter" damage = 50 flag = "bullet" @@ -24,7 +24,7 @@ return 1 /obj/item/projectile/temp - name = "\improper Freeze Beam" + name = "freeze beam" icon_state = "ice_2" damage = 0 damage_type = BURN diff --git a/code/modules/research/message_server.dm b/code/modules/research/message_server.dm index 721c5f00f7..d4c5de435f 100644 --- a/code/modules/research/message_server.dm +++ b/code/modules/research/message_server.dm @@ -54,6 +54,16 @@ var/list/datum/data_pda_msg/pda_msgs = list() var/list/datum/data_rc_msg/rc_msgs = list() + var/active = 1 + +/obj/machinery/message_server/process() + if((stat & (BROKEN|NOPOWER)) && active) + active = 0 + return + + update_icon() + return + /obj/machinery/message_server/proc/send_pda_message(var/recipient = "",var/sender = "",var/message = "") pda_msgs += new/datum/data_pda_msg(recipient,sender,message) @@ -61,8 +71,22 @@ rc_msgs += new/datum/data_rc_msg(recipient,sender,message,stamp,id_auth) /obj/machinery/message_server/attack_hand(user as mob) - user << "\blue There seem to be some parts missing from this server. They should arrive on the station in a few days, give or take a few CentCom delays." +// user << "\blue There seem to be some parts missing from this server. They should arrive on the station in a few days, give or take a few CentCom delays." + user << "You toggle PDA message passing from [active ? "On" : "Off"] to [active ? "Off" : "On"]" + active = !active + update_icon() + return + +/obj/machinery/message_server/update_icon() + if((stat & (BROKEN|NOPOWER))) + icon_state = "server-nopower" + else if (!active) + icon_state = "server-off" + else + icon_state = "server-on" + + return /datum/feedback_variable diff --git a/config/config.txt b/config/config.txt index 94468b193e..248ec7983d 100644 --- a/config/config.txt +++ b/config/config.txt @@ -78,6 +78,8 @@ TRAITOR_SCALING ## If security is prohibited from being most antagonists #PROTECT_ROLES_FROM_ANTAGONIST +## If the auto-tensioner is active by default. It creates more tratiors/other antagonists if it consideers the round slowing down. +#TENSIONER_ACTIVE ## allow players to initiate a restart vote ALLOW_VOTE_RESTART diff --git a/icons/mob/alien.dmi b/icons/mob/alien.dmi index d3de781e6c..1efa862fdc 100644 Binary files a/icons/mob/alien.dmi and b/icons/mob/alien.dmi differ diff --git a/icons/mob/human.dmi b/icons/mob/human.dmi index 5664fa370e..492f253711 100644 Binary files a/icons/mob/human.dmi and b/icons/mob/human.dmi differ diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index 10ab3bea56..77f41fd2bf 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 6d846b839c..1703f6ceb3 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ