diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index c250dc1d2d9..e442f74d14f 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -160,6 +160,8 @@ var/aggressive_changelog = 0 + var/reactionary_explosions = 0 //If we use reactionary explosions, explosions that react to walls and doors + /datum/configuration/New() var/list/L = typesof(/datum/game_mode) - /datum/game_mode for(var/T in L) @@ -485,6 +487,8 @@ config.no_summon_magic = 1 if("no_summon_events") config.no_summon_events = 1 + if("reactionary_explosions") + config.reactionary_explosions = 1 else diary << "Unknown setting in configuration: '[name]'" diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 5cff548b620..838bcde4e26 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -9,6 +9,7 @@ var/global/datum/controller/game_controller/master_controller = new() var/processing_interval = 1 //The minimum length of time between MC ticks (in deciseconds). The highest this can be without affecting schedules, is the GCD of all subsystem var/wait. Set to 0 to disable all processing. var/iteration = 0 var/cost = 0 + var/SSCostPerSecond = 0 var/last_thing_processed var/list/subsystems = list() @@ -60,7 +61,8 @@ calculate the longest number of ticks the MC can wait between each cycle without for(var/datum/subsystem/S in subsystems) S.Initialize(world.timeofday, zlevel) sleep(-1) - + for(var/datum/subsystem/S in subsystems) + S.AfterInitialize(zlevel) world << "Initializations complete" world.log << "Initializations complete" @@ -89,10 +91,11 @@ calculate the longest number of ticks the MC can wait between each cycle without ++iteration start_time = world.timeofday - + var/SubSystemRan = 0 for(var/datum/subsystem/SS in subsystems) if(SS.can_fire > 0) if(SS.next_fire <= world.time) + SubSystemRan = 1 timer = world.timeofday last_thing_processed = SS.type SS.last_fire = world.time @@ -100,7 +103,9 @@ calculate the longest number of ticks the MC can wait between each cycle without SS.cost = MC_AVERAGE(SS.cost, world.timeofday - timer) if (SS.dynamic_wait) var/oldwait = SS.wait - SS.wait = min(max(round(SS.cost*SS.dwait_delta, 0.1),SS.dwait_lower),SS.dwait_upper) + var/GlobalCostDelta = (SSCostPerSecond-(SS.cost/SS.wait))/(SS.wait/10)-1 + var/NewWait = MC_AVERAGE(oldwait,(SS.cost-1.5+GlobalCostDelta)*SS.dwait_delta) + SS.wait = Clamp(round(NewWait,0.1),SS.dwait_lower,SS.dwait_upper) if (oldwait != SS.wait) calculateGCD() SS.next_fire += SS.wait @@ -109,11 +114,20 @@ calculate the longest number of ticks the MC can wait between each cycle without sleep(-1) cost = MC_AVERAGE(cost, world.timeofday - start_time) - + if (SubSystemRan) + calculateSScost() sleep(processing_interval) else sleep(50) +/datum/controller/game_controller/proc/calculateSScost() + var/newcost = 0 + for(var/datum/subsystem/SS in subsystems) + if (!SS.can_fire) + continue + newcost += SS.cost/(SS.wait/10) + SSCostPerSecond = MC_AVERAGE(SSCostPerSecond,newcost) + #undef MC_AVERAGE /datum/controller/game_controller/proc/roundHasStarted() diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 5c74da6d84d..969e2fa6d97 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -3,7 +3,6 @@ var/datum/subsystem/air/SSair /datum/subsystem/air name = "Air" priority = 20 - cost = 5 wait = 5 dynamic_wait = 1 dwait_lower = 5 @@ -56,10 +55,12 @@ var/datum/subsystem/air/SSair /datum/subsystem/air/Initialize(timeofday, zlevel) - setup_allturfs(zlevel) setup_atmos_machinery(zlevel) ..() +/datum/subsystem/air/AfterInitialize(zlevel) + setup_allturfs(zlevel) + #define MC_AVERAGE(average, current) (0.8*(average) + 0.2*(current)) /datum/subsystem/air/fire() var/timer = world.timeofday @@ -167,15 +168,14 @@ var/datum/subsystem/air/SSair EG.dismantle() /datum/subsystem/air/proc/setup_allturfs(z_level) + active_turfs.Cut() var/z_start = 1 var/z_finish = world.maxz if(1 <= z_level && z_level <= world.maxz) z_level = round(z_level) z_start = z_level z_finish = z_level - var/list/turfs_to_init = block(locate(1, 1, z_start), locate(world.maxx, world.maxy, z_finish)) - for(var/turf/simulated/T in turfs_to_init) T.CalculateAdjacentTurfs() if(!T.blocks_air) @@ -195,6 +195,8 @@ var/datum/subsystem/air/SSair if(!T.air.check_turf_total(enemy_tile)) T.excited = 1 active_turfs |= T + if(active_turfs.len) + warning("There are [active_turfs.len] active turfs at roundstart, this is a mapping error caused by a difference of the air between the adjacent turfs.") /datum/subsystem/air/proc/setup_atmos_machinery(z_level) for (var/obj/machinery/atmospherics/AM in atmos_machinery) diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index a99ac70899f..352caeb6195 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -5,9 +5,11 @@ var/datum/subsystem/garbage_collector/SSgarbage can_fire = 1 wait = 5 priority = -1 + dynamic_wait = 1 + dwait_delta = 5 var/collection_timeout = 300// deciseconds to wait to let running procs finish before we just say fuck it and force del() the object - var/max_run_time = 2 // how long, in deciseconds, can we run before waiting for the next tick + var/max_run_time = 1 // how long, in deciseconds, can we run before waiting for the next tick var/delslasttick = 0 // number of del()'s we've done this tick var/gcedlasttick = 0 // number of things that gc'ed last tick var/totaldels = 0 diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index c2a0c3df334..cd74bb16b84 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -7,6 +7,7 @@ var/datum/subsystem/lighting/SSlighting wait = 5 priority = 1 dynamic_wait = 1 + dwait_delta = 1 var/list/changed_lights = list() //list of all datum/light_source that need updating var/changed_lights_workload = 0 //stats on the largest number of lights (max changed_lights.len) diff --git a/code/controllers/subsystems.dm b/code/controllers/subsystems.dm index 5e10dcbcfd6..777bc2e5a1e 100644 --- a/code/controllers/subsystems.dm +++ b/code/controllers/subsystems.dm @@ -37,6 +37,9 @@ world << "[msg]" world.log << msg +/datum/subsystem/proc/AfterInitialize() + return + //hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc. /datum/subsystem/proc/stat_entry(msg) var/dwait = "" diff --git a/code/datums/spells/lichdom.dm b/code/datums/spells/lichdom.dm new file mode 100644 index 00000000000..a6ace565803 --- /dev/null +++ b/code/datums/spells/lichdom.dm @@ -0,0 +1,108 @@ +/obj/effect/proc_holder/spell/targeted/lichdom + name = "Bind Soul" + desc = "A dark necromantic pact that can forever bind your soul to an item of your choosing. So long as both your body and the item remain intact you can revive from death, though the time between reincarnations grows steadily with use." + school = "necromancy" + charge_max = 10 + clothes_req = 0 + centcom_cancast = 0 + invocation = "NECREM IMORTIUM!" + invocation_type = "shout" + range = -1 + level_max = 0 //cannot be improved + cooldown_min = 10 + include_user = 1 + + var/obj/marked_item + var/mob/living/current_body + + action_icon_state = "skeleton" + +/obj/effect/proc_holder/spell/targeted/lichdom/New() + if(ticker.mode.round_ends_with_antag_death) + ticker.mode.round_ends_with_antag_death = 0 + + ..() +/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets) + for(var/mob/user in targets) + var/list/hand_items = list() + if(iscarbon(user)) + hand_items = list(user.get_active_hand(),user.get_inactive_hand()) + + if(marked_item && !stat_allowed) //sanity, shouldn't happen without badminry + marked_item = null + return + + if(stat_allowed) //Death is not my end! + if(user.stat == CONSCIOUS && iscarbon(user)) + user << "You aren't dead enough to revive!" //Usually a good problem to have + charge_counter = charge_max + return + + if(!marked_item.loc) //Wait nevermind + user << "Your phylactery is gone!" + return + + if(isobserver(user)) + var/mob/dead/observer/O = user + O.reenter_corpse() + + var/mob/living/carbon/human/lich = new /mob/living/carbon/human(get_turf(marked_item)) + + lich.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(lich), slot_shoes) + lich.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(lich), slot_w_uniform) + lich.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(lich), slot_wear_suit) + lich.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(lich), slot_head) + + lich.real_name = user.mind.name + user.mind.transfer_to(lich) + hardset_dna(lich,null,null,lich.real_name,null,/datum/species/skeleton) + lich << "Your bones clatter and shutter as they're pulled back into this world!" + charge_max += 600 + var/mob/old_body = current_body + current_body = lich + lich.Weaken(10) + + if(old_body && old_body.loc) + if(iscarbon(old_body)) + var/mob/living/carbon/C = old_body + for(var/obj/item/W in C) + C.unEquip(W) + var/wheres_wizdo = dir2text(get_dir(get_turf(old_body), get_turf(marked_item))) + if(wheres_wizdo) + old_body.visible_message("Suddenly [old_body.name]'s corpse falls to pieces! You see a strange energy rise from the remains, and speed off towards the [wheres_wizdo]!") + old_body.dust() + + if(!marked_item) //linking item to the spell + message = "" + for(var/obj/item in hand_items) + if(ABSTRACT in item.flags || NODROP in item.flags) + continue + marked_item = item + user << "You begin to focus your very being into the [item.name]..." + break + + if(!marked_item) + user << "You must hold an item you wish to make your phylactery..." + + spawn(50) + if(marked_item.loc != user) //I changed my mind I don't want to put my soul in a cheeseburger! + user << "Your soul snaps back to your body as you drop the [marked_item.name]!" + marked_item = null + return + name = "RISE!" + desc = "Rise from the dead! You will reform at the location of your phylactery and your old body will crumble away." + charge_max = 1800 //3 minute cooldown, if you rise in sight of someone and killed again, you're probably screwed. + charge_counter = 1800 + stat_allowed = 1 + marked_item.name = "Ensouled [marked_item.name]" + marked_item.desc = "A terrible aura surrounds this item, its very existence is offensive to life itself..." + marked_item.color = "#003300" + user << "With a hideous feeling of emptiness you watch in horrified fascination as skin sloughs off bone! Blood boils, nerves disintegrate, eyes boil in their sockets! As your organs crumble to dust in your fleshless chest you come to terms with your choice. You're a lich!" + hardset_dna(user, null, null, null, null, /datum/species/skeleton) + current_body = user.mind.current + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.unEquip(H.wear_suit) + H.unEquip(H.head) + H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), slot_wear_suit) + H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), slot_head) \ No newline at end of file diff --git a/code/datums/spells/summonitem.dm b/code/datums/spells/summonitem.dm index e74ce4a92c6..7b29e448844 100644 --- a/code/datums/spells/summonitem.dm +++ b/code/datums/spells/summonitem.dm @@ -7,7 +7,7 @@ invocation = "GAR YOK" invocation_type = "whisper" range = -1 - level_max = 1 //cannot be improved + level_max = 0 //cannot be improved cooldown_min = 100 include_user = 1 diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 8afadbc4ce8..cb638aa6f31 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -21,6 +21,10 @@ // replaced by OPENCONTAINER flags and atom/proc/is_open_container() ///Chemistry. var/allow_spin = 1 + + //Value used to increment ex_act() if reactionary_explosions is on + var/explosion_block = 0 + /atom/proc/onCentcom() var/turf/T = get_turf(src) if(!T) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 4bfeecb2247..eddb0216d76 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -188,7 +188,7 @@ return 0 - if(living_antag_player && living_antag_player.mind && living_antag_player.stat != DEAD && !isnewplayer(living_antag_player) &&!isbrain(living_antag_player)) + if(living_antag_player && living_antag_player.mind && isliving(living_antag_player) && living_antag_player.stat != DEAD && !isnewplayer(living_antag_player) &&!isbrain(living_antag_player)) return 0 //A resource saver: once we find someone who has to die for all antags to be dead, we can just keep checking them, cycling over everyone only when we lose our mark. for(var/mob/Player in living_mob_list) diff --git a/code/game/gamemodes/gang/dominator.dm b/code/game/gamemodes/gang/dominator.dm new file mode 100644 index 00000000000..4fbae44af79 --- /dev/null +++ b/code/game/gamemodes/gang/dominator.dm @@ -0,0 +1,209 @@ +/obj/machinery/dominator + name = "dominator" + desc = "A visibly sinister device. Looks like you can break it if you hit it enough." + icon = 'icons/obj/machines/dominator.dmi' + icon_state = "dominator" + density = 1 + anchored = 1.0 + layer = 3.6 + var/health = 200 + var/gang + var/operating = 0 + var/broken = 0 + +/obj/machinery/dominator/New() + if(!istype(ticker.mode, /datum/game_mode/gang)) + qdel(src) + return + SetLuminosity(2) + +/obj/machinery/dominator/examine(mob/user) + ..() + if(broken) + user << "It looks completely busted." + return + + var/datum/game_mode/gang/mode = ticker.mode + var/time = null + if(isnum(mode.A_timer)) + time = max(mode.A_timer, 0) + if(isnum(mode.B_timer)) + time = max(mode.B_timer, 0) + if(isnum(time)) + if(time > 0) + user << "Hostile Takeover in progress. Estimated [time] seconds remain." + else + user << "Hostile Takeover of [station_name()] successful. Have a great day." + else + user << "System on standby." + user << "System Integrity: [health/2]%" + + +/obj/machinery/dominator/proc/healthcheck(var/damage) + var/iconname = "dominator" + if(gang) + iconname += "-[gang]" + SetLuminosity(3) + + var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread + + health -= damage + + switch(health) + if(101 to INFINITY) + if(prob(damage*2)) + sparks.set_up(5, 1, src) + sparks.start() + if(1 to 100) + sparks.set_up(5, 1, src) + sparks.start() + iconname += "-damaged" + + if(!broken) + if(health <= 0) + set_broken() + else + icon_state = iconname + + if(health <= -50) + new /obj/item/stack/sheet/plasteel(src.loc) + qdel(src) + +/obj/machinery/dominator/proc/set_broken() + if(!gang) + return + var/datum/game_mode/gang/mode = ticker.mode + if(gang == "A") + mode.A_timer = "OFFLINE" + if(gang == "B") + mode.B_timer = "OFFLINE" + if(!isnum(mode.A_timer) && !isnum(mode.B_timer)) + SSshuttle.emergencyNoEscape = 0 + if(SSshuttle.emergency.mode == SHUTTLE_STRANDED) + SSshuttle.emergency.mode = SHUTTLE_DOCKED + SSshuttle.emergency.timer = world.time + priority_announce("Hostile enviroment resolved. You have 3 minutes to board the Emergency Shuttle.", null, 'sound/AI/shuttledock.ogg', "Priority") + else + priority_announce("All hostile activity within station systems have ceased.","Network Alert") + SetLuminosity(0) + icon_state = "dominator-broken" + broken = 1 + +/obj/machinery/dominator/Destroy() + if(!broken) + set_broken() + ..() + +/obj/machinery/dominator/emp_act(severity) + healthcheck(100) + ..() + +/obj/machinery/dominator/ex_act(severity, target) + if(target == src) + qdel(src) + return + switch(severity) + if(1.0) + qdel(src) + if(2.0) + healthcheck(120) + if(3.0) + healthcheck(30) + return + +/obj/machinery/dominator/bullet_act(var/obj/item/projectile/Proj) + if(Proj.damage) + if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) + playsound(src, 'sound/effects/bang.ogg', 50, 1) + visible_message("[src] was hit by [Proj].") + healthcheck(Proj.damage) + ..() + +/obj/machinery/dominator/blob_act() + healthcheck(110) + +/obj/machinery/dominator/attackby(I as obj, user as mob, params) + + return + +/obj/machinery/dominator/attack_hand(mob/user) + if(operating||broken) + examine(user) + return + + var/datum/game_mode/gang/mode = ticker.mode + var/gang_territory + var/timer + + var/tempgang + if(user.mind in (ticker.mode.A_gang|ticker.mode.A_bosses)) + tempgang = "A" + gang_territory = ticker.mode.A_territory.len + timer = mode.A_timer + else if(user.mind in (ticker.mode.B_gang|ticker.mode.B_bosses)) + tempgang = "B" + gang_territory = ticker.mode.B_territory.len + timer = mode.B_timer + + if(!tempgang) + examine(user) + return + + if(isnum(timer)) //In theory, this shouldn't happen. But if it does, they get this meme + user << "Error: Hostile Takeover is already in progress." + return + + var/time = max(180,900 - ((round((gang_territory/start_state.num_territories)*200, 1) - 60) * 15)) + if(alert(user,"With [round((gang_territory/start_state.num_territories)*100, 1)]% station control, a takeover will require [time] seconds.\nThe entire station will likely be alerted once it starts.\nYour gang must be prepared to defend this device throughout the duration.\nAre you ready?","Confirmation","Yes","No") == "Yes") + if ((!in_range(src, user) || !istype(src.loc, /turf))) + return 0 + var/area/srcloc = get_area(src.loc) + gang = tempgang + mode.domination(gang,1,srcloc.name) + src.name = "[gang_name(gang)] Gang [src.name]" + healthcheck(0) + operating = 1 + +/obj/machinery/dominator/attack_alien(mob/living/user) + user.do_attack_animation(src) + playsound(src, 'sound/effects/bang.ogg', 50, 1) + user.visible_message("[user] smashes against [src] with its claws.",\ + "You smash against [src] with your claws.",\ + "You hear metal scraping.") + healthcheck(15) + +/obj/machinery/dominator/attack_animal(mob/living/user as mob) + if(!isanimal(user)) + return + var/mob/living/simple_animal/M = user + M.do_attack_animation(src) + if(M.melee_damage_upper <= 0) + return + healthcheck(M.melee_damage_upper) + +/obj/machinery/dominator/mech_melee_attack(obj/mecha/M) + if(M.damtype == "brute") + playsound(src, 'sound/effects/bang.ogg', 50, 1) + visible_message("[M.name] has hit [src].") + healthcheck(M.force) + return + +/obj/machinery/dominator/attack_hulk(mob/user) + playsound(src, 'sound/effects/bang.ogg', 50, 1) + user.visible_message("[user] smashes [src].",\ + "You punch [src].",\ + "You hear metal being slammed.") + healthcheck(5) + +/obj/machinery/dominator/attackby(obj/item/weapon/I as obj, mob/living/user as mob, params) + if(istype(I, /obj/item/weapon)) + add_fingerprint(user) + user.changeNext_move(CLICK_CD_MELEE) + user.do_attack_animation(src) + if( (I.flags&NOBLUDGEON) || !I.force ) + return + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + visible_message("[user] has hit \the [src] with [I].") + if(I.damtype == BURN || I.damtype == BRUTE) + healthcheck(I.force) + return diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm index 6967dc894c7..97ed4eecbcd 100644 --- a/code/game/gamemodes/gang/gang.dm +++ b/code/game/gamemodes/gang/gang.dm @@ -15,6 +15,10 @@ var/list/A_territory_lost = list() var/list/B_territory_new = list() var/list/B_territory_lost = list() + var/gang_A_style + var/gang_A_headgear + var/gang_B_style + var/gang_B_headgear /datum/game_mode/gang name = "gang war" @@ -26,14 +30,15 @@ recommended_enemies = 2 enemy_minimum_age = 14 var/finished = 0 - var/goal_scalar = 0.5 //Goal = Total territories x goal_scalar - + // Victory timers + var/A_timer = "OFFLINE" + var/B_timer = "OFFLINE" /////////////////////////// //Announces the game type// /////////////////////////// /datum/game_mode/gang/announce() world << "The current game mode is - Gang War!" - world << "A violent turf war has erupted on the station!
Gangsters - Take over the station by claiming more than [round(100*goal_scalar,1)]% of the station!
Crew - The gangs will try to keep you on the station. Successfully evacuate the station to win!
" + world << "A violent turf war has erupted on the station!
Gangsters - Take over the station by activating and defending a Dominator!
Crew - The gangs will try to keep you on the station. Successfully evacuate the station to win!
" /////////////////////////////////////////////////////////////////////////////// @@ -73,6 +78,15 @@ modePlayer += B_bosses ..() +/datum/game_mode/gang/process(seconds) + if(!finished) + if(isnum(A_timer)) + A_timer -= seconds + if(isnum(B_timer)) + B_timer -= seconds + + ticker.mode.check_win() + /datum/game_mode/gang/proc/assign_bosses() var/datum/mind/boss = pick(antag_candidates) A_bosses += boss @@ -91,7 +105,7 @@ /datum/game_mode/proc/forge_gang_objectives(var/datum/mind/boss_mind) var/datum/objective/rival_obj = new rival_obj.owner = boss_mind - rival_obj.explanation_text = "Claim more than 50% the station before the [(boss_mind in A_bosses) ? gang_name("B") : gang_name("A")] Gang does." + rival_obj.explanation_text = "Preform a hostile takeover of the station with a Dominator." boss_mind.objectives += rival_obj @@ -103,6 +117,17 @@ boss_mind.current << "Objective #[obj_count]: [objective.explanation_text]" obj_count++ +/datum/game_mode/gang/proc/domination(var/gang,var/modifier=1,var/dominatorloc) + if(gang=="A") + A_timer = max(180,900 - ((round((ticker.mode.A_territory.len/start_state.num_territories)*200, 1) - 60) * 15)) * modifier + if(gang=="B") + B_timer = max(180,900 - ((round((ticker.mode.B_territory.len/start_state.num_territories)*200, 1) - 60) * 15)) * modifier + if(gang && dominatorloc) + priority_announce("Hostile runtimes detected in all station systems. A network breach by the [gang_name(gang)] Gang has been traced to [dominatorloc].","Network Alert") + if(get_security_level() != "delta") + set_security_level("red") + SSshuttle.emergencyNoEscape = 1 + /////////////////////////////////////////////////////////////////////////// //This equips the bosses with their gear, and makes the clown not clumsy// /////////////////////////////////////////////////////////////////////////// @@ -132,37 +157,107 @@ var/where = mob.equip_in_one_of_slots(gangtool, slots) if (!where) mob << "Your Syndicate benefactors were unfortunately unable to get you a Gangtool." + . += 1 else gangtool.register_device(mob) - mob << "The Gangtool in your [where] will allow you to use your influence to purchase items and prevent the station from evacuating before you can take over. Use it to recall the emergency shuttle from anywhere on the station." + mob << "The Gangtool in your [where] will allow you to purchase items, send messages to your gangsters and to recall the emergency shuttle from anywhere on the station." mob << "You can also promote your gang members to lieutenant by giving them an unregistered gangtool. Lieutenants cannot be deconverted and are able to use recruitment pens and gangtools." - . += 1 var/where2 = mob.equip_in_one_of_slots(T, slots) if (!where2) mob << "Your Syndicate benefactors were unfortunately unable to get you a recruitment pen to start." + . += 1 else mob << "The recruitment pen in your [where2] will help you get your gang started. Use it on unsuspecting crew members to recruit them." - . += 1 var/where3 = mob.equip_in_one_of_slots(SC, slots) if (!where3) mob << "Your Syndicate benefactors were unfortunately unable to get you a territory spraycan to start." + . += 1 else mob << "The territory spraycan in your [where3] can be used to claim areas of the station for your gang. The more territory your gang controls, the more influence you get. Distribute these to your gangsters to grow your influence faster." - . += 1 mob.update_icons() return . +//Used by recallers when purchasing a gang outfit. First time a gang outfit is purchased the buyer decides a gang style which is stored so gang outfits are uniform +/datum/game_mode/proc/gang_outfit(mob/user,var/obj/item/device/gangtool/gangtool,var/gang) + if(!user || !gangtool || !gang) + return 0 + if(!gangtool.can_use(user)) + return 0 + + var/gang_style_list = list("Gang Colors","Leather Jackets","Fine Suits") + var/style + var/headgear + if(gang == "A") + if(!gang_A_style) + gang_A_style = input("Pick an outfit style.", "Pick Style") as null|anything in gang_style_list + if(gang_A_style && (alert(user,"Include headgear?","Option","Yes","No") == "Yes")) + gang_A_headgear = 1 + style = gang_A_style + headgear = gang_A_headgear + + if(gang == "B") + if(!gang_B_style) + gang_B_style = input("Pick an outfit style.", "Pick Style") as null|anything in gang_style_list + if(gang_B_style && (alert(user,"Include headgear?","Option","Yes","No") == "Yes")) + gang_B_headgear = 1 + style = gang_B_style + headgear = gang_B_headgear + + if(!style) + return 0 + + if(gangtool.can_use(user) && (((gang == "A") ? gang_points.A : gang_points.B) >= 1)) + switch(style) + if("Gang Colors") + if(gang == "A") + new /obj/item/clothing/under/color/blue(user.loc) + if(headgear) + new /obj/item/clothing/mask/bandana/blue(user.loc) + if(gang == "B") + new /obj/item/clothing/under/color/red(user.loc) + if(headgear) + new /obj/item/clothing/mask/bandana/red(user.loc) + if("Leather Jackets") + new /obj/item/clothing/suit/jacket/leather(user.loc) + if(headgear) + if(gang == "A") + new /obj/item/clothing/mask/bandana/blue(user.loc) + if(gang == "B") + new /obj/item/clothing/mask/bandana/red(user.loc) + if("Fine Suits") + new /obj/item/clothing/under/suit_jacket/really_black(user.loc) + if(headgear) + new /obj/item/clothing/head/fedora(user.loc) + + return 1 + + return 0 + ///////////////////////////////////////////// //Checks if the either gang have won or not// ///////////////////////////////////////////// /datum/game_mode/gang/check_win() - if(A_territory.len > (start_state.num_territories * goal_scalar)) - finished = "A" //Gang A wins - else if(B_territory.len > (start_state.num_territories * goal_scalar)) - finished = "B" //Gang B wins + var/winner = 0 + + if(isnum(A_timer)) + if(A_timer < 0) + winner += 1 + if(isnum(B_timer)) + if(B_timer < 0) + winner += 2 + + if(winner) + if(winner == 3) //Edge Case: If both dominators activate at the same time + domination("A",0.5) + domination("B",0.5) + priority_announce("Multiple station takeover attempts have made simultaneously. Conflicting hostile runtimes have delayed both attempts.","Network Alert") + else if(winner == 1) + finished = "A" //Gang A wins + else if(winner == 2) + finished = "B" //Gang B wins /////////////////////////////// //Checks if the round is over// @@ -282,7 +377,7 @@ if(!finished) world << "The station was [station_was_nuked ? "destroyed!" : "evacuated before either gang could claim it!"]" else - world << "The [finished=="A" ? gang_name("A") : gang_name("B")] Gang has claimed over [round(100*goal_scalar,1)]% of the station and has assumed control!" + world << "The [finished=="A" ? gang_name("A") : gang_name("B")] Gang successfully preformed a hostile takeover of the station!!" ..() return 1 @@ -338,8 +433,8 @@ ////////////////////////////////////////////////////////// /datum/gang_points - var/A = 30 - var/B = 30 + var/A = 25 + var/B = 25 var/next_point_interval = 1800 var/next_point_time @@ -429,12 +524,9 @@ var/A_control = round((ticker.mode.A_territory.len/start_state.num_territories)*100, 1) var/B_control = round((ticker.mode.B_territory.len/start_state.num_territories)*100, 1) ticker.mode.message_gangtools((ticker.mode.A_tools),"Your gang now has [A_control]% control of the station.",0) - ticker.mode.message_gangtools((ticker.mode.A_tools),"The [gang_name("B")] Gang has [B_control]% control of the station.",0,1) + //ticker.mode.message_gangtools((ticker.mode.A_tools),"The [gang_name("B")] Gang has [B_control]% control of the station.",0,1) ticker.mode.message_gangtools((ticker.mode.B_tools),"Your gang now has [B_control]% control of the station.",0) - ticker.mode.message_gangtools((ticker.mode.B_tools),"The [gang_name("A")] Gang has [A_control]% control of the station.",0,1) - - //Victory check - ticker.mode.check_win() + //ticker.mode.message_gangtools((ticker.mode.B_tools),"The [gang_name("A")] Gang has [A_control]% control of the station.",0,1) //Restart the counter start() diff --git a/code/game/objects/items/devices/recaller.dm b/code/game/gamemodes/gang/recaller.dm similarity index 72% rename from code/game/objects/items/devices/recaller.dm rename to code/game/gamemodes/gang/recaller.dm index de3f046635c..addef28d740 100644 --- a/code/game/objects/items/devices/recaller.dm +++ b/code/game/gamemodes/gang/recaller.dm @@ -2,7 +2,7 @@ /obj/item/device/gangtool name = "suspicious device" desc = "A strange device of sorts. Hard to really make out what it actually does just by looking." - icon_state = "recaller" + icon_state = "gangtool" item_state = "walkietalkie" throwforce = 0 w_class = 1.0 @@ -33,30 +33,28 @@ else dat += "Register Device
" else + var/datum/game_mode/gang/gangmode + if(istype(ticker.mode, /datum/game_mode/gang)) + gangmode = ticker.mode + var/gang_size = ((gang == "A")? (ticker.mode.A_gang.len + ticker.mode.A_bosses.len) : (ticker.mode.B_gang.len + ticker.mode.B_bosses.len)) var/gang_territory = ((gang == "A")? ticker.mode.A_territory.len : ticker.mode.B_territory.len) var/points = ((gang == "A") ? ticker.mode.gang_points.A : ticker.mode.gang_points.B) + var/timer + if(gangmode) + timer = ((gang == "A") ? gangmode.A_timer : gangmode.B_timer) + if(isnum(timer)) + dat += "
Takeover In Progress:
[timer] seconds remain

