diff --git a/code/game/asteroid.dm b/code/game/asteroid.dm index 88ff95833ad..3753c888912 100644 --- a/code/game/asteroid.dm +++ b/code/game/asteroid.dm @@ -97,7 +97,7 @@ var/global/max_secret_rooms = 6 theme = "xenoden" walltypes = list(/turf/simulated/mineral/random/high_chance=1) floortypes = list(/turf/simulated/floor/plating/airless/asteroid, /turf/simulated/floor/beach/sand) - treasureitems = list(/obj/item/clothing/mask/facehugger=1) + treasureitems = list(/obj/item/clothing/mask/facehugger=1,/obj/item/stack/sheet/animalhide/xeno=2,/obj/item/clothing/suit/xenos=2,/obj/item/clothing/head/xenos=2) fluffitems = list(/obj/effect/decal/remains/human=1,/obj/effect/decal/cleanable/blood/xeno=5) if("hitech") diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm index 616a2deb206..aec9b2580b5 100644 --- a/code/game/dna/genes/vg_powers.dm +++ b/code/game/dna/genes/vg_powers.dm @@ -224,8 +224,7 @@ Obviously, requires DNA2. var/list/validtargets = new /list() for(var/mob/M in living_mob_list) if(M && M.mind) - var/special_role = M.mind.special_role - if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Syndicate" || special_role == "Syndicate Commando" || special_role == "Vox Raider" || special_role == "Alien") + if(isAntag(M)) continue validtargets += M @@ -244,15 +243,14 @@ Obviously, requires DNA2. var/say = strip_html(input("What do you wish to say")) for(var/mob/living/target in targets) + log_say("Project Mind: [key_name(usr)]->[key_name(target)]: [say]") if(REMOTE_TALK in target.mutations) target.show_message("\blue You hear [usr.real_name]'s voice: [say]") else target.show_message("\blue You hear a voice that seems to echo around the room: [say]") usr.show_message("\blue You project your mind into [target.real_name]: [say]") for(var/mob/dead/observer/G in player_list) - G.show_message("Telepathic message from [usr] to [target]: [say]") - - + G.show_message("Telepathic message from [usr] ([ghost_follow_link(usr, ghost=G)]) to [target] ([ghost_follow_link(target, ghost=G)]): [say]") /datum/dna/gene/basic/grant_spell/remoteview name="Remote Viewing" diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index c42c9cec293..3b7ca6d5b0e 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -558,12 +558,16 @@ var/list/sacrificed = list() else usr.whisper("[input]") + log_say("Cult Message: [key_name(usr)]: [input]") for(var/datum/mind/H in ticker.mode.cult) if (H.current) H.current << "[cultName]: [input]" for(var/mob/spirit/spirit in spirits) spirit << "[displayName]: [input]" + + for(var/mob/dead/observer/G in player_list) + G.show_message("[displayName] ([cultName]) ([ghost_follow_link(usr, ghost=G)]): [input]") qdel(src) return 1 diff --git a/code/game/gamemodes/events/holidays/Other.dm b/code/game/gamemodes/events/holidays/Other.dm deleted file mode 100644 index 74b47506aaf..00000000000 --- a/code/game/gamemodes/events/holidays/Other.dm +++ /dev/null @@ -1,10 +0,0 @@ -/proc/GameOver() - if(!hadevent) - hadevent = 1 - message_admins("The apocalypse has begun! (this holiday event can be disabled by toggling events off within 60 seconds)") - spawn(600) - if(!config.allow_random_events) return - Show2Group4Delay(ScreenText(null,"
GAME OVER
"),null,150) - for(var/i=1,i<=4,i++) - spawn_dynamic_event() - sleep(50) \ No newline at end of file diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 0d821a186fa..d0e2228162c 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -238,8 +238,7 @@ var/list/suspects = list() for(var/mob/living/carbon/human/man in player_list) if(man.client && man.mind) // NT relation option - var/special_role = man.mind.special_role - if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Syndicate" || special_role == "Syndicate Commando" || special_role == "Vox Raider" || special_role == "Alien") + if(isAntag(man)) continue //NT intelligence ruled out possiblity that those are too classy to pretend to be a crew. if(man.client.prefs.nanotrasen_relation == "Opposed" && prob(50) || \ man.client.prefs.nanotrasen_relation == "Skeptical" && prob(20)) diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index b11edd5ae8d..f9f13d4f907 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -992,7 +992,8 @@ /obj/machinery/alarm/emag_act(mob/user) if(!emagged) src.emagged = 1 - user.visible_message("Sparks fly out of the [src]!", "You emag the [src], disabling its safeties.") + if(user) + user.visible_message("Sparks fly out of the [src]!", "You emag the [src], disabling its safeties.") playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1) return diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 7bb074e03f4..0b7907eb88f 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -352,8 +352,9 @@ var/list/turret_icons if(!emagged) //Emagging the turret makes it go bonkers and stun everyone. It also makes //the turret shoot much, much faster. - user << "You short out [src]'s threat assessment circuits." - visible_message("[src] hums oddly...") + if(user) + user << "You short out [src]'s threat assessment circuits." + visible_message("[src] hums oddly...") emagged = 1 iconholder = 1 controllock = 1 diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index f7924a83ed7..be2b3a0c075 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -9,6 +9,7 @@ #define ASSIGNMENT_SECURITY "Security" var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT_LEVEL_MODERATE = "Moderate", EVENT_LEVEL_MAJOR = "Major") +var/list/event_last_fired = list() /datum/event_container var/severity = -1 @@ -134,8 +135,7 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation",/datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wallrot", /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30, ASSIGNMENT_GARDENER = 50)), // NON-BAY EVENTS - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Cargo Bonus", /datum/event/cargo_bonus, 100), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Revenant", /datum/event/revenant, 50) + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Cargo Bonus", /datum/event/cargo_bonus, 100) ) /datum/event_container/moderate @@ -158,7 +158,6 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Ion Storm", /datum/event/ion_storm, 0, list(ASSIGNMENT_AI = 50, ASSIGNMENT_CYBORG = 50, ASSIGNMENT_ENGINEER = 15, ASSIGNMENT_SCIENTIST = 5)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Borer Infestation", /datum/event/borer_infestation, 20, list(ASSIGNMENT_SECURITY = 20), 1), - new /datum/event_meta/alien(EVENT_LEVEL_MODERATE, "Alien Infestation", /datum/event/alien_infestation, 0, list(ASSIGNMENT_SECURITY = 15), 1), //new /datum/event_meta/ninja(EVENT_LEVEL_MODERATE, "Space Ninja", /datum/event/space_ninja, 0, list(ASSIGNMENT_SECURITY = 15), 1), // NON-BAY EVENTS new /datum/event_meta(EVENT_LEVEL_MODERATE, "Mass Hallucination", /datum/event/mass_hallucination, 300), @@ -172,6 +171,7 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT new /datum/event_meta(EVENT_LEVEL_MODERATE, "Bluespace Anomaly", /datum/event/anomaly/anomaly_bluespace, 50, list(ASSIGNMENT_ENGINEER = 25)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Flux Anomaly", /datum/event/anomaly/anomaly_flux, 50, list(ASSIGNMENT_ENGINEER = 50)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gravitational Anomaly", /datum/event/anomaly/anomaly_grav, 200), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Revenant", /datum/event/revenant, 150) ) /datum/event_container/major @@ -183,6 +183,7 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT new /datum/event_meta(EVENT_LEVEL_MAJOR, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 30), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, 0, list(ASSIGNMENT_ENGINEER = 30), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 3), 1), + new /datum/event_meta/alien(EVENT_LEVEL_MAJOR, "Alien Infestation", /datum/event/alien_infestation, 0, list(ASSIGNMENT_SECURITY = 30), 1), ) diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm deleted file mode 100644 index 2a491a62b9d..00000000000 --- a/code/modules/events/event_dynamic.dm +++ /dev/null @@ -1,242 +0,0 @@ - -/* -/proc/start_events() - //changed to a while(1) loop since they are more efficient. - //Moved the spawn in here to allow it to be called with advance proc call if it crashes. - //and also to stop spawn copying variables from the game ticker - spawn(3000) - while(1) - /*if(prob(50))//Every 120 seconds and prob 50 2-4 weak spacedusts will hit the station - spawn(1) - dust_swarm("weak")*/ - if(!event) - //CARN: checks to see if random events are enabled. - if(config.allow_random_events) - hadevent = event() - else - Holiday_Random_Event() - else - event = 0 - sleep(2400) - */ - -var/list/event_last_fired = list() - -//Always triggers an event when called, dynamically chooses events based on job population -var/global/list/possibleEvents = list() -/proc/spawn_dynamic_event() - if(!config.allow_random_events) - return - - var/minutes_passed = world.time/600 - - var/list/active_with_role = number_active_with_role() - //var/engineer_count = number_active_with_role("Engineer") - //var/security_count = number_active_with_role("Security") - //var/medical_count = number_active_with_role("Medical") - //var/AI_count = number_active_with_role("AI") - //var/janitor_count = number_active_with_role("Janitor") - - // Maps event names to event chances - // For each chance, 100 represents "normal likelihood", anything below 100 is "reduced likelihood", anything above 100 is "increased likelihood" - // Events have to be manually added to this proc to happen - - //see: - // Code/WorkInProgress/Cael_Aislinn/Economy/Economy_Events.dm - // Code/WorkInProgress/Cael_Aislinn/Economy/Economy_Events_Mundane.dm - - possibleEvents[/datum/event/economic_event] = 300 - possibleEvents[/datum/event/trivial_news] = 400 - possibleEvents[/datum/event/mundane_news] = 300 - - possibleEvents[/datum/event/cargo_bonus] = 100 - possibleEvents[/datum/event/revenant] = 75 - - possibleEvents[/datum/event/pda_spam] = max(min(25, player_list.len) * 4, 200) - possibleEvents[/datum/event/money_lotto] = max(min(5, player_list.len), 50) - if(account_hack_attempted) - possibleEvents[/datum/event/money_hacker] = max(min(25, player_list.len) * 4, 200) - - possibleEvents[/datum/event/mass_hallucination] = 200 - possibleEvents[/datum/event/vent_clog] = 300 - possibleEvents[/datum/event/anomaly/anomaly_grav] = 200 - - possibleEvents[/datum/event/wormholes] = 150 - - possibleEvents[/datum/event/carp_migration] = 20 + 10 * active_with_role["Engineer"] - possibleEvents[/datum/event/dust] = 50 + 50 * active_with_role["Engineer"] - possibleEvents[/datum/event/dust/meaty] = 50 + 50 * active_with_role["Engineer"] - - possibleEvents[/datum/event/rogue_drone] = 5 + 25 * active_with_role["Engineer"] + 25 * active_with_role["Security"] - possibleEvents[/datum/event/infestation] = 100 + 100 * active_with_role["Janitor"] - - possibleEvents[/datum/event/communications_blackout] = 50 + 25 * active_with_role["AI"] + active_with_role["Scientist"] * 25 - possibleEvents[/datum/event/ion_storm] = active_with_role["AI"] * 25 + active_with_role["Cyborg"] * 25 + active_with_role["Engineer"] * 10 + active_with_role["Scientist"] * 5 -// possibleEvents[/datum/event/grid_check] = 25 + 10 * active_with_role["Engineer"] - possibleEvents[/datum/event/electrical_storm] = 15 * active_with_role["Janitor"] + 5 * active_with_role["Engineer"] - possibleEvents[/datum/event/wallrot] = 30 * active_with_role["Engineer"] + 50 * active_with_role["Botanist"] - possibleEvents[/datum/event/borer_infestation] = 50 + 15 * active_with_role["Security"] - - if(!spacevines_spawned) - possibleEvents[/datum/event/spacevine] = 10 + 5 * active_with_role["Engineer"] - if(minutes_passed >= 30) // Give engineers time to set up engine - possibleEvents[/datum/event/brand_intelligence] = 50 + 25 * active_with_role["Engineer"] - possibleEvents[/datum/event/anomaly/anomaly_pyro] = 100 + 60 * active_with_role["Engineer"] - possibleEvents[/datum/event/anomaly/anomaly_vortex] = 50 + 25 * active_with_role["Engineer"] - possibleEvents[/datum/event/anomaly/anomaly_bluespace] = 50 + 25 * active_with_role["Engineer"] - possibleEvents[/datum/event/anomaly/anomaly_flux] = 50 + 50 * active_with_role["Engineer"] - - possibleEvents[/datum/event/meteor_wave] = 10 * active_with_role["Engineer"] - possibleEvents[/datum/event/blob] = 10 * active_with_role["Engineer"] - - if(active_with_role["Medical"] > 0) - possibleEvents[/datum/event/radiation_storm] = active_with_role["Medical"] * 10 - possibleEvents[/datum/event/viral_infection] = active_with_role["Medical"] * 10 - - possibleEvents[/datum/event/prison_break] = active_with_role["Security"] * 50 - if(active_with_role["Security"] > 0) - if(!sent_spiders_to_station) - possibleEvents[/datum/event/spider_infestation] = max(active_with_role["Security"], 5) + 5 - if(aliens_allowed && !sent_aliens_to_station) - possibleEvents[/datum/event/alien_infestation] = max(active_with_role["Security"], 5) + 2.5 - /*if(!sent_ninja_to_station && toggle_space_ninja) - possibleEvents[/datum/event/space_ninja] = max(active_with_role["Security"], 5)*/ - possibleEvents[/datum/event/tear] = active_with_role["Security"] * 25 - - for(var/event_type in event_last_fired) if(possibleEvents[event_type]) - var/time_passed = world.time - event_last_fired[event_type] - var/full_recharge_after = 60 * 60 * 10 * 3 // 3 hours - var/weight_modifier = max(0, (full_recharge_after - time_passed) / 300) - - possibleEvents[event_type] = max(possibleEvents[event_type] - weight_modifier, 0) - - var/picked_event = pickweight(possibleEvents) - event_last_fired[picked_event] = world.time - - // Debug code below here, very useful for testing so don't delete please. - var/debug_message = "Firing random event. " - for(var/V in active_with_role) - debug_message += "#[V]:[active_with_role[V]] " - debug_message += "||| " - for(var/V in possibleEvents) - debug_message += "[V]:[possibleEvents[V]]" - debug_message += "|||Picked:[picked_event]" - log_debug(debug_message) - - if(!picked_event) - return - - //The event will add itself to the MC's event list - //and start working via the constructor. - new picked_event - - //moved this to proc/check_event() - /*var/chance = possibleEvents[picked_event] - var/base_chance = 0.4 - switch(player_list.len) - if(5 to 10) - base_chance = 0.6 - if(11 to 15) - base_chance = 0.7 - if(16 to 20) - base_chance = 0.8 - if(21 to 25) - base_chance = 0.9 - if(26 to 30) - base_chance = 1.0 - if(30 to 100000) - base_chance = 1.1 - - // Trigger the event based on how likely it currently is. - if(!prob(chance * eventchance * base_chance / 100)) - return 0*/ - - /*switch(picked_event) - if("Meteor") - command_announcement.Announce("Meteors have been detected on collision course with the station.", "Meteor Alert", new_sound = 'sound/AI/meteors.ogg') - spawn(100) - meteor_wave(10) - spawn_meteors() - spawn(700) - meteor_wave(10) - spawn_meteors() - if("Space Ninja") - //Handled in space_ninja.dm. Doesn't announce arrival, all sneaky-like. - space_ninja_arrival() - if("Radiation") - high_radiation_event() - if("Virus") - viral_outbreak() - if("Alien") - alien_infestation() - if("Prison Break") - prison_break() - if("Carp") - carp_migration() - if("Lights") - lightsout(1,2) - if("Appendicitis") - appendicitis() - if("Ion Storm") - IonStorm() - if("Spacevine") - spacevine_infestation() - if("Communications") - communications_blackout() - if("Grid Check") - grid_check() - if("Meteor") - meteor_shower()*/ - - return 1 - -// Returns how many characters are currently active(not logged out, not AFK for more than 10 minutes) -// with a specific role. -// Note that this isn't sorted by department, because e.g. having a roboticist shouldn't make meteors spawn. -/proc/number_active_with_role() - var/list/active_with_role = list() - active_with_role["Engineer"] = 0 - active_with_role["Medical"] = 0 - active_with_role["Security"] = 0 - active_with_role["Scientist"] = 0 - active_with_role["AI"] = 0 - active_with_role["Cyborg"] = 0 - active_with_role["Janitor"] = 0 - active_with_role["Botanist"] = 0 - active_with_role["Any"] = player_list.len - - for(var/mob/M in player_list) - if(!M.mind || !M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive - continue - - if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "engineering robot module") - active_with_role["Engineer"]++ - if(M.mind.assigned_role in list("Chief Engineer", "Station Engineer")) - active_with_role["Engineer"]++ - - if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "medical robot module") - active_with_role["Medical"]++ - if(M.mind.assigned_role in list("Chief Medical Officer", "Medical Doctor")) - active_with_role["Medical"]++ - - if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "security robot module") - active_with_role["Security"]++ - if(M.mind.assigned_role in security_positions) - active_with_role["Security"]++ - - if(M.mind.assigned_role in list("Research Director", "Scientist")) - active_with_role["Scientist"]++ - - if(M.mind.assigned_role == "AI") - active_with_role["AI"]++ - - if(M.mind.assigned_role == "Cyborg") - active_with_role["Cyborg"]++ - - if(M.mind.assigned_role == "Janitor") - active_with_role["Janitor"]++ - - if(M.mind.assigned_role == "Botanist") - active_with_role["Botanist"]++ - - return active_with_role diff --git a/code/modules/events/event_manager.dm b/code/modules/events/event_manager.dm index 7982fc1debf..b5fec993420 100644 --- a/code/modules/events/event_manager.dm +++ b/code/modules/events/event_manager.dm @@ -361,3 +361,54 @@ if(P.client) players++ return players + +// Returns how many characters are currently active(not logged out, not AFK for more than 10 minutes) +// with a specific role. +// Note that this isn't sorted by department, because e.g. having a roboticist shouldn't make meteors spawn. +/proc/number_active_with_role() + var/list/active_with_role = list() + active_with_role["Engineer"] = 0 + active_with_role["Medical"] = 0 + active_with_role["Security"] = 0 + active_with_role["Scientist"] = 0 + active_with_role["AI"] = 0 + active_with_role["Cyborg"] = 0 + active_with_role["Janitor"] = 0 + active_with_role["Botanist"] = 0 + active_with_role["Any"] = player_list.len + + for(var/mob/M in player_list) + if(!M.mind || !M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive + continue + + if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "engineering robot module") + active_with_role["Engineer"]++ + if(M.mind.assigned_role in list("Chief Engineer", "Station Engineer")) + active_with_role["Engineer"]++ + + if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "medical robot module") + active_with_role["Medical"]++ + if(M.mind.assigned_role in list("Chief Medical Officer", "Medical Doctor")) + active_with_role["Medical"]++ + + if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "security robot module") + active_with_role["Security"]++ + if(M.mind.assigned_role in security_positions) + active_with_role["Security"]++ + + if(M.mind.assigned_role in list("Research Director", "Scientist")) + active_with_role["Scientist"]++ + + if(M.mind.assigned_role == "AI") + active_with_role["AI"]++ + + if(M.mind.assigned_role == "Cyborg") + active_with_role["Cyborg"]++ + + if(M.mind.assigned_role == "Janitor") + active_with_role["Janitor"]++ + + if(M.mind.assigned_role == "Botanist") + active_with_role["Botanist"]++ + + return active_with_role diff --git a/code/modules/events/tgevents/false_alarm.dm b/code/modules/events/tgevents/false_alarm.dm index 5d29829eaa8..b91ceeebfbf 100644 --- a/code/modules/events/tgevents/false_alarm.dm +++ b/code/modules/events/tgevents/false_alarm.dm @@ -3,8 +3,10 @@ endWhen = 1 /datum/event/falsealarm/announce() - var/datum/event/E = pick(possibleEvents) - var/datum/event/Event = new E - message_admins("False Alarm: [Event]") - Event.announce() //just announce it like it's happening - Event.kill() //do not process this event - no starts, no ticks, no ends + var/weight = pick(EVENT_LEVEL_MUNDANE,EVENT_LEVEL_MUNDANE,EVENT_LEVEL_MUNDANE,EVENT_LEVEL_MODERATE,EVENT_LEVEL_MODERATE,EVENT_LEVEL_MAJOR) + var/datum/event_container/container = event_manager.event_containers[weight] + var/datum/event/E = container.acquire_event() + var/datum/event/Event = new E + message_admins("False Alarm: [Event]") + Event.announce() //just announce it like it's happening + Event.kill() //do not process this event - no starts, no ticks, no ends diff --git a/code/modules/karma/karma.dm b/code/modules/karma/karma.dm index ed00a84e97c..6c3a5d35046 100644 --- a/code/modules/karma/karma.dm +++ b/code/modules/karma/karma.dm @@ -63,8 +63,7 @@ var/list/karma_spenders = list() var/list/karma_list = list("Cancel") for(var/mob/M in player_list) if(M.client && M.mind) - var/special_role = M.mind.special_role - if (special_role == "Wizard" || special_role == "Ninja" || special_role == "Syndicate" || special_role == "Syndicate Commando" || special_role == "Vox Raider" || special_role == "Alien") // Don't include special roles, because players use it to meta + if(isAntag(M)) // Don't include special roles, because players use it to meta continue karma_list += M diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm index 4b5fc980d2c..e1cae9e3c66 100644 --- a/code/modules/mob/language.dm +++ b/code/modules/mob/language.dm @@ -97,7 +97,7 @@ return (copytext(message, length(message)) == "!") ? 2 : 1 /datum/language/proc/broadcast(var/mob/living/speaker,var/message,var/speaker_mask) - log_say("[key_name(speaker)] : ([name]) [message]") + log_say("[key_name(speaker)]: ([name]) [message]") if(!speaker_mask) speaker_mask = speaker.name var/msg = "[name], [speaker_mask] [format_message(message, get_spoken_verb(message))]" diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm index 4efc0c56dc6..3a60506ebe1 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm @@ -43,9 +43,11 @@ Doesn't work on other aliens/AI.*/ adjustToxLoss(-10) var/msg = sanitize(input("Message:", "Alien Whisper") as text|null) if(msg) - log_say("AlienWhisper: [key_name(src)]->[M.key] : [msg]") + log_say("Alien Whisper: [key_name(src)]->[key_name(M)]: [msg]") M << "You hear a strange, alien voice in your head...[msg]" - src << {"You said: "[msg]" to [M]"} + src << "You said: [msg] to [M]" + for(var/mob/dead/observer/G in player_list) + G.show_message("Alien message from [src] ([ghost_follow_link(src, ghost=G)]) to [M] ([ghost_follow_link(M, ghost=G)]): [msg]") return /mob/living/carbon/alien/humanoid/verb/transfer_plasma(mob/living/carbon/alien/M as mob in oview()) diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index c2dc78c5377..3ec2633e2e9 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -30,7 +30,7 @@ min_n2 = 0 max_n2 = 0 var/dead = 0 - unsuitable_atoms_damage = 15 + unsuitable_atmos_damage = 15 faction = list("alien") status_flags = CANPUSH minbodytemp = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm index 3a88146dfb0..285948e6073 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm @@ -8,7 +8,7 @@ max_co2 = 0 min_n2 = 0 max_n2 = 0 - unsuitable_atoms_damage = 15 + unsuitable_atmos_damage = 15 faction = list("mining") environment_smash = 2 minbodytemp = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index b642c5c6dda..c519c2c62bc 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -27,7 +27,7 @@ max_co2 = 5 min_n2 = 0 max_n2 = 0 - unsuitable_atoms_damage = 15 + unsuitable_atmos_damage = 15 speak_emote = list("yarrs") var/corpse = /obj/effect/landmark/mobcorpse/pirate var/weapon1 = /obj/item/weapon/melee/energy/sword/pirate diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm index d62a4ba976d..2635c97f9a1 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm @@ -36,4 +36,4 @@ maxbodytemp = 370 heat_damage_per_tick = 15 //amount of damage applied if animal's body temperature is higher than maxbodytemp cold_damage_per_tick = 10 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp - unsuitable_atoms_damage = 10 + unsuitable_atmos_damage = 10 diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm index d1140f38c5b..729ef2ad658 100644 --- a/code/modules/mob/living/simple_animal/hostile/russian.dm +++ b/code/modules/mob/living/simple_animal/hostile/russian.dm @@ -29,7 +29,7 @@ max_co2 = 5 min_n2 = 0 max_n2 = 0 - unsuitable_atoms_damage = 15 + unsuitable_atmos_damage = 15 faction = list("russian") status_flags = CANPUSH diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index a83eddf5e84..6eb56766229 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -30,7 +30,7 @@ max_co2 = 5 min_n2 = 0 max_n2 = 0 - unsuitable_atoms_damage = 15 + unsuitable_atmos_damage = 15 faction = list("syndicate") status_flags = CANPUSH diff --git a/code/modules/mob/living/simple_animal/revenant/revenant.dm b/code/modules/mob/living/simple_animal/revenant/revenant.dm index bad520aa326..1d83cbcc9d8 100644 --- a/code/modules/mob/living/simple_animal/revenant/revenant.dm +++ b/code/modules/mob/living/simple_animal/revenant/revenant.dm @@ -12,47 +12,52 @@ invisibility = INVISIBILITY_OBSERVER health = 25 maxHealth = 25 - see_in_dark = 255 see_invisible = SEE_INVISIBLE_OBSERVER universal_understand = 1 response_help = "passes through" response_disarm = "swings at" response_harm = "punches" + unsuitable_atmos_damage = 0 minbodytemp = 0 maxbodytemp = INFINITY - harm_intent_damage = 5 - speak_emote = list("hisses", "spits", "growls") + harm_intent_damage = 0 friendly = "touches" status_flags = 0 wander = 0 density = 0 + flying = 1 + anchored = 1 - var/essence = 25 //The resource of revenants. Max health is equal to twice this amount + var/essence = 25 //The resource of revenants. Max health is equal to three times this amount var/essence_regen_cap = 25 //The regeneration cap of essence (go figure); regenerates every Life() tick up to this amount. - var/essence_regen = 1 //If the revenant regenerates essence or not; 1 for yes, 0 for no + var/essence_regenerating = 1 //If the revenant regenerates essence or not; 1 for yes, 0 for no + var/essence_regen_amount = 2 //How much essence regenerates var/essence_min = 1 //The minimum amount of essence a revenant can have; by default, it never drops below one - var/strikes = 0 //How many times a revenant can die before dying for good + var/essence_accumulated = 0 //How much essence the revenant has stolen var/revealed = 0 //If the revenant can take damage from normal sources. var/inhibited = 0 //If the revenant's abilities are blocked by a chaplain's power. + var/essence_drained = 0 //How much essence the revenant has drained. + var/draining = 0 //If the revenant is draining someone. + var/list/drained_mobs = list() //Cannot harvest the same mob twice /mob/living/simple_animal/revenant/Life() ..() if(essence < essence_min) essence = essence_min - if(strikes > 0) - strikes-- - src << "Your essence has dropped below critical levels. You barely manage to save yourself - [strikes ? "you can't keep this up!" : "next time, it's death."]" - else if(strikes <= 0) - Die() - maxHealth = essence * 2 + if(essence_regenerating && !inhibited && essence < essence_regen_cap) //While inhibited, essence will not regenerate + essence += essence_regen_amount + if(essence > essence_regen_cap) + essence = essence_regen_cap + maxHealth = essence * 3 if(!revealed) health = maxHealth //Heals to full when not revealed - if(essence_regen && !inhibited && essence < essence_regen_cap) //While inhibited, essence will not regenerate - essence++ /mob/living/simple_animal/revenant/ex_act(severity) return 1 //Immune to the effects of explosions. +/mob/living/simple_animal/revenant/blob_act() + return 1 //blah blah blobs aren't in tune with the spirit world, or something. + /mob/living/simple_animal/revenant/ClickOn(var/atom/A, var/params) //Copypaste from ghost code - revenants can't interact with the world directly. if(client.buildmode) build_click(src, client.buildmode, params, A) @@ -75,6 +80,70 @@ if(world.time <= next_move) return A.attack_ghost(src) + if(ishuman(A) && in_range(src, A)) + Harvest(A) + +/mob/living/simple_animal/revenant/proc/Harvest(mob/living/carbon/human/target) + if(!castcheck(0)) + return + if(draining) + src << "You are already siphoning the essence of a soul!" + return + if(target in drained_mobs) + src << "[target]'s soul is dead and empty." + return + if(!target.stat) + src << "This being's soul is too strong to harvest." + if(prob(10)) + target << "You feel as if you are being watched." + return + draining = 1 + essence_drained = 2 + src << "You search for the soul of [target]." + if(do_after(src, 10, 3, 0, target)) //did they get deleted in that second? + if(target.ckey) + src << "Their soul burns with intelligence." + essence_drained += 2 + if(target.stat != DEAD) + src << "Their soul blazes with life!" + essence_drained += 2 + else + src << "Their soul is weak and faltering." + if(do_after(src, 20, 6, 0, target)) //did they get deleted NOW? + switch(essence_drained) + if(1 to 2) + src << "[target] will not yield much essence. Still, every bit counts." + if(3 to 4) + src << "[target] will yield an average amount of essence." + if(5 to INFINITY) + src << "Such a feast! [target] will yield much essence to you." + if(do_after(src, 30, 9, 0, target)) //how about now + if(!target.stat) + src << "They are now powerful enough to fight off your draining." + target << "You feel something tugging across your body before subsiding." + draining = 0 + return //hey, wait a minute... + src << "You begin siphoning essence from [target]'s soul." + if(target.stat != DEAD) + target << "You feel a horribly unpleasant draining sensation as your grip on life weakens..." + icon_state = "revenant_draining" + reveal(65) + stun(65) + target.visible_message("[target] suddenly rises slightly into the air, their skin turning an ashy gray.") + target.Beam(src,icon_state="drain_life",icon='icons/effects/effects.dmi',time=60) + if(target) //As one cannot prove the existance of ghosts, ghosts cannot prove the existance of the target they were draining. + change_essence_amount(essence_drained * 5, 0, target) + src << "[target]'s soul has been considerably weakened and will yield no more essence for the time being." + target.visible_message("[target] gently slumps back onto the ground.") + drained_mobs.Add(target) + target.death(0) + icon_state = "revenant_idle" + else + src << "You are not close enough to siphon [target]'s soul. The link has been broken." + draining = 0 + return + draining = 0 + return /mob/living/simple_animal/revenant/say(message) return 0 //Revenants cannot speak out loud. @@ -83,6 +152,7 @@ ..() if(statpanel("Status")) stat(null, "Current essence: [essence]E") + stat(null, "Stolen essence: [essence_accumulated]E") /mob/living/simple_animal/revenant/New() ..() @@ -99,11 +169,11 @@ src << "You do not remember anything of your past lives, nor will you remember anything about this one after your death." src << "Be sure to read the wiki page at http://nanotrasen.se/wiki/index.php/Revenant to learn more." var/datum/objective/revenant/objective = new - objective.owner = src + objective.owner = src.mind src.mind.objectives += objective src << "Objective #1: [objective.explanation_text]" var/datum/objective/revenantFluff/objective2 = new - objective2.owner = src + objective2.owner = src.mind src.mind.objectives += objective2 src << "Objective #2: [objective2.explanation_text]" ticker.mode.traitors |= src.mind //Necessary for announcing @@ -119,13 +189,12 @@ src.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revenant_harvest src.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/revenant_transmit src.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/revenant_light - src.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/revenantDefile + src.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/revenant_defile + src.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/revenant_malf return 1 return 0 /mob/living/simple_animal/revenant/Die() - if(strikes) - return 0 //Impossible to die with strikes still active ..() src << "NO! No... it's too late, you can feel yourself fading..." notransform = 1 @@ -145,74 +214,78 @@ /mob/living/simple_animal/revenant/attackby(obj/item/W, mob/living/user, params) - ..() if(istype(W, /obj/item/weapon/nullrod)) visible_message("[src] violently flinches!", \ - "The null rod invokes agony in you! You feel your essence draining away!") + "As the null rod passes through you, you feel your essence draining away!") essence -= 25 //hella effective inhibited = 1 spawn(30) inhibited = 0 + + ..() - - -/mob/living/simple_animal/revenant/proc/castcheck(var/essence_cost) - var/mob/living/simple_animal/revenant/user = usr - if(!istype(user) || !user) +/mob/living/simple_animal/revenant/proc/castcheck(essence_cost) + if(!src) return - var/turf/T = get_turf(usr) + var/turf/T = get_turf(src) if(istype(T, /turf/simulated/wall)) - user << "You cannot use abilities from inside of a wall." + src << "You cannot use abilities from inside of a wall." return 0 - if(!user.change_essence_amount(essence_cost, 1)) - user << "You lack the essence to use that ability." + if(src.inhibited) + src << "Your powers have been suppressed by nulling energy!" return 0 - if(user.inhibited) - user << "Your powers have been suppressed by holy energies!" + if(!src.change_essence_amount(essence_cost, 1)) + src << "You lack the essence to use that ability." return 0 return 1 - - -/mob/living/simple_animal/revenant/proc/change_essence_amount(var/essence_amt, var/silent = 0, var/source = null) - var/mob/living/simple_animal/revenant/user = usr - if(!istype(usr) || !usr) +/mob/living/simple_animal/revenant/proc/change_essence_amount(essence_amt, silent = 0, source = null) + if(!src) return - if(user.essence + essence_amt <= 0) + if(essence + essence_amt <= 0) return - user.essence += essence_amt - user.essence = Clamp(user.essence, 0, INFINITY) + essence += essence_amt + essence = max(0, essence) + if(essence_amt > 0) + essence_accumulated += essence_amt + essence_accumulated = max(0, essence_accumulated) if(!silent) if(essence_amt > 0) - user << "Gained [essence_amt]E from [source]." + src << "Gained [essence_amt]E from [source]." else - user << "Lost [essence_amt]E from [source]." + src << "Lost [essence_amt]E from [source]." return 1 - - -/mob/living/simple_animal/revenant/proc/reveal(var/time, var/stun) - var/mob/living/simple_animal/revenant/R = usr - if(!istype(usr) || !usr) +/mob/living/simple_animal/revenant/proc/reveal(time) + if(!src) return - R.revealed = 1 - R.invisibility = 0 - if(stun) - R.notransform = 1 - R << "You have been revealed [stun ? "and cannot move" : ""]." + if(time <= 0) + return + revealed = 1 + invisibility = 0 + src << "You have been revealed." spawn(time) - R.revealed = 0 - R.invisibility = INVISIBILITY_OBSERVER - if(stun) - R.notransform = 0 - R << "You are once more concealed [stun ? "and can move again" : ""]." + revealed = 0 + invisibility = INVISIBILITY_OBSERVER + src << "You are once more concealed." +/mob/living/simple_animal/revenant/proc/stun(time) + if(!src) + return + if(time <= 0) + return + notransform = 1 + src << "You cannot move!" + spawn(time) + notransform = 0 + src << "You can move again!" + /datum/objective/revenant var/targetAmount = 100 /datum/objective/revenant/New() targetAmount = rand(100,200) - explanation_text = "Absorb [targetAmount] points of essence." + explanation_text = "Absorb [targetAmount] points of essence from humans." ..() /datum/objective/revenant/check_completion() @@ -221,8 +294,8 @@ var/mob/living/simple_animal/revenant/R = owner.current if(!R || R.stat == DEAD) return 0 - var/essenceAccumulated = R.essence - if(essenceAccumulated < targetAmount) + var/essence_stolen = R.essence_accumulated + if(essence_stolen < targetAmount) return 0 return 1 @@ -254,7 +327,7 @@ /obj/item/weapon/ectoplasm/revenant/New() ..() reforming = 1 - spawn(1800) //3 minutes + spawn(600) //1 minutes if(src && reforming) return reform() if(src && !reforming) @@ -290,7 +363,7 @@ /obj/item/weapon/ectoplasm/revenant/proc/reform() if(!reforming || !src) return - message_admins("Revenant ectoplasm was left undestroyed for 3 minutes and has reformed into a new revenant.") + message_admins("Revenant ectoplasm was left undestroyed for 1 minute and has reformed into a new revenant.") loc = get_turf(src) //In case it's in a backpack or someone's hand visible_message("[src] suddenly rises into the air before fading away.") var/mob/living/simple_animal/revenant/R = new(get_turf(src)) diff --git a/code/modules/mob/living/simple_animal/revenant/revenant_abilities.dm b/code/modules/mob/living/simple_animal/revenant/revenant_abilities.dm index 01f527f2e07..016b8171113 100644 --- a/code/modules/mob/living/simple_animal/revenant/revenant_abilities.dm +++ b/code/modules/mob/living/simple_animal/revenant/revenant_abilities.dm @@ -1,128 +1,66 @@ //Harvest Essence: The bread and butter of the revenant. The basic way of harvesting additional essence. /obj/effect/proc_holder/spell/targeted/revenant_harvest - name = "Harvest (0E)" + name = "Harvest" desc = "Siphons the lingering spectral essence from a human, empowering yourself." panel = "Revenant Abilities" - charge_max = 100 //Short cooldown + charge_max = 0 //Short cooldown clothes_req = 0 - range = 5 - var/essence_drained = 0 - var/draining - var/list/drained_mobs = list() //Cannot harvest the same mob twice + range = 1 /obj/effect/proc_holder/spell/targeted/revenant_harvest/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr) - if(!user.castcheck(0)) - charge_counter = charge_max - return for(var/mob/living/carbon/human/target in targets) spawn(0) - if(draining) - user << "You are already siphoning the essence of a soul!" - return - if(target in drained_mobs) - user << "[target]'s soul is dead and empty." - return - if(target.stat != DEAD) - user << "This being's soul is too strong to harvest." - if(prob(10)) - target << "You feel as if you are being watched." - return - draining = 1 - essence_drained = 1 - user << "You search for the still-living soul of [target]." - sleep(10) - if(target.ckey) - user << "Their soul burns with intelligence." - essence_drained += 3 - sleep(20) - switch(essence_drained) - if(1 to 2) - user << "[target] will not yield much essence. Still, every bit counts." - if(3 to 4) - user << "[target] will yield an average amount of essence." - if(5 to INFINITY) - user << "Such a feast! [target] will yield much essence to you." - sleep(30) - if(!in_range(user, target)) - user << "You are not close enough to siphon [target]'s soul. The link has been broken." - draining = 0 - return - if(!target.stat) - user << "They are now powerful enough to fight off your draining." - target << "You feel something tugging across your body before subsiding." - user << "You begin siphoning essence from [target]'s soul. You can not move while this is happening." - if(target.stat != DEAD) - target << "You feel a horribly unpleasant draining sensation as your grip on life weakens..." - user.icon_state = "revenant_draining" - user.notransform = 1 - user.revealed = 1 - user.invisibility = 0 - target.visible_message("[target] suddenly rises slightly into the air, their skin turning an ashy gray.") - target.Beam(user,icon_state="drain_life",icon='icons/effects/effects.dmi',time=80) - target.death(0) - target.visible_message("[target] gently slumps back onto the ground.") - user.icon_state = "revenant_idle" - user.change_essence_amount(essence_drained * 5, 0, target) - user << "[target]'s soul has been considerably weakened and will yield no more essence for the time being." - user.revealed = 0 - user.notransform = 0 - user.invisibility = INVISIBILITY_OBSERVER - drained_mobs.Add(target) - draining = 0 - + user.Harvest(target) //Transmit: the revemant's only direct way to communicate. Sends a single message silently to a single mob for 5E. /obj/effect/proc_holder/spell/targeted/revenant_transmit - name = "Transmit (5E)" + name = "Transmit" desc = "Telepathically transmits a message to the target." - panel = "Revenant Abilities (Locked)" - charge_max = 50 + panel = "Revenant Abilities" + charge_max = 0 clothes_req = 0 - range = -1 - include_user = 1 - var/locked = 1 + range = 7 + include_user = 0 /obj/effect/proc_holder/spell/targeted/revenant_transmit/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr) - if(!user.castcheck(-5)) - charge_counter = charge_max - return - if(locked) - usr << "You have unlocked Transmit!" - locked = 0 - charge_counter = charge_max - panel = "Revenant Abilities" - range = 7 - include_user = 0 - return for(var/mob/living/M in targets) spawn(0) var/msg = stripped_input(usr, "What do you wish to tell [M]?", null, "") if(!msg) charge_counter = charge_max return - usr << "You transmit to [M]: [msg]" - M << "A strange voice resonates in your head... [msg]" + log_say("Revenant Transmit: [key_name(usr)]->[key_name(M)]: [msg]") + usr << "You transmit to [M]: [msg]" + M << "A strange voice resonates in your head... [msg]" + for(var/mob/dead/observer/G in player_list) + G.show_message("Revenant message from [usr] ([ghost_follow_link(usr, ghost=G)]) to [M] ([ghost_follow_link(M, ghost=G)]): [msg]") //Overload Light: Breaks a light that's online and sends out lightning bolts to all nearby people. /obj/effect/proc_holder/spell/aoe_turf/revenant_light - name = "Overload Light (25E)" - desc = "Directs a large amount of essence into an electrical light, causing an impressive light show." + name = "Overload Light (30E)" + desc = "Directs a large amount of essence into nearby electrical lights, causing lights to shock those nearby." panel = "Revenant Abilities (Locked)" - charge_max = 300 + charge_max = 200 clothes_req = 0 range = 1 + var/reveal = 80 + var/stun = 20 var/locked = 1 /obj/effect/proc_holder/spell/aoe_turf/revenant_light/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr) - if(!user.castcheck(-25)) - charge_counter = charge_max - return if(locked) - user << "You have unlocked Overload Light!" + if(!user.castcheck(-30)) + charge_counter = charge_max + return + user << "You have unlocked Overload Lights!" + name = "Overload Lights (20E)" panel = "Revenant Abilities" locked = 0 - range = 5 + range = 6 + charge_counter = charge_max + return + if(!user.castcheck(-20)) charge_counter = charge_max return for(var/turf/T in targets) @@ -132,57 +70,106 @@ if(!L.on) return L.visible_message("\The [L] suddenly flares brightly and begins to spark!") - sleep(20) + sleep(10) + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(4, 1, L) + s.start() + sleep(10) for(var/mob/living/M in orange(4, L)) if(M == user) return M.Beam(L,icon_state="lightning",icon='icons/effects/effects.dmi',time=5) M.electrocute_act(25, "[L.name]") + var/datum/effect/effect/system/spark_spread/z = new /datum/effect/effect/system/spark_spread + z.set_up(4, 1, M) + z.start() playsound(M, 'sound/machines/defib_zap.ogg', 50, 1, -1) - user.reveal(50, 1) - + user.reveal(reveal) + user.stun(stun) //Defile: Corrupts nearby stuff, unblesses floor tiles. -/obj/effect/proc_holder/spell/aoe_turf/revenantDefile - name = "Defile (30E)" - desc = "Twists and corrupts certain nearby objects. Also dispels holy auras on floors, but not salt lines." +/obj/effect/proc_holder/spell/aoe_turf/revenant_defile + name = "Defile (35E)" + desc = "Twists and corrupts the nearby area. Also dispels holy auras on floors, but not salt lines." panel = "Revenant Abilities (Locked)" - charge_max = 300 + charge_max = 200 clothes_req = 0 range = 1 + var/reveal = 100 + var/stun = 20 var/locked = 1 -/obj/effect/proc_holder/spell/aoe_turf/revenantDefile/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr) - if(!user.castcheck(-30)) - charge_counter = charge_max - return +/obj/effect/proc_holder/spell/aoe_turf/revenant_defile/cast(list/targets, var/mob/living/simple_animal/revenant/user = usr) if(locked) + if(!user.castcheck(-35)) + charge_counter = charge_max + return user << "You have unlocked Defile!" + name = "Defile (20E)" panel = "Revenant Abilities" locked = 0 - range = 4 + range = 3 + charge_counter = charge_max + return + if(!user.castcheck(-20)) charge_counter = charge_max return for(var/turf/T in targets) spawn(0) if(T.flags & NOJAUNT) T.flags -= NOJAUNT - for(var/obj/machinery/bot/secbot/secbot in T.contents) //Not including ED-209 - secbot.emagged = 2 - secbot.Emag(null) - for(var/obj/machinery/bot/cleanbot/cleanbot in T.contents) - cleanbot.emagged = 2 - cleanbot.Emag(null) + if(!istype(T, /turf/simulated/wall/cult) && istype(T, /turf/simulated/wall) && prob(40)) + T.ChangeTurf(/turf/simulated/wall/cult) + if(!istype(T, /turf/simulated/floor/engine/cult) && istype(T, /turf/simulated/floor) && prob(40)) + T.ChangeTurf(/turf/simulated/floor/engine/cult) for(var/mob/living/carbon/human/human in T.contents) human << "You suddenly feel tired." - human.adjustStaminaLoss(25) - for(var/mob/living/silicon/robot/robot in T.contents) - robot.visible_message("[robot] lets out an alarm!", \ - "01001111 01010110 01000101 01010010 01001100 01001111 01000001 01000100") //Translates to "OVERLOAD" - robot << 'sound/misc/interference.ogg' - playsound(robot, 'sound/machines/warning-buzzer.ogg', 50, 1) + human.adjustStaminaLoss(35) for(var/obj/structure/window/window in T.contents) - window.hit(rand(10,50)) + window.hit(rand(50,125)) for(var/obj/machinery/light/light in T.contents) light.flicker() //spooky - user.reveal(30, 1) + user.reveal(reveal) + user.stun(stun) + +//Malfunction: Makes bad stuff happen to robots and machines. +/obj/effect/proc_holder/spell/aoe_turf/revenant_malf + name = "Malfunction (50E)" + desc = "Corrupts and damages nearby machines and mechanical objects." + panel = "Revenant Abilities (Locked)" + charge_max = 150 + clothes_req = 0 + range = 1 + var/reveal = 60 + var/stun = 30 + var/locked = 1 + +/obj/effect/proc_holder/spell/aoe_turf/revenant_malf/cast(list/targets, mob/living/simple_animal/revenant/user = usr) + if(locked) + if(!user.castcheck(-50)) + charge_counter = charge_max + return + user << "You have unlocked Malfunction!" + name = "Malfunction (15E)" + panel = "Revenant Abilities" + locked = 0 + range = 4 + charge_counter = charge_max + return + if(!user.castcheck(-15)) + charge_counter = charge_max + return + for(var/turf/T in targets) + spawn(0) + for(var/obj/machinery/bot/bot in T.contents) + if(!bot.emagged) + bot.locked = 0 + bot.open = 1 + bot.Emag(null) + for(var/obj/machinery/mach in T.contents) + if(prob(10)) + mach.emag_act(null) + + empulse(user.loc, 3, 5) + user.reveal(reveal) + user.stun(stun) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 7fd2dba5c90..dbd87107f1e 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -51,7 +51,7 @@ var/max_co2 = 5 var/min_n2 = 0 var/max_n2 = 0 - var/unsuitable_atoms_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above + var/unsuitable_atmos_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly @@ -227,7 +227,7 @@ fire_alert = 0 if(!atmos_suitable) - adjustBruteLoss(unsuitable_atoms_damage) + adjustBruteLoss(unsuitable_atmos_damage) return 1 /mob/living/simple_animal/Bumped(AM as mob|obj) diff --git a/code/modules/mob/living/simple_animal/slaughter/slaughter.dm b/code/modules/mob/living/simple_animal/slaughter/slaughter.dm index a03b9b5173b..764947115d3 100644 --- a/code/modules/mob/living/simple_animal/slaughter/slaughter.dm +++ b/code/modules/mob/living/simple_animal/slaughter/slaughter.dm @@ -120,8 +120,12 @@ var/msg = stripped_input(usr, "What do you wish to tell [M]?", null, "") if(!(msg)) return - usr << "You whisper to [M]: [msg]" - M << "Suddenly a strange,demonic,voice resonates in your head... [msg]" + log_say("Slaughter Demon Transmit: [key_name(usr)]->[key_name(M)]: [msg]") + usr << "You whisper to [M]: [msg]" + M << "Suddenly a strange, demonic voice resonates in your head... [msg]" + for(var/mob/dead/observer/G in player_list) + G.show_message("Demonic message from [usr] ([ghost_follow_link(usr, ghost=G)]) to [M] ([ghost_follow_link(M, ghost=G)]): [msg]") + //////////The Loot diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 8f228eb30f4..4b2763c0d86 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -276,4 +276,5 @@ if(!emagged) locked = 0 emagged = 1 - user.visible_message("[user.name] emags the [src.name].","\red You short out the lock.") + if(user) + user.visible_message("[user.name] emags the [src.name].","\red You short out the lock.") diff --git a/icons/obj/power.dmi b/icons/obj/power.dmi index ea42ac5b39d..19e56047c76 100644 Binary files a/icons/obj/power.dmi and b/icons/obj/power.dmi differ diff --git a/paradise.dme b/paradise.dme index a1748771fa1..2126b1b0b21 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1111,7 +1111,6 @@ #include "code\modules\events\electrical_storm.dm" #include "code\modules\events\event.dm" #include "code\modules\events\event_container.dm" -#include "code\modules\events\event_dynamic.dm" #include "code\modules\events\event_manager.dm" #include "code\modules\events\grid_check.dm" #include "code\modules\events\infestation.dm"