" dat += "Registration: [(gang == "A")? gang_name("A") : gang_name("B")] Gang [boss ? "Administrator" : "Lieutenant"]
" - dat += "Organization Size: [gang_size]
" - dat += "Station Control: [round((gang_territory/start_state.num_territories)*100, 1)]%
" + dat += "Organization Size: [gang_size] | Station Control: [round((gang_territory/start_state.num_territories)*100, 1)]%
" + dat += "Send Gang-wide Message
" dat += "Recall Emergency Shuttle
" dat += "
" dat += "Influence: [points]
" - dat += "Time until Influence grows: [(points >= 100) ? ("--:--") : (time2text(ticker.mode.gang_points.next_point_time - world.time, "mm:ss"))]
" - dat += "Purchase Items:
" - - dat += "(5 Influence) " - if(points >= 5) - dat += "Send Gang-wide Message
" - else - dat += "Send Gang-wide Message
" - - dat += "(10 Influence) " - if(points >= 10) - dat += "Territory Spraycan
" - else - dat += "Territory Spraycan
" + dat += "Time until Influence grows: [(points >= 999) ? ("--:--") : (time2text(ticker.mode.gang_points.next_point_time - world.time, "mm:ss"))]
" + dat += "
" + dat += "Purchase Weapons:
" dat += "(10 Influence) " if(points >= 10) @@ -64,8 +62,8 @@ else dat += "Switchblade
" - dat += "(25 Influence) " - if(points >= 25) + dat += "(20 Influence) " + if(points >= 20) dat += "10mm Pistol
" else dat += "10mm Pistol
" @@ -76,8 +74,35 @@ else dat += "10mm Ammo
" - dat += "(40 Influence) " - if(points >= 40) + dat += "(50 Influence) " + if(points >= 50) + dat += "Thompson SMG
" + else + dat += "Thompson SMG
" + + dat += "
" + dat += "Purchase Utilities:
" + + dat += "(10 Influence) " + if(points >= 10) + dat += "Territory Spraycan
" + else + dat += "Territory Spraycan
" + + dat += "(1 Influence) " + if(points >= 1) + dat += "Gang Outfit
" + else + dat += "Gang Outfit
" + + dat += "(10 Influence) " + if(points >= 10) + dat += "Bulletproof Vest
" + else + dat += "Bulletproof Vest
" + + dat += "(30 Influence) " + if(points >= 30) dat += "Recruitment Pen
" else dat += "Recruitment Pen
" @@ -91,14 +116,23 @@ dat += "Promote a Gangster
" else dat += "Promote a Gangster
" + if(gangmode) + dat += "(50 Influence) " + if(points >= 50) + dat += "Station Dominator
" + dat += "(Estimated Takeover Time: [round(max(180,900 - ((round((gang_territory/start_state.num_territories)*200, 10) - 60) * 15))/60,1)] minutes)
" + else + dat += "Station Dominator
" dat += "
" dat += "Refresh
" - var/datum/browser/popup = new(user, "gangtool", "Welcome to GangTool v0.4") + var/datum/browser/popup = new(user, "gangtool", "Welcome to GangTool v0.4", 350, 550) popup.set_content(dat) popup.open() + + /obj/item/device/gangtool/Topic(href, href_list) if(!can_use(usr)) return @@ -115,6 +149,10 @@ var/points = ((gang == "A") ? ticker.mode.gang_points.A : ticker.mode.gang_points.B) var/item_type switch(href_list["purchase"]) + if("outfit") + if(points >= 1) + item_type = ticker.mode.gang_outfit(usr,src,gang) + points = 1 if("spraycan") if(points >= 10) item_type = /obj/item/toy/crayon/spraycan/gang @@ -124,31 +162,60 @@ item_type = /obj/item/weapon/switchblade points = 10 if("pistol") - if(points >= 25) + if(points >= 20) item_type = /obj/item/weapon/gun/projectile/automatic/pistol - points = 25 + points = 20 if("ammo") if(points >= 10) item_type = /obj/item/ammo_box/magazine/m10mm points = 10 + if("SMG") + if(points >= 50) + item_type = /obj/item/weapon/gun/projectile/automatic/tommygun + points = 50 + if("vest") + if(points >= 10) + item_type = /obj/item/clothing/suit/armor/bulletproof + points = 10 if("pen") - if(points >= 40) + if(points >= 30) item_type = /obj/item/weapon/pen/gang - points = 40 + points = 30 if("gangtool") if((promotions < 3) && (points >= (promotions*20)+10)) item_type = /obj/item/device/gangtool/lt points = (promotions*20)+10 promotions++ + if("dominator") + if(istype(ticker.mode, /datum/game_mode/gang)) + var/datum/game_mode/gang/mode = ticker.mode + if(isnum((gang == "A") ? mode.A_timer : mode.B_timer)) + return + + var/fail = 0 + var/usrarea = get_area(usr.loc) + var/usrturf = get_turf(usr.loc) + if(istype(usrarea,/area/space) || istype(usrturf,/turf/space) || usr.z != 1) + usr << "You can only use this on the station!" + fail = 1 + for(var/obj/obj in usrturf) + if(obj.density) + usr << "There's not enough room here!" + fail = 1 + break + if(!fail && points >= 50) + item_type = /obj/machinery/dominator + points = 50 if(item_type) if(gang == "A") ticker.mode.gang_points.A -= points else if(gang == "B") ticker.mode.gang_points.B -= points - var/obj/purchased = new item_type(get_turf(usr)) - var/mob/living/carbon/human/H = usr - H.put_in_any_hand_if_possible(purchased) + if(ispath(item_type)) + var/obj/purchased = new item_type(get_turf(usr)) + var/mob/living/carbon/human/H = usr + H.put_in_any_hand_if_possible(purchased) ticker.mode.message_gangtools(((gang=="A")? ticker.mode.A_tools : ticker.mode.B_tools), "A [href_list["purchase"]] was purchased by [usr] for [points] Influence.") log_game("A [href_list["purchase"]] was purchased by [key_name(usr)] for [points] Influence.") @@ -172,18 +239,16 @@ return var/list/members = list() if(gang == "A") - if(ticker.mode.gang_points.A >= 5) - members += ticker.mode.A_bosses | ticker.mode.A_gang - ticker.mode.gang_points.A -= 5 + members += ticker.mode.A_bosses | ticker.mode.A_gang else if(gang == "B") - if(ticker.mode.gang_points.B >= 5) - members += ticker.mode.B_bosses | ticker.mode.B_gang - ticker.mode.gang_points.B -= 5 + members += ticker.mode.B_bosses | ticker.mode.B_gang if(members.len) + var/ping = "[boss ? "Gang Boss" : "Gang Lieutenant"]: [message]" for(var/datum/mind/ganger in members) if(ganger.current.z <= 2) - ganger.current << "BOSS: [message]" - message_admins("[key_name_admin(user)] sent a global message to the [gang_name(gang)] Gang ([gang]): [message].") + ganger.current << "[ping]" + for(var/mob/M in dead_mob_list) + M << "[gang_name(gang)] [ping]" log_game("[key_name(user)] sent a global message to the [gang_name(gang)] Gang ([gang]): [message].") @@ -196,6 +261,7 @@ if(user.mind in (ticker.mode.A_gang | ticker.mode.A_bosses)) ticker.mode.A_tools += src gang = "A" + icon_state = "gangtool-a" if(!(user.mind in ticker.mode.A_bosses)) ticker.mode.remove_gangster(user.mind, 0, 2) ticker.mode.A_bosses += user.mind @@ -206,6 +272,7 @@ else if(user.mind in (ticker.mode.B_gang | ticker.mode.B_bosses)) ticker.mode.B_tools += src gang = "B" + icon_state = "gangtool-b" if(!(user.mind in ticker.mode.B_bosses)) ticker.mode.remove_gangster(user.mind, 0, 2) ticker.mode.B_bosses += user.mind @@ -218,7 +285,7 @@ user << "You have been promoted to Lieutenant!" ticker.mode.forge_gang_objectives(user.mind) ticker.mode.greet_gang(user.mind,0) - user << "The Gangtool you registered will allow you to use your gang's influence to purchase items and prevent the station from evacuating before your gang can take over. Use it to recall the emergency shuttle from anywhere on the station." + user << "The Gangtool you registered will allow you to purchase items, send messages to your gangsters and to recall the emergency shuttle from anywhere on the station." user << "You may also now use recruitment pens to grow your gang membership. Use them on unsuspecting crew members to recruit them." if(!gang) usr << "ACCESS DENIED: Unauthorized user." diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index 8a58076e663..da2e49f4af7 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -182,6 +182,11 @@ log_name = "IS" category = "Utility Spells" +/datum/spellbook_entry/lichdom + name = "Bind Soul" + spell_type = /obj/effect/proc_holder/spell/targeted/lichdom + log_name = "LD" + /datum/spellbook_entry/lightningbolt name = "Lightning Bolt" spell_type = /obj/effect/proc_holder/spell/targeted/lightning diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm index 87eb95b4f42..abb5bc29586 100644 --- a/code/game/machinery/atmo_control.dm +++ b/code/game/machinery/atmo_control.dm @@ -78,6 +78,7 @@ set_frequency(frequency) /obj/machinery/air_sensor/Destroy() + SSair.atmos_machinery -= src if(radio_controller) radio_controller.remove_object(src,frequency) ..() diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm index 302860eaef4..77f019ffc99 100644 --- a/code/game/machinery/atmoalter/meter.dm +++ b/code/game/machinery/atmoalter/meter.dm @@ -18,6 +18,11 @@ src.target = locate(/obj/machinery/atmospherics/pipe) in loc return 1 +/obj/machinery/meter/Destroy() + SSair.atmos_machinery -= src + src.target = null + ..() + /obj/machinery/meter/initialize() if (!target) src.target = locate(/obj/machinery/atmospherics/pipe) in loc diff --git a/code/game/machinery/atmoalter/zvent.dm b/code/game/machinery/atmoalter/zvent.dm index 26bd2cff6c1..42e1926ef4e 100644 --- a/code/game/machinery/atmoalter/zvent.dm +++ b/code/game/machinery/atmoalter/zvent.dm @@ -9,6 +9,14 @@ var/on = 0 var/volume_rate = 800 +/obj/machinery/zvent/New() + ..() + SSair.atmos_machinery += src + +/obj/machinery/zvent/Destroy() + SSair.atmos_machinery -= src + ..() + /obj/machinery/zvent/process_atmos() //all this object does, is make its turf share air with the ones above and below it, if they have a vent too. diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index f04424c08a7..00a8bde3ac0 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -44,6 +44,8 @@ for(var/obj/item/weapon/stock_parts/manipulator/P in component_parts) speed_coeff += P.rating heal_level = (efficiency * 15) + 10 + if(heal_level > 100) + heal_level = 100 //The return of data disks?? Just for transferring between genetics machine/cloning machine. //TO-DO: Make the genetics machine accept them. @@ -224,7 +226,7 @@ use_power(7500) //This might need tweaking. return - else if((src.occupant.cloneloss <= (100 - src.heal_level)) && (!src.eject_wait) || src.occupant.health >= 100) + else if((src.occupant.cloneloss <= (100 - src.heal_level)) && (!src.eject_wait)) src.connected_message("Cloning Process Complete.") src.locked = 0 src.go_out() diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index c7fa9504a89..2b52906bbae 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -46,6 +46,8 @@ var/hasShocked = 0 //Prevents multiple shocks from happening var/autoclose = 1 + explosion_block = 1 + /obj/machinery/door/airlock/command icon = 'icons/obj/doors/Doorcom.dmi' doortype = /obj/structure/door_assembly/door_assembly_com @@ -268,6 +270,7 @@ name = "high tech security airlock" icon = 'icons/obj/doors/hightechsecurity.dmi' doortype = /obj/structure/door_assembly/door_assembly_highsecurity + explosion_block = 2 /obj/machinery/door/airlock/shuttle name = "shuttle airlock" diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index e558ccbac61..c1836108462 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -6,6 +6,7 @@ var/id = 1 var/auto_close = 0 // Time in seconds to automatically close when opened, 0 if it doesn't. sub_door = 1 + explosion_block = 3 heat_proof = 1 /obj/machinery/door/poddoor/preopen @@ -87,318 +88,27 @@ operating = 0 +//"BLAST" doors are obviously stronger than regular doors when it comes to BLASTS. +/obj/machinery/door/poddoor/ex_act(severity, target) + switch(severity) + if(1.0) + if(prob(80)) + qdel(src) + else + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() + if(2.0) + if(prob(20)) + qdel(src) + else + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() + if(3.0) + if(prob(80)) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(2, 1, src) + s.start() -/* -/obj/machinery/door/poddoor/two_tile_hor/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - src.SetOpacity(0) - f1.SetOpacity(0) - f2.SetOpacity(0) - - sleep(10) - src.density = 0 - f1.density = 0 - f2.density = 0 - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/two_tile_hor/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - - src.density = 1 - f1.density = 1 - f2.density = 1 - - sleep(10) - src.SetOpacity(initial(opacity)) - f1.SetOpacity(initial(opacity)) - f2.SetOpacity(initial(opacity)) - - update_nearby_tiles() - - src.operating = 0 - return - -/obj/machinery/door/poddoor/four_tile_hor/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - sleep(10) - src.density = 0 - src.sd_SetOpacity(0) - - f1.density = 0 - f1.sd_SetOpacity(0) - f2.density = 0 - f2.sd_SetOpacity(0) - f3.density = 0 - f3.sd_SetOpacity(0) - f4.density = 0 - f4.sd_SetOpacity(0) - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/four_tile_hor/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - src.density = 1 - - f1.density = 1 - f1.sd_SetOpacity(1) - f2.density = 1 - f2.sd_SetOpacity(1) - f3.density = 1 - f3.sd_SetOpacity(1) - f4.density = 1 - f4.sd_SetOpacity(1) - - if (src.visible) - src.sd_SetOpacity(1) - update_nearby_tiles() - - sleep(10) - src.operating = 0 - return - -/obj/machinery/door/poddoor/two_tile_ver/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - sleep(10) - src.density = 0 - src.sd_SetOpacity(0) - - f1.density = 0 - f1.sd_SetOpacity(0) - f2.density = 0 - f2.sd_SetOpacity(0) - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/two_tile_ver/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - src.density = 1 - - f1.density = 1 - f1.sd_SetOpacity(1) - f2.density = 1 - f2.sd_SetOpacity(1) - - if (src.visible) - src.sd_SetOpacity(1) - update_nearby_tiles() - - sleep(10) - src.operating = 0 - return - -/obj/machinery/door/poddoor/four_tile_ver/open() - if (src.operating == 1) //doors can still open when emag-disabled - return - if (!ticker) - return 0 - if(!src.operating) //in case of emag - src.operating = 1 - flick("pdoorc0", src) - src.icon_state = "pdoor0" - sleep(10) - src.density = 0 - src.sd_SetOpacity(0) - - f1.density = 0 - f1.sd_SetOpacity(0) - f2.density = 0 - f2.sd_SetOpacity(0) - f3.density = 0 - f3.sd_SetOpacity(0) - f4.density = 0 - f4.sd_SetOpacity(0) - - update_nearby_tiles() - - if(operating == 1) //emag again - src.operating = 0 - if(autoclose) - spawn(150) - autoclose() - return 1 - -/obj/machinery/door/poddoor/four_tile_ver/close() - if (src.operating) - return - src.operating = 1 - flick("pdoorc1", src) - src.icon_state = "pdoor1" - src.density = 1 - - f1.density = 1 - f1.sd_SetOpacity(1) - f2.density = 1 - f2.sd_SetOpacity(1) - f3.density = 1 - f3.sd_SetOpacity(1) - f4.density = 1 - f4.sd_SetOpacity(1) - - if (src.visible) - src.sd_SetOpacity(1) - update_nearby_tiles() - - sleep(10) - src.operating = 0 - return - - - - -/obj/machinery/door/poddoor/two_tile_hor - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - icon = 'icons/obj/doors/1x2blast_hor.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(src,EAST)) - f1.density = density - f2.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - - Destroy() - qdel(f1) - qdel(f2) - ..() - -/obj/machinery/door/poddoor/two_tile_ver - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - icon = 'icons/obj/doors/1x2blast_vert.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(src,NORTH)) - f1.density = density - f2.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - - Destroy() - qdel(f1) - qdel(f2) - ..() - -/obj/machinery/door/poddoor/four_tile_hor - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - var/obj/machinery/door/poddoor/filler_object/f3 - var/obj/machinery/door/poddoor/filler_object/f4 - icon = 'icons/obj/doors/1x4blast_hor.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(f1,EAST)) - f3 = new/obj/machinery/door/poddoor/filler_object (get_step(f2,EAST)) - f4 = new/obj/machinery/door/poddoor/filler_object (get_step(f3,EAST)) - f1.density = density - f2.density = density - f3.density = density - f4.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - f4.sd_SetOpacity(opacity) - f3.sd_SetOpacity(opacity) - - Destroy() - qdel(f1) - qdel(f2) - qdel(f3) - qdel(f4) - ..() - -/obj/machinery/door/poddoor/four_tile_ver - var/obj/machinery/door/poddoor/filler_object/f1 - var/obj/machinery/door/poddoor/filler_object/f2 - var/obj/machinery/door/poddoor/filler_object/f3 - var/obj/machinery/door/poddoor/filler_object/f4 - icon = 'icons/obj/doors/1x4blast_vert.dmi' - - New() - ..() - f1 = new/obj/machinery/door/poddoor/filler_object (src.loc) - f2 = new/obj/machinery/door/poddoor/filler_object (get_step(f1,NORTH)) - f3 = new/obj/machinery/door/poddoor/filler_object (get_step(f2,NORTH)) - f4 = new/obj/machinery/door/poddoor/filler_object (get_step(f3,NORTH)) - f1.density = density - f2.density = density - f3.density = density - f4.density = density - f1.sd_SetOpacity(opacity) - f2.sd_SetOpacity(opacity) - f4.sd_SetOpacity(opacity) - f3.sd_SetOpacity(opacity) - - Destroy() - qdel(f1) - qdel(f2) - qdel(f3) - qdel(f4) - ..() - -/obj/machinery/door/poddoor/filler_object - name = "" - icon_state = "" - -*/ \ No newline at end of file diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm index df94284c2c5..f8c634f9724 100644 --- a/code/game/machinery/doors/unpowered.dm +++ b/code/game/machinery/doors/unpowered.dm @@ -21,4 +21,5 @@ name = "door" icon_state = "door1" opacity = 1 - density = 1 \ No newline at end of file + density = 1 + explosion_block = 1 \ No newline at end of file diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 63620b72676..7e1fd4d977c 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -90,6 +90,18 @@ for(var/turf/T in trange(max_range, epicenter)) var/dist = cheap_pythag(T.x - x0,T.y - y0) + + if(config.reactionary_explosions) + var/turf/Trajectory = T + while(Trajectory != epicenter) + Trajectory = get_step_towards(Trajectory, epicenter) + if(Trajectory.density && Trajectory.explosion_block) + dist += Trajectory.explosion_block + + for(var/obj/machinery/door/D in Trajectory) + if(D.density && D.explosion_block) + dist += D.explosion_block + var/flame_dist = 0 var/throw_dist = dist @@ -138,3 +150,76 @@ /proc/secondaryexplosion(turf/epicenter, range) for(var/turf/tile in trange(range, epicenter)) tile.ex_act(2) + + +/client/proc/check_bomb_impacts() + set name = "Check Bomb Impact" + set category = "Debug" + + var/newmode = alert("Use reactionary explosions?","Check Bomb Impact", "Yes", "No") + var/turf/epicenter = get_turf(mob) + if(!epicenter) + return + + var/dev = 0 + var/heavy = 0 + var/light = 0 + var/list/choices = list("Small Bomb","Medium Bomb","Big Bomb","Custom Bomb") + var/choice = input("Bomb Size?") in choices + switch(choice) + if(null) + return 0 + if("Small Bomb") + dev = 1 + heavy = 2 + light = 3 + if("Medium Bomb") + dev = 2 + heavy = 3 + light = 4 + if("Big Bomb") + dev = 3 + heavy = 5 + light = 7 + if("Custom Bomb") + dev = input("Devestation range (Tiles):") as num + heavy = input("Heavy impact range (Tiles):") as num + light = input("Light impact range (Tiles):") as num + + var/max_range = max(dev, heavy, light) + var/x0 = epicenter.x + var/y0 = epicenter.y + var/list/wipe_colours = list() + for(var/turf/T in trange(max_range, epicenter)) + wipe_colours += T + var/dist = cheap_pythag(T.x - x0, T.y - y0) + + if(newmode == "Yes") + var/turf/TT = T + while(TT != epicenter) + TT = get_step_towards(TT,epicenter) + if(TT.density && TT.explosion_block) + dist += TT.explosion_block + + for(var/obj/machinery/door/D in TT) + if(D.density && D.explosion_block) + dist += D.explosion_block + + if(dist < dev) + T.color = "red" + T.maptext = "Dev" + else if (dist < heavy) + T.color = "yellow" + T.maptext = "Heavy" + else if (dist < light) + T.color = "blue" + T.maptext = "Light" + else + continue + + sleep(100) + for(var/turf/T in wipe_colours) + T.color = null + T.maptext = "" + + diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 731a7324b81..a512741096f 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -97,10 +97,7 @@ /obj/item/toy/crayon/spraycan/New() ..() - if(gang) - name = "Modified Paint Applicator" - else - name = "NanoTrasen-brand Rapid Paint Applicator" + name = "spray can" update_icon() /obj/item/toy/crayon/spraycan/examine(mob/user) @@ -116,7 +113,7 @@ if("Toggle Cap") user << "You [capped ? "Remove" : "Replace"] the cap of the [src]" capped = capped ? 0 : 1 - icon_state = "spraycan[gang ? "_gang" : ""][capped ? "_cap" : ""]" + icon_state = "spraycan[capped ? "_cap" : ""]" update_icon() if("Change Drawing") ..() @@ -155,8 +152,7 @@ overlays += I /obj/item/toy/crayon/spraycan/gang - desc = "A suspicious-looking spraycan modified to use special paint used by gangsters to mark territory." - icon_state = "spraycan_gang_cap" + desc = "A modified container containing suspicious paint." gang = 1 uses = 20 instant = -1 diff --git a/code/game/objects/items/holotape.dm b/code/game/objects/items/holotape.dm index bd10a107cad..68070972d6e 100644 --- a/code/game/objects/items/holotape.dm +++ b/code/game/objects/items/holotape.dm @@ -153,6 +153,8 @@ charging = 0 /obj/item/holotape/Bumped(var/mob/M) + if(!ismob(M)) + return if(iscarbon(M)) var/mob/living/carbon/C = M if(C.m_intent == "walk") @@ -227,11 +229,11 @@ /obj/item/holotape/proc/breaktape() var/dir[2] - var/icon_dir = src.icon_state - if(icon_dir == "[src.icon_base]_h") + var/icon_dir = icon_state + if(icon_dir == "[icon_base]_h") dir[1] = EAST dir[2] = WEST - if(icon_dir == "[src.icon_base]_v") + if(icon_dir == "[icon_base]_v") dir[1] = NORTH dir[2] = SOUTH diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index 92ebff9c716..7519804b005 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -335,3 +335,17 @@ ..() +/* + * Chemistry bag + */ + +/obj/item/weapon/storage/bag/chemistry + name = "chemistry bag" + icon = 'icons/obj/chemical.dmi' + icon_state = "bag" + desc = "A bag for storing pills, patches, and bottles." + storage_slots = 50 + max_combined_w_class = 200 + w_class = 1 + preposition = "in" + can_hold = list(/obj/item/weapon/reagent_containers/pill, /obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/reagent_containers/glass/bottle) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 47124bc5a34..1425cfd6e71 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -68,7 +68,7 @@ return (!density) /obj/structure/closet/proc/can_open() - if(src.welded || src.locked) + if(welded || locked) return 0 return 1 @@ -81,32 +81,32 @@ /obj/structure/closet/proc/dump_contents() for(var/obj/O in src) - O.loc = src.loc + O.loc = loc for(var/mob/M in src) - M.loc = src.loc + M.loc = loc if(M.client) M.client.eye = M.client.mob M.client.perspective = MOB_PERSPECTIVE /obj/structure/closet/proc/take_contents() - for(var/atom/movable/AM in src.loc) + for(var/atom/movable/AM in loc) if(insert(AM) == -1) // limit reached break /obj/structure/closet/proc/open() - if(src.opened) + if(opened) return 0 - if(!src.can_open()) + if(!can_open()) return 0 - src.dump_contents() + dump_contents() - src.opened = 1 + opened = 1 if(istype(src, /obj/structure/closet/body_bag)) - playsound(src.loc, 'sound/items/zip.ogg', 15, 1, -3) + playsound(loc, 'sound/items/zip.ogg', 15, 1, -3) else - playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) + playsound(loc, 'sound/machines/click.ogg', 15, 1, -3) density = 0 update_icon() return 1 @@ -139,25 +139,25 @@ return 1 /obj/structure/closet/proc/close() - if(!src.opened) + if(!opened) return 0 - if(!src.can_close()) + if(!can_close()) return 0 take_contents() - src.opened = 0 + opened = 0 if(istype(src, /obj/structure/closet/body_bag)) - playsound(src.loc, 'sound/items/zip.ogg', 15, 1, -3) + playsound(loc, 'sound/items/zip.ogg', 15, 1, -3) else - playsound(src.loc, 'sound/machines/click.ogg', 15, 1, -3) + playsound(loc, 'sound/machines/click.ogg', 15, 1, -3) density = 1 update_icon() return 1 /obj/structure/closet/proc/toggle() - if(src.opened) - return src.close() - return src.open() + if(opened) + return close() + return open() /obj/structure/closet/ex_act(severity, target) contents_explosion(severity, target) @@ -192,9 +192,9 @@ return if(opened) if(istype(W, /obj/item/weapon/grab)) - if(src.large) + if(large) var/obj/item/weapon/grab/G = W - src.MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet + MouseDrop_T(G.affecting, user) //act like they were dragged onto the closet user.drop_item() else user << "The locker is too small to stuff [W] into!" @@ -210,7 +210,7 @@ if( !opened || !istype(src, /obj/structure/closet) || !user || !WT || !WT.isOn() || !user.loc ) return playsound(loc, 'sound/items/Welder2.ogg', 50, 1) - new /obj/item/stack/sheet/metal(src.loc) + new /obj/item/stack/sheet/metal(loc) visible_message("[user] has cut \the [src] apart with \the [WT].", "You hear welding.") qdel(src) return @@ -239,10 +239,10 @@ user << "The locker appears to be broken." return if(!place(user, W) && !isnull(W)) - src.attack_hand(user) + attack_hand(user) /obj/structure/closet/proc/place(var/mob/user, var/obj/item/I) - if(!src.opened && secure) + if(!opened && secure) togglelock(user) return 1 return 0 @@ -258,21 +258,21 @@ return 0 if(!istype(user.loc, /turf)) // are you in a container/closet/pod/etc? Will also check for null loc return 0 - if(needs_opened && !src.opened) + if(needs_opened && !opened) return 0 if(istype(O, /obj/structure/closet)) return 0 if(move_them) - step_towards(O, src.loc) + step_towards(O, loc) if(show_message && user != O) user.show_viewers("[user] stuffs [O] into [src]!") - src.add_fingerprint(user) + add_fingerprint(user) return 1 /obj/structure/closet/relaymove(mob/user as mob) - if(user.stat || !isturf(src.loc)) + if(user.stat || !isturf(loc)) return - if(!src.open()) + if(!open()) user << "It won't budge!" if(world.time > lastbang+5) lastbang = world.time @@ -281,19 +281,20 @@ /obj/structure/closet/attack_paw(mob/user as mob) - return src.attack_hand(user) + return attack_hand(user) /obj/structure/closet/attack_hand(mob/user as mob) - src.add_fingerprint(user) + add_fingerprint(user) if(user.lying && get_dist(src, user) > 0) return - if(!src.toggle()) - return src.attackby(null, user) + if(!toggle()) + user << "You cannot close the locker!" + return // tk grab then use on self /obj/structure/closet/attack_self_tk(mob/user as mob) - return src.attack_hand(user) + return attack_hand(user) /obj/structure/closet/verb/verb_toggleopen() set src in oview(1) @@ -304,7 +305,7 @@ return if(iscarbon(usr) || issilicon(usr)) - src.attack_hand(usr) + attack_hand(usr) else usr << "This mob type can't use this verb." @@ -322,7 +323,7 @@ if(istype(user.loc, /obj/structure/closet/critter) && !welded) breakout_time = 0.75 //45 seconds if it's an unwelded critter crate - if( opened || (!welded && !locked && !istype(src.loc, /obj/mecha)) ) + if( opened || (!welded && !locked && !istype(loc, /obj/mecha)) ) return //Door's open, not locked or welded or inside a mech, no point in resisting. //okay, so the closet is either welded or locked... resist!!! @@ -332,7 +333,7 @@ for(var/mob/O in viewers(src)) O << "[src] begins to shake violently!" if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds - if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded && !istype(src.loc, /obj/mecha)) ) + if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded && !istype(loc, /obj/mecha)) ) return //we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting @@ -340,11 +341,11 @@ locked = 0 //applies to critter crates and secure lockers only broken = 1 //applies to secure lockers only user.visible_message("[user] successfully broke out of [src]!", "You successfully break out of [src]!") - if(istype( src.loc, /obj/structure/bigDelivery)) - var/obj/structure/bigDelivery/D = src.loc + if(istype( loc, /obj/structure/bigDelivery)) + var/obj/structure/bigDelivery/D = loc qdel(D) - else if(istype( src.loc, /obj/mecha)) - src.loc = get_turf(src.loc) + else if(istype( loc, /obj/mecha)) + loc = get_turf(loc) open() else user << "You fail to break out of [src]!" @@ -354,7 +355,7 @@ if(!user.canUseTopic(user) || broken) user << "You can't do that right now!" return - if(src.opened || !secure || !in_range(src, user)) + if(opened || !secure || !in_range(src, user)) return else togglelock(user) @@ -364,20 +365,20 @@ O.emp_act(severity) if(secure && !broken) if(prob(50/severity)) - src.locked = !src.locked - src.update_icon() + locked = !locked + update_icon() if(prob(20/severity) && !opened) if(!locked) open() else - src.req_access = list() - src.req_access += pick(get_all_accesses()) + req_access = list() + req_access += pick(get_all_accesses()) ..() /obj/structure/closet/proc/togglelock(mob/user as mob) if(secure) - if(src.allowed(user)) - src.locked = !src.locked + if(allowed(user)) + locked = !locked add_fingerprint(user) for(var/mob/O in viewers(user, 3)) if((O.client && !( O.eye_blind ))) diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index a4510966df7..37433c2423c 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -311,6 +311,8 @@ new /obj/item/weapon/storage/backpack/chemistry(src) new /obj/item/weapon/storage/backpack/satchel_chem(src) new /obj/item/weapon/storage/backpack/satchel_chem(src) + new /obj/item/weapon/storage/bag/chemistry(src) + new /obj/item/weapon/storage/bag/chemistry(src) return diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 6eb5f7b9317..ffe58681ab0 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -106,7 +106,20 @@ name = "magic mirror" desc = "Turn and face the strange... face." icon_state = "magic_mirror" + var/list/races_blacklist = list("skeleton") + var/list/choosable_races = list() +/obj/structure/mirror/magic/New() + if(!choosable_races.len) + for(var/datum/species/S in typesof(/datum/species) - /datum/species) + if(!(S.id in races_blacklist)) + choosable_races += S + ..() + +/obj/structure/mirror/magic/badmin/New() + for(var/datum/species/S in typesof(/datum/species) - /datum/species) + choosable_races += S + ..() /obj/structure/mirror/magic/attack_hand(mob/user as mob) if(!ishuman(user)) @@ -130,7 +143,7 @@ if("race") var/newrace - var/racechoice = input(H, "What are we again?", "Race change") as null|anything in species_list + var/racechoice = input(H, "What are we again?", "Race change") as null|anything in choosable_races newrace = species_list[racechoice] if(!newrace || !H.dna) diff --git a/code/game/objects/structures/table_frames.dm b/code/game/objects/structures/table_frames.dm index 0fed8ff3a77..5196a37fa9d 100644 --- a/code/game/objects/structures/table_frames.dm +++ b/code/game/objects/structures/table_frames.dm @@ -32,28 +32,38 @@ return if(istype(I, /obj/item/stack/sheet/plasteel)) var/obj/item/stack/sheet/plasteel/P = I + if(P.get_amount() < 1) + user << "You need one plasteel sheet to do this!" + return user << "You start adding [P] to [src]..." if(do_after(user, 50, target = src)) + P.use(1) new /obj/structure/table/reinforced(src.loc) qdel(src) - P.use(1) - return + return if(istype(I, /obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/metal/M = I + if(M.get_amount() < 1) + user << "You need one metal sheet to do this!" + return user << "You start adding [M] to [src]..." if(do_after(user, 20, target = src)) + M.use(1) new /obj/structure/table(src.loc) qdel(src) - M.use(1) - return + return if(istype(I, /obj/item/stack/sheet/glass)) var/obj/item/stack/sheet/glass/G = I + if(G.get_amount() < 1) + user << "You need one glass sheet to do this!" + return user << "You start adding [G] to [src]..." if(do_after(user, 20, target = src)) + G.use(1) + new /obj/structure/table/glass(src.loc) qdel(src) - G.use(1) - return + return /* * Wooden Frames @@ -71,17 +81,23 @@ ..() if(istype(I, /obj/item/stack/sheet/mineral/wood)) var/obj/item/stack/sheet/mineral/wood/W = I + if(W.get_amount() < 1) + user << "You need one wood sheet to do this!" + return user << "You start adding [W] to [src]..." if(do_after(user, 20, target = src)) + W.use(1) new /obj/structure/table/wood(src.loc) qdel(src) - W.use(1) - return + return if(istype(I, /obj/item/stack/tile/carpet)) var/obj/item/stack/tile/carpet/C = I + if(C.get_amount() < 1) + user << "You need one carpet sheet to do this!" + return user << "You start adding [C] to [src]..." if(do_after(user, 20, target = src)) + C.use(1) new /obj/structure/table/wood/poker(src.loc) qdel(src) - C.use(1) - return \ No newline at end of file + return diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index 4b304c10330..4f0227a972e 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -29,7 +29,7 @@ /obj/structure/windoor_assembly/New(dir=NORTH) ..() - src.ini_dir = src.dir + ini_dir = dir air_update_turf(1) /obj/structure/windoor_assembly/Destroy() @@ -77,7 +77,7 @@ var/obj/item/weapon/weldingtool/WT = W if (WT.remove_fuel(0,user)) user.visible_message("[user] disassembles the windoor assembly.", "You start to disassemble the windoor assembly...") - playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1) + playsound(loc, 'sound/items/Welder2.ogg', 50, 1) if(do_after(user, 40, target = src)) if(!src || !WT.isOn()) return @@ -93,41 +93,41 @@ //Wrenching an unsecure assembly anchors it in place. Step 4 complete if(istype(W, /obj/item/weapon/wrench) && !anchored) - for(var/obj/machinery/door/window/WD in src.loc) - if(WD.dir == src.dir) + for(var/obj/machinery/door/window/WD in loc) + if(WD.dir == dir) user << "There is already a windoor in that location!" return - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + playsound(loc, 'sound/items/Ratchet.ogg', 100, 1) user.visible_message("[user] secures the windoor assembly to the floor.", "You start to secure the windoor assembly to the floor...") if(do_after(user, 40, target = src)) - if(!src || src.anchored) + if(!src || anchored) return - for(var/obj/machinery/door/window/WD in src.loc) - if(WD.dir == src.dir) + for(var/obj/machinery/door/window/WD in loc) + if(WD.dir == dir) user << "There is already a windoor in that location!" return user << "You secure the windoor assembly." - src.anchored = 1 - if(src.secure) - src.name = "secure anchored windoor assembly" + anchored = 1 + if(secure) + name = "secure anchored windoor assembly" else - src.name = "anchored windoor assembly" + name = "anchored windoor assembly" //Unwrenching an unsecure assembly un-anchors it. Step 4 undone else if(istype(W, /obj/item/weapon/wrench) && anchored) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + playsound(loc, 'sound/items/Ratchet.ogg', 100, 1) user.visible_message("[user] unsecures the windoor assembly to the floor.", "You start to unsecure the windoor assembly to the floor...") if(do_after(user, 40, target = src)) - if(!src || !src.anchored) + if(!src || !anchored) return user << "You unsecure the windoor assembly." - src.anchored = 0 - if(src.secure) - src.name = "secure windoor assembly" + anchored = 0 + if(secure) + name = "secure windoor assembly" else - src.name = "windoor assembly" + name = "windoor assembly" //Adding plasteel makes the assembly a secure windoor assembly. Step 2 (optional) complete. else if(istype(W, /obj/item/stack/sheet/plasteel) && !secure) @@ -143,27 +143,29 @@ P.use(2) user << "You reinforce the windoor." - src.secure = 1 - if(src.anchored) - src.name = "secure anchored windoor assembly" + secure = 1 + if(anchored) + name = "secure anchored windoor assembly" else - src.name = "secure windoor assembly" + name = "secure windoor assembly" //Adding cable to the assembly. Step 5 complete. else if(istype(W, /obj/item/stack/cable_coil) && anchored) user.visible_message("[user] wires the windoor assembly.", "You start to wire the windoor assembly...") if(do_after(user, 40, target = src)) - if(!src || !src.anchored || src.state != "01") + if(!src || !anchored || src.state != "01") return var/obj/item/stack/cable_coil/CC = W - CC.use(1) + if(!CC.use(1)) + user << "You need more cable to do this!" + return user << "You wire the windoor." - src.state = "02" - if(src.secure) - src.name = "secure wired windoor assembly" + state = "02" + if(secure) + name = "secure wired windoor assembly" else - src.name = "wired windoor assembly" + name = "wired windoor assembly" else ..() @@ -171,61 +173,61 @@ //Removing wire from the assembly. Step 5 undone. if(istype(W, /obj/item/weapon/wirecutters)) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1) user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly...") if(do_after(user, 40, target = src)) - if(!src || src.state != "02") + if(!src || state != "02") return user << "You cut the windoor wires." new/obj/item/stack/cable_coil(get_turf(user), 1) - src.state = "01" - if(src.secure) - src.name = "secure anchored windoor assembly" + state = "01" + if(secure) + name = "secure anchored windoor assembly" else - src.name = "anchored windoor assembly" + name = "anchored windoor assembly" //Adding airlock electronics for access. Step 6 complete. else if(istype(W, /obj/item/weapon/airlock_electronics)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly...") user.drop_item() W.loc = src if(do_after(user, 40, target = src)) - if(!src || src.electronics) + if(!src || electronics) W.loc = src.loc return user << "You install the airlock electronics." - src.name = "near finished windoor assembly" - src.electronics = W + name = "near finished windoor assembly" + electronics = W else - W.loc = src.loc + W.loc = loc //Screwdriver to remove airlock electronics. Step 6 undone. else if(istype(W, /obj/item/weapon/screwdriver)) if(!electronics) return - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1) user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to uninstall electronics from the airlock assembly...") if(do_after(user, 40, target = src)) if(!src || !electronics) return user << "You remove the airlock electronics." - src.name = "wired windoor assembly" + name = "wired windoor assembly" var/obj/item/weapon/airlock_electronics/ae ae = electronics electronics = null - ae.loc = src.loc + ae.loc = loc else if(istype(W, /obj/item/weapon/pen)) - var/t = stripped_input(user, "Enter the name for the door.", src.name, src.created_name,MAX_NAME_LEN) + var/t = stripped_input(user, "Enter the name for the door.", name, created_name,MAX_NAME_LEN) if(!t) return - if(!in_range(src, usr) && src.loc != usr) + if(!in_range(src, usr) && loc != usr) return created_name = t return @@ -234,37 +236,37 @@ //Crowbar to complete the assembly, Step 7 complete. else if(istype(W, /obj/item/weapon/crowbar)) - if(!src.electronics) + if(!electronics) usr << "The assembly is missing electronics!" return usr << browse(null, "window=windoor_access") - playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) + playsound(loc, 'sound/items/Crowbar.ogg', 100, 1) user.visible_message("[user] pries the windoor into the frame.", "You start prying the windoor into the frame...") if(do_after(user, 40, target = src)) - if(src.loc && src.electronics) + if(loc && electronics) density = 1 //Shouldn't matter but just incase user << "You finish the windoor." if(secure) - var/obj/machinery/door/window/brigdoor/windoor = new /obj/machinery/door/window/brigdoor(src.loc) - if(src.facing == "l") + var/obj/machinery/door/window/brigdoor/windoor = new /obj/machinery/door/window/brigdoor(loc) + if(facing == "l") windoor.icon_state = "leftsecureopen" windoor.base_state = "leftsecure" else windoor.icon_state = "rightsecureopen" windoor.base_state = "rightsecure" - windoor.dir = src.dir + windoor.dir = dir windoor.density = 0 - if(src.electronics.use_one_access) - windoor.req_one_access = src.electronics.conf_access + if(electronics.use_one_access) + windoor.req_one_access = electronics.conf_access else - windoor.req_access = src.electronics.conf_access - windoor.electronics = src.electronics - src.electronics.loc = windoor + windoor.req_access = electronics.conf_access + windoor.electronics = electronics + electronics.loc = windoor if(created_name) windoor.name = created_name qdel(src) @@ -272,19 +274,19 @@ else - var/obj/machinery/door/window/windoor = new /obj/machinery/door/window(src.loc) - if(src.facing == "l") + var/obj/machinery/door/window/windoor = new /obj/machinery/door/window(loc) + if(facing == "l") windoor.icon_state = "leftopen" windoor.base_state = "left" else windoor.icon_state = "rightopen" windoor.base_state = "right" - windoor.dir = src.dir + windoor.dir = dir windoor.density = 0 - windoor.req_access = src.electronics.conf_access - windoor.electronics = src.electronics - src.electronics.loc = windoor + windoor.req_access = electronics.conf_access + windoor.electronics = electronics + electronics.loc = windoor if(created_name) windoor.name = created_name qdel(src) @@ -305,18 +307,18 @@ set src in oview(1) if(usr.stat || !usr.canmove || usr.restrained()) return - if (src.anchored) + if (anchored) usr << "It is fastened to the floor; therefore, you can't rotate it!" return 0 - //if(src.state != "01") + //if(state != "01") //update_nearby_tiles(need_rebuild=1) //Compel updates before - src.dir = turn(src.dir, 270) + dir = turn(dir, 270) - //if(src.state != "01") + //if(state != "01") //update_nearby_tiles(need_rebuild=1) - src.ini_dir = src.dir + ini_dir = dir update_icon() return @@ -328,11 +330,11 @@ if(usr.stat || !usr.canmove || usr.restrained()) return - if(src.facing == "l") + if(facing == "l") usr << "The windoor will now slide to the right." - src.facing = "r" + facing = "r" else - src.facing = "l" + facing = "l" usr << "The windoor will now slide to the left." update_icon() diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index b9462383f9b..edb1fe79b28 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -105,6 +105,28 @@ ChangeTurf(/turf/simulated/floor/plating) return + +/turf/simulated/floor/engine/ex_act(severity,target) + switch(severity) + if(1.0) + if(prob(80)) + ReplaceWithLattice() + else if(prob(50)) + qdel(src) + else + make_plating(1) + if(2.0) + if(prob(50)) + make_plating(1) + + +/turf/simulated/floor/engine/cult + name = "engraved floor" + icon_state = "cult" + +/turf/simulated/floor/engine/cult/narsie_act() + return + /turf/simulated/floor/engine/n20/New() ..() var/datum/gas_mixture/adding = new diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index 251c0d9cb46..97640c2e6af 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -6,6 +6,7 @@ opacity = 1 density = 1 blocks_air = 1 + explosion_block = 1 thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m plasteel wall diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm index c61a20cb100..fb73c1f61c6 100644 --- a/code/game/turfs/simulated/walls_mineral.dm +++ b/code/game/turfs/simulated/walls_mineral.dm @@ -17,6 +17,7 @@ mineral = "gold" //var/electro = 1 //var/shocked = null + explosion_block = 0 //gold is a soft metal you dingus. /turf/simulated/wall/mineral/silver name = "silver wall" @@ -34,6 +35,7 @@ walltype = "diamond" mineral = "diamond" slicing_duration = 200 //diamond wall takes twice as much time to slice + explosion_block = 3 /turf/simulated/wall/mineral/diamond/thermitemelt(mob/user as mob) return @@ -51,6 +53,7 @@ icon_state = "sandstone0" walltype = "sandstone" mineral = "sandstone" + explosion_block = 0 /turf/simulated/wall/mineral/uranium name = "uranium wall" @@ -143,3 +146,4 @@ walltype = "wood" mineral = "wood" hardness = 70 + explosion_block = 0 \ No newline at end of file diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm index b73fa532738..ed880a17f00 100644 --- a/code/game/turfs/simulated/walls_reinforced.dm +++ b/code/game/turfs/simulated/walls_reinforced.dm @@ -10,6 +10,7 @@ var/d_state = 0 hardness = 10 sheet_type = /obj/item/stack/sheet/plasteel + explosion_block = 2 /turf/simulated/wall/r_wall/break_wall() builtin_sheet.loc = src diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index d85eb7a75d8..1c073505ab8 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -122,6 +122,7 @@ var/list/admin_verbs_debug = list( /client/proc/test_movable_UI, /client/proc/test_snap_UI, /client/proc/debugNatureMapGenerator, + /client/proc/check_bomb_impacts, /proc/machine_upgrade ) var/list/admin_verbs_possess = list( diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 311a87950bd..14d8693c3e5 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -307,7 +307,7 @@ if(ratio) config.midround_antag_life_check = ratio/100 - message_admins("[key_name_admin(usr)] edited the midround antagonist living crew ratio to [ratio * 100]% alive.") + message_admins("[key_name_admin(usr)] edited the midround antagonist living crew ratio to [ratio]% alive.") check_antagonists() else if(href_list["toggle_noncontinuous_behavior"]) diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm index f14df6a3fc9..3125067f32b 100644 --- a/code/modules/admin/verbs/modifyvariables.dm +++ b/code/modules/admin/verbs/modifyvariables.dm @@ -142,15 +142,33 @@ var/list/VVckey_edit = list("key", "ckey") if(confirm != "Continue") return - var/list/names = sortList(L) + var/assoc = 0 + if(L.len > 0) + var/a = L[1] + if(istext(a) && L[a] != null) + assoc = 1 //This is pretty weak test but i can't think of anything else + usr << "List appears to be associative." - var/variable = input("Which var?","Var") as null|anything in names + "(ADD VAR)" + var/list/names = null + if(!assoc) + names = sortList(L) + + var/variable + var/assoc_key + if(assoc) + variable = input("Which var?","Var") as null|anything in L + "(ADD VAR)" + else + variable = input("Which var?","Var") as null|anything in names + "(ADD VAR)" if(variable == "(ADD VAR)") mod_list_add(L, O, original_name, objectvar) return - if(!variable) + if(assoc) + assoc_key = variable + variable = L[assoc_key] + + if(!assoc && !variable || assoc && !assoc_key) return var/default @@ -240,7 +258,12 @@ var/list/VVckey_edit = list("key", "ckey") if(holder.marked_datum && class == "marked datum ([holder.marked_datum.type])") class = "marked datum" - var/original_var = L[L.Find(variable)] + var/original_var + if(assoc) + original_var = L[assoc_key] + else + original_var = L[L.Find(variable)] + var/new_var switch(class) //Spits a runtime error if you try to modify an entry in the contents list. Dunno how to fix it, yet. @@ -249,7 +272,10 @@ var/list/VVckey_edit = list("key", "ckey") if("restore to default") new_var = initial(variable) - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("edit referenced object") modify_variables(variable) @@ -263,35 +289,59 @@ var/list/VVckey_edit = list("key", "ckey") if("text") new_var = input("Enter new text:","Text") as text - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("num") new_var = input("Enter new number:","Num") as num - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("type") new_var = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf) - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("reference") new_var = input("Select reference:","Reference") as mob|obj|turf|area in world - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("mob reference") new_var = input("Select reference:","Reference") as mob in world - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("file") new_var = input("Pick file:","File") as file - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("icon") new_var = input("Pick icon:","Icon") as icon - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var if("marked datum") new_var = holder.marked_datum - L[L.Find(variable)] = new_var + if(assoc) + L[assoc_key] = new_var + else + L[L.Find(variable)] = new_var world.log << "### ListVarEdit by [src]: [O.type] [objectvar]: [original_var]=[new_var]" log_admin("[key_name(src)] modified [original_name]'s [objectvar]: [original_var]=[new_var]") @@ -539,4 +589,4 @@ var/list/VVckey_edit = list("key", "ckey") world.log << "### VarEdit by [src]: [O.type] [variable]=[html_encode("[O.vars[variable]]")]" log_admin("[key_name(src)] modified [original_name]'s [variable] to [O.vars[variable]]") - message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.vars[variable]]") \ No newline at end of file + message_admins("[key_name_admin(src)] modified [original_name]'s [variable] to [O.vars[variable]]") diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index 2aecf9f789b..dd22a1e9f5c 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -19,6 +19,11 @@ desc = "Strange-looking yellow hat-wear that most certainly belongs to a powerful magic user." icon_state = "yellowwizard" +/obj/item/clothing/head/wizard/black + name = "black wizard hat" + desc = "Strange-looking black hat-wear that most certainly belongs to a real skeleton. Spooky." + icon_state = "blackwizard" + /obj/item/clothing/head/wizard/fake name = "wizard hat" desc = "It has WIZZARD written across it in sequins. Comes with a cool beard." @@ -72,6 +77,12 @@ icon_state = "yellowwizard" item_state = "yellowwizrobe" +/obj/item/clothing/suit/wizrobe/black + name = "black wizard robe" + desc = "An unnerving black gem-lined robe that reeks of death and decay." + icon_state = "blackwizard" + item_state = "blackwizrobe" + /obj/item/clothing/suit/wizrobe/marisa name = "witch robe" desc = "Magic is all about the spell power, ZE!" diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm index 4ba2414beb7..ba32bb2c6ff 100644 --- a/code/modules/hydroponics/biogenerator.dm +++ b/code/modules/hydroponics/biogenerator.dm @@ -159,6 +159,7 @@ dat += "Book bag: Make ([200/efficiency])
" dat += "Plant bag: Make ([200/efficiency])
" dat += "Mining satchel: Make ([200/efficiency])
" + dat += "Chemistry bag: Make ([200/efficiency])
" dat += "Botanical gloves: Make ([250/efficiency])
" dat += "Utility belt: Make ([300/efficiency])
" dat += "Security belt: Make ([300/efficiency])
" @@ -270,6 +271,9 @@ if("mnbag") if (check_cost(200/efficiency)) return 0 else new/obj/item/weapon/storage/bag/ore(src.loc) + if("chbag") + if (check_cost(200/efficiency)) return 0 + else new/obj/item/weapon/storage/bag/chemistry(src.loc) if("gloves") if (check_cost(250/efficiency)) return 0 else new/obj/item/clothing/gloves/botanic_leather(src.loc) diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 88e13ce578c..fcef371cf26 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -17,7 +17,7 @@ var/global/list/rockTurfEdgeCache density = 1 blocks_air = 1 temperature = TCMB - var/obj/mineralType = null + var/mineralType = null var/mineralAmt = 3 var/spread = 0 //will the seam spread? var/spreadChance = 0 //the percentual chance of an ore spreading to the neighbouring tiles @@ -449,7 +449,7 @@ var/global/list/rockTurfEdgeCache var/i for (i=0;i 0)) stat(null, "Time left: [max(malf.AI_win_timeleft/malf.apcs, 0)]") + if(istype(ticker.mode, /datum/game_mode/gang)) + var/datum/game_mode/gang/mode = ticker.mode + if(isnum(mode.A_timer)) + stat(null, "[gang_name("A")] Gang Takeover: [max(mode.A_timer, 0)]") + if(isnum(mode.B_timer)) + stat(null, "[gang_name("B")] Gang Takeover: [max(mode.B_timer, 0)]") + /mob/dead/observer/verb/reenter_corpse() set category = "Ghost" set name = "Re-enter Corpse" diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index f55238a821b..b9321879663 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -31,7 +31,7 @@ /mob/living/carbon/human/experience_pressure_difference() playsound(src, 'sound/effects/space_wind.ogg', 50, 1) - if(shoes.flags&NOSLIP) + if(shoes && shoes.flags&NOSLIP) return 0 . = ..() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 4f953dff6e9..7d29d7a3bdc 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -73,12 +73,14 @@ if (getBrainLoss() >= 60 && stat != DEAD) if (prob(3)) - switch(pick(1,2,3)) + switch(pick(1,2,3,4)) if(1) - say(pick("IM A PONY NEEEEEEIIIIIIIIIGH", "without oxigen blob don't evoluate?", "CAPTAINS A COMDOM", "[pick("", "that faggot traitor")] [pick("joerge", "george", "gorge", "gdoruge")] [pick("mellens", "melons", "mwrlins")] is grifing me HAL;P!!!", "can u give me [pick("telikesis","halk","eppilapse")]?", "THe saiyans screwed", "Bi is THE BEST OF BOTH WORLDS>", "I WANNA PET TEH monkeyS", "stop grifing me!!!!", "SOTP IT#")) + say(pick("IM A PONY NEEEEEEIIIIIIIIIGH", "without oxigen blob don't evoluate?", "CAPTAINS A COMDOM", "[pick("", "that faggot traitor")] [pick("joerge", "george", "gorge", "gdoruge")] [pick("mellens", "melons", "mwrlins")] is grifing me HAL;P!!!", "can u give me [pick("telikesis","halk","eppilapse","kamelien","eksrey","glowey skin")]?", "THe saiyans screwed", "Bi is THE BEST OF BOTH WORLDS>", "I WANNA PET TEH monkeyS", "stop grifing me!!!!", "SOTP IT#", "shiggey diggey!!", "A PIRATE APPEAR")) if(2) - say(pick("FUS RO DAH","fucking 4rries!", "stat me", ">my face", "roll it easy!", "waaaaaagh!!!", "red wonz go fasta", "FOR TEH EMPRAH", "lol2cat", "dem dwarfs man, dem dwarfs", "SPESS MAHREENS", "hwee did eet fhor khayosss", "lifelike texture ;_;", "luv can bloooom", "PACKETS!!!")) + say(pick("FUS RO DAH","fucking 4rries!", "stat me", ">my face", "roll it easy!", "waaaaaagh!!!", "red wonz go fasta", "FOR TEH EMPRAH", "lol2cat", "dem dwarfs man, dem dwarfs", "SPESS MAHREENS", "hwee did eet fhor khayosss", "lifelike texture ;_;", "luv can bloooom", "PACKETS!!!", "port ba[pick("y", "i", "e")] med!!!!", "REVIRT GON CHEM!!!!!!!!", "youed call her a toeugh bithc", "closd for merbegging", "pray can u [pick("spawn", "MAke me", "creat")] [pick("zenomorfs", "ayleins", "treaitors", "sheadow linkgs", "ubdoocters")]???")) if(3) + say(pick("GEY AWAY FROM ME U GREIFING PRICK!!!!", "ur a fuckeing autist!", ";HELP SHITECIRTY MURDERIN MEE!!!", "hwat dose tha [pick("g", "squid", "r")] mean?????", "CAL; TEH SHUTTLE!!!!!", "wearnig siNGUARLTY IS .... FIne xDDDDDDDDD", "AI laW 22 Open door", "this SI mY stATIon......", "who the HELL do u thenk u r?!!!!", "geT THE FUCK OUTTTT", "H U G B O X", ";;CRAGING THIS STTAYTION WITH NIO SURVIVROS", "[pick("bager", "syebl")] is down11!!!!!!!!!!!!!!!!!")) + if(4) emote("drool") diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 902e1420504..855ecf423c4 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -817,6 +817,18 @@ Sorry Giacom. Please don't be mad :( /mob/living/proc/get_standard_pixel_y_offset(lying = 0) return initial(pixel_y) +/mob/living/Stat() + ..() + if(statpanel("Status")) + if(ticker) + if(ticker.mode) + if(istype(ticker.mode, /datum/game_mode/gang)) + var/datum/game_mode/gang/mode = ticker.mode + if(isnum(mode.A_timer)) + stat(null, "[gang_name("A")] Gang Takeover: [max(mode.A_timer, 0)]") + if(isnum(mode.B_timer)) + stat(null, "[gang_name("B")] Gang Takeover: [max(mode.B_timer, 0)]") + /mob/living/cancel_camera() ..() cameraFollow = null @@ -840,5 +852,5 @@ Sorry Giacom. Please don't be mad :( // Now, are they viewable by a camera? (This is last because it's the most intensive check) if(!near_camera(src)) return 0 - + return 1 diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index e15a9a939d1..f1480e7f217 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -556,13 +556,8 @@ if(user != src)//To prevent syndieborgs from emagging themselves if(!opened)//Cover is closed if(locked) - if(prob(90)) - user << "You emag the cover lock." - locked = 0 - else - user << "You fail to emag the cover lock!" - if(prob(25)) - src << "Hack attempt detected." + user << "You emag the cover lock." + locked = 0 else user << "The cover is already unlocked!" return @@ -573,42 +568,37 @@ return else sleep(6) - if(prob(50)) - SetEmagged(1) - SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown - lawupdate = 0 - connected_ai = null - user << "You emag [src]'s interface." - message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.") - log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.") - clear_supplied_laws() - clear_inherent_laws() - laws = new /datum/ai_laws/syndicate_override - var/time = time2text(world.realtime,"hh:mm:ss") - lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])") - set_zeroth_law("Only [user.real_name] and people they designate as being such are Syndicate Agents.") - src << "ALERT: Foreign software detected." - sleep(5) - src << "Initiating diagnostics..." - sleep(20) - src << "SynBorg v1.7 loaded." - sleep(5) - src << "LAW SYNCHRONISATION ERROR" - sleep(5) - src << "Would you like to send a report to NanoTraSoft? Y/N" - sleep(10) - src << "> N" - sleep(20) - src << "ERRORERRORERROR" - src << "Obey these laws:" - laws.show_laws(src) - src << "ALERT: [user.real_name] is your new master. Obey your new laws and their commands." - SetLockdown(0) - update_icons() - else - user << "You fail to [ locked ? "unlock" : "lock"] [src]'s interface!" - if(prob(25)) - src << "ALERT: Hack attempt detected." + SetEmagged(1) + SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown + lawupdate = 0 + connected_ai = null + user << "You emag [src]'s interface." + message_admins("[key_name_admin(user)] emagged cyborg [key_name_admin(src)]. Laws overridden.") + log_game("[key_name(user)] emagged cyborg [key_name(src)]. Laws overridden.") + clear_supplied_laws() + clear_inherent_laws() + laws = new /datum/ai_laws/syndicate_override + var/time = time2text(world.realtime,"hh:mm:ss") + lawchanges.Add("[time] : [user.name]([user.key]) emagged [name]([key])") + set_zeroth_law("Only [user.real_name] and people they designate as being such are Syndicate Agents.") + src << "ALERT: Foreign software detected." + sleep(5) + src << "Initiating diagnostics..." + sleep(20) + src << "SynBorg v1.7 loaded." + sleep(5) + src << "LAW SYNCHRONISATION ERROR" + sleep(5) + src << "Would you like to send a report to NanoTraSoft? Y/N" + sleep(10) + src << "> N" + sleep(20) + src << "ERRORERRORERROR" + src << "Obey these laws:" + laws.show_laws(src) + src << "ALERT: [user.real_name] is your new master. Obey your new laws and their commands." + SetLockdown(0) + update_icons() /mob/living/silicon/robot/verb/unlock_own_cover() set category = "Robot Commands" diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index f04268cf99d..416fe4d1170 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -716,6 +716,7 @@ var/list/slot_equipment_priority = list( \ if(master_controller) stat("MasterController:","[round(master_controller.cost,0.001)]ds (Interval:[master_controller.processing_interval] | Iteration:[master_controller.iteration])") + stat("Subsystem cost per second:","[round(master_controller.SSCostPerSecond,0.001)]ds") for(var/datum/subsystem/SS in master_controller.subsystems) if(SS.can_fire) SS.stat_entry() diff --git a/code/modules/projectiles/guns/projectile/automatic.dm b/code/modules/projectiles/guns/projectile/automatic.dm index fdec6f437b9..8a6ffca294b 100644 --- a/code/modules/projectiles/guns/projectile/automatic.dm +++ b/code/modules/projectiles/guns/projectile/automatic.dm @@ -230,10 +230,11 @@ return /obj/item/weapon/gun/projectile/automatic/tommygun - name = "tommy gun" + name = "thompson SMG" desc = "A genuine 'Chicago Typewriter'." icon_state = "tommygun" item_state = "shotgun" + w_class = 5 slot_flags = 0 origin_tech = "combat=5;materials=1;syndicate=2" mag_type = /obj/item/ammo_box/magazine/tommygunm45 diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index 29f9bd5653e..3dab9a3442a 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -192,7 +192,8 @@ dispensable_reagents = list() var/list/special_reagents = list(list("hydrogen", "oxygen", "silicon", "phosphorus", "sulfur", "carbon", "nitrogen", "water"), list("lithium", "sugar", "sacid", "copper", "mercury", "sodium","iodine","bromine"), - list("ethanol", "chlorine", "potassium", "aluminium", "radium", "fluorine", "iron", "welding_fuel","silver","stable_plasma")) + list("ethanol", "chlorine", "potassium", "aluminium", "radium", "fluorine", "iron", "welding_fuel","silver","stable_plasma"), + list("oil", "ash", "acetone", "saltpetre", "ammonia", "diethylamine")) /obj/machinery/chem_dispenser/constructable/New() ..() diff --git a/code/orphaned procs/priority_announce.dm b/code/orphaned procs/priority_announce.dm index e085fa783ca..3630b9d58df 100644 --- a/code/orphaned procs/priority_announce.dm +++ b/code/orphaned procs/priority_announce.dm @@ -6,7 +6,8 @@ if(type == "Priority") announcement += "

Priority Announcement

" - + if (title && length(title) > 0) + announcement += "

[html_encode(title)]

" else if(type == "Captain") announcement += "

Captain Announces

" news_network.SubmitArticle(text, "Captain's Announcement", "Station Announcements", null) diff --git a/config/game_options.txt b/config/game_options.txt index cc2a9c13d1d..ed44c926e10 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -276,3 +276,7 @@ MIDROUND_ANTAG_LIFE_CHECK 0.7 #NO_SUMMON_MAGIC #NO_SUMMON_EVENTS +//Comment for "normal" explosions, which ignore obstacles +//Uncomment for explosions that react to doors and walls +REACTIONARY_EXPLOSIONS + diff --git a/html/changelog.html b/html/changelog.html index fc869a9a0f4..69c3bf7818a 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,40 @@ -->
+

12 June 2015

+

Ikarrus updated:

+
    +
  • Gang Updates
  • +
  • New objective: To win, Gangs must now buy a Dominator machine (50 influence) and defend it for a varying time frame.
    * The location of the dominator is broadcasted to the entire station the moment it is activated
    * The more territories the gang controls, the less time it will take
    * Gangs no longer win by capturing territories
  • +
  • A choice of gang outfits are now purchasable for 1 influence each
  • +
  • Thompson SMGs aka "tommy guns" are now purchasable for 50 influence
  • +
  • Bulletproof armor vests are now purchasable for 10 influence
  • +
  • Gang messages are now free to send
  • +
  • Prices of pistols and pens reduced to 20 and 30, respectively
  • +
  • Gang spraycans have been made a lot less obvious. They look nearly identical to regular ones, now.
  • +
  • Gangs will no longer be notified how much territory the enemy controls
  • +
+

Incoming5643 updated:

+
    +
  • Growing tired of reports of slain members, the Wizard Federation has cautiously sactioned the dark path of lichdom. Beware of the powerful lich who hides his phylactery well, for he is immortal!
  • +
  • The trick to defeating liches is to destroy either their body or their phylactery item before they can ressurect to it. The more a lich is slain the longer it will take him to make use of his phylactery and the more likely the crew is to catch him during a vunerable moment.
  • +
  • Due to the addition of proper liching, skeletons as a choosable race from magic mirrors has been discontinued. My apologies to the powergamers. A special admin version of the mirror that allows for skeletons has also been added to the code.
  • +
+

Miauw updated:

+
    +
  • AIs have received several minor nerfs in order to increase antagonist counterplay:
  • +
  • AI tracking is no longer instant, it takes an amount of time that increases with distance from the AI eye, up to 4 seconds. The AI detector item will light up when an AI begins tracking.
  • +
  • A random camera failure event has been added, which will break one or two random cameras.
  • +
  • You can no longer keep tracking people that are outside of your camera vision.
  • +
  • Camera wires have been removed. Screwdriver a camera to open the panel, then use wirecutters to disable it or a multitool to change the focus.
  • +
  • You can now hit cameras with items to break them. To repair a camera, simply open the panel and use wirecutters on it.
  • +
  • Camera alerts now only happen after a camera is reactivated.
  • +
+

RemieRichards updated:

+
    +
  • New optional explosion effect ported from /vg/'s DeityLink, Explosions that are affected by Walls and Doors
  • +
+

11 June 2015

Cheridan updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index c90596dca91..e7f6df25d6e 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -2705,3 +2705,49 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. 2015-06-11: Cheridan: - rscdel: Removes the powerdrain for individiual active modules on cyborgs. +2015-06-12: + Ikarrus: + - experiment: Gang Updates + - rscadd: 'New objective: To win, Gangs must now buy a Dominator machine (50 influence) + and defend it for a varying time frame.
    * The location of the dominator is + broadcasted to the entire station the moment it is activated
    * The more territories + the gang controls, the less time it will take
    * Gangs no longer win by capturing + territories' + - rscadd: A choice of gang outfits are now purchasable for 1 influence each + - rscadd: Thompson SMGs aka "tommy guns" are now purchasable for 50 influence + - rscadd: Bulletproof armor vests are now purchasable for 10 influence + - tweak: Gang messages are now free to send + - tweak: Prices of pistols and pens reduced to 20 and 30, respectively + - tweak: Gang spraycans have been made a lot less obvious. They look nearly identical + to regular ones, now. + - rscdel: Gangs will no longer be notified how much territory the enemy controls + Incoming5643: + - rscadd: Growing tired of reports of slain members, the Wizard Federation has cautiously + sactioned the dark path of lichdom. Beware of the powerful lich who hides his + phylactery well, for he is immortal! + - rscadd: The trick to defeating liches is to destroy either their body or their + phylactery item before they can ressurect to it. The more a lich is slain the + longer it will take him to make use of his phylactery and the more likely the + crew is to catch him during a vunerable moment. + - rscremove: Due to the addition of proper liching, skeletons as a choosable race + from magic mirrors has been discontinued. My apologies to the powergamers. A + special admin version of the mirror that allows for skeletons has also been + added to the code. + Miauw: + - tweak: 'AIs have received several minor nerfs in order to increase antagonist + counterplay:' + - tweak: AI tracking is no longer instant, it takes an amount of time that increases + with distance from the AI eye, up to 4 seconds. The AI detector item will light + up when an AI begins tracking. + - tweak: A random camera failure event has been added, which will break one or two + random cameras. + - tweak: You can no longer keep tracking people that are outside of your camera + vision. + - tweak: Camera wires have been removed. Screwdriver a camera to open the panel, + then use wirecutters to disable it or a multitool to change the focus. + - tweak: You can now hit cameras with items to break them. To repair a camera, simply + open the panel and use wirecutters on it. + - tweak: Camera alerts now only happen after a camera is reactivated. + RemieRichards: + - rscadd: New optional explosion effect ported from /vg/'s DeityLink, Explosions + that are affected by Walls and Doors diff --git a/html/changelogs/Miauw-AInerf.yml b/html/changelogs/Miauw-AInerf.yml deleted file mode 100644 index 63ff2ff55ed..00000000000 --- a/html/changelogs/Miauw-AInerf.yml +++ /dev/null @@ -1,12 +0,0 @@ -author: Miauw - -delete-after: True - -changes: - - tweak: "AIs have received several minor nerfs in order to increase antagonist counterplay:" - - tweak: "AI tracking is no longer instant, it takes an amount of time that increases with distance from the AI eye, up to 4 seconds. The AI detector item will light up when an AI begins tracking." - - tweak: "A random camera failure event has been added, which will break one or two random cameras." - - tweak: "You can no longer keep tracking people that are outside of your camera vision." - - tweak: "Camera wires have been removed. Screwdriver a camera to open the panel, then use wirecutters to disable it or a multitool to change the focus." - - tweak: "You can now hit cameras with items to break them. To repair a camera, simply open the panel and use wirecutters on it." - - tweak: "Camera alerts now only happen after a camera is reactivated." \ No newline at end of file diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi index bc98f542874..4ced7caebed 100644 Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi index 522826b5530..934435bd835 100644 Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi index dd1f96dcbfe..6572955ff2b 100644 Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi index 9c5ddae42c1..42e1b95b2c0 100644 Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi index f4d22e41ee2..59ac6436d18 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index b56aa44170d..deca94b24fa 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/crayons.dmi b/icons/obj/crayons.dmi index a3966103053..7d3489285c3 100644 Binary files a/icons/obj/crayons.dmi and b/icons/obj/crayons.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 473e51f6964..5a3e80c66f7 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/machines/dominator.dmi b/icons/obj/machines/dominator.dmi new file mode 100644 index 00000000000..7671dedff86 Binary files /dev/null and b/icons/obj/machines/dominator.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 7e8d66f026d..e448e1b78bd 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -227,6 +227,7 @@ #include "code\datums\spells\genetic.dm" #include "code\datums\spells\inflict_handler.dm" #include "code\datums\spells\knock.dm" +#include "code\datums\spells\lichdom.dm" #include "code\datums\spells\lightning.dm" #include "code\datums\spells\mime.dm" #include "code\datums\spells\mind_transfer.dm" @@ -325,7 +326,9 @@ #include "code\game\gamemodes\cult\runes.dm" #include "code\game\gamemodes\cult\talisman.dm" #include "code\game\gamemodes\extended\extended.dm" +#include "code\game\gamemodes\gang\dominator.dm" #include "code\game\gamemodes\gang\gang.dm" +#include "code\game\gamemodes\gang\recaller.dm" #include "code\game\gamemodes\malfunction\Malf_Modules.dm" #include "code\game\gamemodes\malfunction\malfunction.dm" #include "code\game\gamemodes\meteor\meteor.dm" @@ -578,7 +581,6 @@ #include "code\game\objects\items\devices\pipe_painter.dm" #include "code\game\objects\items\devices\pizza_bomb.dm" #include "code\game\objects\items\devices\powersink.dm" -#include "code\game\objects\items\devices\recaller.dm" #include "code\game\objects\items\devices\scanners.dm" #include "code\game\objects\items\devices\sensor_device.dm" #include "code\game\objects\items\devices\taperecorder.dm"