diff --git a/code/game/gamemodes/vampire/vampire_helpers.dm b/code/game/gamemodes/vampire/vampire_helpers.dm index a0cac794841..8665bc475d3 100644 --- a/code/game/gamemodes/vampire/vampire_helpers.dm +++ b/code/game/gamemodes/vampire/vampire_helpers.dm @@ -76,7 +76,7 @@ if (!mind.vampire) return 0 - if ((mind.vampire.status & VAMP_FULLPOWER) && !(T.mind.vampire && (T.mind.vampire.status & VAMP_FULLPOWER))) + if ((mind.vampire.status & VAMP_FULLPOWER) && !(T.mind && T.mind.vampire && (T.mind.vampire.status & VAMP_FULLPOWER))) return 1 if (T.mind) @@ -179,13 +179,9 @@ if (next_alert && message) if (!vampire.last_frenzy_message || vampire.last_frenzy_message + next_alert < world.time) - to_chat(usr, message) + to_chat(src, message) vampire.last_frenzy_message = world.time - // Remove one point per every life() tick. - if (vampire.frenzy > 0) - vampire.frenzy-- - /mob/proc/vampire_start_frenzy(var/force_frenzy = 0) var/datum/vampire/vampire = mind.vampire @@ -243,6 +239,10 @@ if (mind.vampire.blood_usable < 10) mind.vampire.frenzy += 2 + else if (mind.vampire.frenzy > 0) + mind.vampire.frenzy = max(0, mind.vampire.frenzy -= Clamp(mind.vampire.blood_usable * 0.1, 1, 10)) + + mind.vampire.frenzy = min(mind.vampire.frenzy, 450) vampire_check_frenzy() diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 85744c8c9d9..ebe85b020f7 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -247,19 +247,19 @@ if(occupant.client) occupant.client.eye = occupant.client.mob occupant.client.perspective = MOB_PERSPECTIVE - occupant.loc = loc + occupant.forceMove(loc) occupant = null - for(var/atom/movable/A in src) // In case an object was dropped inside or something + for(var/atom/movable/A in (contents - component_parts)) // In case an object was dropped inside or something if(A == beaker) continue - A.loc = loc + A.forceMove(loc) update_use_power(1) update_icon() toggle_filter() /obj/machinery/sleeper/proc/remove_beaker() if(beaker) - beaker.loc = loc + beaker.forceMove(loc) beaker = null toggle_filter() diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 4077a7da9c7..046fff12588 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -53,6 +53,12 @@ var/const/HOLOPAD_MODE = RANGE_BASED var/obj/machinery/hologram/holopad/targetpad var/last_message +/obj/machinery/hologram/holopad/check_eye(mob/user) + if (user && user == caller_id) + return 0 + + return -1 + /obj/machinery/hologram/holopad/attack_hand(var/mob/living/carbon/human/user) //Carn: Hologram requests. if(!istype(user)) return @@ -109,8 +115,9 @@ var/const/HOLOPAD_MODE = RANGE_BASED /obj/machinery/hologram/holopad/proc/take_call(mob/living/carbon/user) incoming_connection = 0 + caller_id.set_machine(src) caller_id.reset_view(src) - if(!masters[caller_id])//If there is no hologram, possibly make one. + if(!masters[caller_id]) //If there is no hologram, possibly make one. activate_holocall(caller_id) /obj/machinery/hologram/holopad/proc/end_call(mob/user) @@ -119,19 +126,21 @@ var/const/HOLOPAD_MODE = RANGE_BASED caller_id.reset_view() //Send the caller back to his body clear_holo(null, caller_id) // destroy the hologram caller_id = null + if(user) user.unset_machine() user.reset_view() //Send the caller back to his body clear_holo(null, user) // destroy the hologram user = null + /obj/machinery/hologram/holopad/proc/activate_holocall(mob/living/carbon/caller_id) if(caller_id) - create_holo(0,caller_id)//Create one. - src.visible_message("A holographic image of [caller_id] flicks to life right before your eyes!") + create_holo(0, caller_id)//Create one. + visible_message("A holographic image of [caller_id] flicks to life right before your eyes!") else to_chat(caller_id, "ERROR: Unable to project hologram.") return - + /obj/machinery/hologram/holopad/attack_ai(mob/living/silicon/ai/user) if (!istype(user)) return @@ -223,16 +232,14 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ if(hacked == 0) var/obj/effect/overlay/hologram = new(T)//Spawn a blank effect at the location. if(caller_id) - var/tempicon = 0 - for(var/datum/data/record/t in data_core.locked) - if(t.fields["name"] == caller_id.name) - tempicon = t.fields["image"] + var/tempicon = getFlatIcon(caller_id) + hologram.name = "[caller_id.name] (Hologram)" hologram.loc = get_step(src,1) masters[caller_id] = hologram - add_overlay(getHologramIcon(icon(tempicon))) // Add the callers image as an overlay to keep coloration! + hologram.icon = getHologramIcon(icon(tempicon)) // Add the callers image as an overlay to keep coloration! else - add_overlay(A.holo_icon) // Add the AI's configured holo Icon + hologram.icon = A.holo_icon // Add the AI's configured holo Icon hologram.name = "[A.name] (Hologram)"//If someone decides to right click. A.holo = src masters[A] = hologram @@ -253,14 +260,14 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ A.holo = src return 1 -/obj/machinery/hologram/holopad/proc/clear_holo(mob/living/silicon/ai/user, mob/living/carbon/caller_id) +/obj/machinery/hologram/holopad/proc/clear_holo(mob/living/silicon/ai/user, mob/living/carbon/call_user) if(user) qdel(masters[user])//Get rid of user's hologram user.holo = null masters -= user //Discard AI from the list of those who use holopad - if(caller_id) - qdel(masters[caller_id])//Get rid of user's hologram - masters -= caller_id //Discard the caller from the list of those who use holopad + if(call_user) + qdel(masters[call_user]) //Get rid of user's hologram + masters -= call_user //Discard the caller from the list of those who use holopad if (!masters.len)//If no users left set_light(0) //pad lighting (hologram lighting will be handled automatically since its owner was deleted) icon_state = "holopad0" @@ -289,7 +296,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ sourcepad.audible_message("The holopad connection timed out") sourcepad = 0 if (caller_id && sourcepad) - if(caller_id.loc!=sourcepad.loc) + if(caller_id.loc != sourcepad.loc) sourcepad.visible_message("Severing connection to distant holopad.") visible_message("The connection has been terminated by [caller_id].") end_call() diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 21cae21a1a3..5c4bd313291 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -114,13 +114,15 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images if(istype(target)) ManualFollow(target) -/mob/dead/observer/proc/initialise_postkey() +/mob/dead/observer/proc/initialise_postkey(set_timers = TRUE) //This function should be run after a ghost has been created and had a ckey assigned + if (!set_timers) + return //Death times are initialised if they were unset //get/set death_time functions are in mob_helpers.dm if (!get_death_time(ANIMAL)) - set_death_time(ANIMAL, world.time - RESPAWN_ANIMAL)//allow instant mouse spawning + set_death_time(ANIMAL, world.time - RESPAWN_ANIMAL) //allow instant mouse spawning if (!get_death_time(MINISYNTH)) set_death_time(MINISYNTH, world.time - RESPAWN_MINISYNTH) //allow instant drone spawning if (!get_death_time(CREW)) @@ -174,25 +176,15 @@ Works together with spawning an observer, noted above. C.images += target.hud_list[SPECIALROLE_HUD] return 1 -/mob/proc/ghostize(var/can_reenter_corpse = 1, var/should_set_timer = 1) +/mob/proc/ghostize(var/can_reenter_corpse = TRUE, var/should_set_timer = TRUE) if(ckey) var/mob/dead/observer/ghost = new(src) //Transfer safety to observer spawning proc. ghost.can_reenter_corpse = can_reenter_corpse ghost.timeofdeath = src.stat == DEAD ? src.timeofdeath : world.time - if(should_set_timer) - //This is duplicated for robustness in cases where death might not be called. - //It is also set in the mob/death proc - if (isanimal(src)) - set_death_time(ANIMAL, world.time) - else if (ispAI(src) || isDrone(src)) - set_death_time(MINISYNTH, world.time) - else - set_death_time(CREW, world.time)//Crew is the fallback - ghost.ckey = ckey ghost.client = client - ghost.initialise_postkey() + ghost.initialise_postkey(should_set_timer) if(ghost.client) if(!ghost.client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed. ghost.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing! diff --git a/code/modules/mob/living/bot/medbot.dm b/code/modules/mob/living/bot/medbot.dm index bd30db99b54..300c7d7788e 100644 --- a/code/modules/mob/living/bot/medbot.dm +++ b/code/modules/mob/living/bot/medbot.dm @@ -353,7 +353,7 @@ var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN) if(!t) return - if(!in_range(src, usr) && loc != usr) + if(!in_range(src, user) && loc != user) return created_name = t else diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm index 89b02b03b85..aa3907d9997 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -253,11 +253,11 @@ G = module_state_1 if (!G.wrapped && G.grip_item(W, src, 1)) return 1 - if (istype(module_state_2, /obj/item/weapon/gripper)) + else if (istype(module_state_2, /obj/item/weapon/gripper)) G = module_state_2 if (!G.wrapped && G.grip_item(W, src, 0)) return 1 - if (istype(module_state_2, /obj/item/weapon/gripper)) + else if (istype(module_state_3, /obj/item/weapon/gripper)) G = module_state_3 if (!G.wrapped && G.grip_item(W, src, 0)) return 1 @@ -292,4 +292,4 @@ return 1 if (I.loc != src) return 1//Allows objects inside grippers - return 0//don't allow dropping our modules \ No newline at end of file + return 0//don't allow dropping our modules diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 0766010e911..54dd0ce0e1b 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -482,7 +482,12 @@ announce_ghost_joinleave(client, 0) + // Run this here to null out death timers for the next go. + var/mob/new_player/M = new /mob/new_player() + + M.reset_death_timers() + if(!client) log_game("[usr.key] AM failed due to disconnect.",ckey=key_name(usr)) qdel(M) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 7ad6b85acb3..532837e1db9 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -991,6 +991,26 @@ proc/is_blind(A) P.time_of_death[which] = value return 1 +/** + * Resets death timers for a mob. Should only be called during new player creation. + */ +/mob/proc/reset_death_timers() + var/datum/preferences/P + if (client) + P = client.prefs + else if (ckey) + // To avoid runtimes during adminghost. + if (copytext(ckey, 1, 2) == "@") + P = preferences_datums[copytext(ckey, 2)] + else + P = preferences_datums[ckey] + else + return + + if (!P) + return + + P.time_of_death.Cut() //Below here is stuff related to devouring, but which is generally helpful and thus placed here //See Devour.dm for more info in how these are used @@ -1045,7 +1065,7 @@ proc/is_blind(A) "donor" = WEAKREF(src), "viruses" = null, "species" = name, - "blood_DNA" = md5("\ref[src]"), + "blood_DNA" = md5("\ref[src]"), "blood_colour" = "#a10808", "blood_type" = null, "resistances" = null, diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm index 73a6ff4074e..beb9d75a06c 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -549,6 +549,8 @@ slime_temp_adj = 15 /datum/reagent/capsaicin/condensed/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) +#define EYES_PROTECTED 1 +#define EYES_MECH 2 var/eyes_covered = 0 var/mouth_covered = 0 var/no_pain = 0 @@ -563,13 +565,18 @@ protection = list(H.head, H.glasses, H.wear_mask) if(H.species && (H.species.flags & NO_PAIN)) no_pain = 1 //TODO: living-level can_feel_pain() proc + + // Robo-eyes are immune to pepperspray now. Wee. + var/obj/item/organ/eyes/E = H.get_eyes() + if (istype(E) && (E.status & (ORGAN_ROBOT|ORGAN_ADV_ROBOT))) + eyes_covered |= EYES_MECH else protection = list(M.wear_mask) for(var/obj/item/I in protection) if(I) if(I.body_parts_covered & EYES) - eyes_covered = 1 + eyes_covered |= EYES_PROTECTED eye_protection = I.name if((I.body_parts_covered & FACE) && !(I.item_flags & FLEXIBLEMATERIAL)) mouth_covered = 1 @@ -577,8 +584,10 @@ var/message = null if(eyes_covered) - if(!mouth_covered) + if (!mouth_covered && (eyes_covered & EYES_PROTECTED)) message = "Your [eye_protection] protects your eyes from the pepperspray!" + else if (eyes_covered & EYES_MECH) + message = "Your mechanical eyes are invulnurable pepperspray!" else message = "The pepperspray gets in your eyes!" if(mouth_covered) @@ -597,6 +606,8 @@ M.custom_emote(2, "[pick("coughs!","coughs hysterically!","splutters!")]") M.Stun(5) M.Weaken(5) +#undef EYES_PROTECTED +#undef EYES_MECH /datum/reagent/condensedcapsaicin/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) if(ishuman(M)) diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index a67377e62ac..e577603fd55 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -73,7 +73,7 @@ /obj/item/weapon/reagent_containers/spray/proc/Spray_at(atom/A as mob|obj, mob/user as mob, proximity) if (A.density && proximity) - A.visible_message("[usr] sprays [A] with [src].") + A.visible_message("[user] sprays [A] with [src].") reagents.splash(A, amount_per_transfer_from_this) else spawn(0) @@ -157,12 +157,12 @@ /obj/item/weapon/reagent_containers/spray/pepper/attack_self(var/mob/user) safety = !safety - usr << "You switch the safety [safety ? "on" : "off"]." + user << "You switch the safety [safety ? "on" : "off"]." playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1) -/obj/item/weapon/reagent_containers/spray/pepper/Spray_at(atom/A as mob|obj) +/obj/item/weapon/reagent_containers/spray/pepper/Spray_at(atom/A as mob|obj, mob/user) if(safety) - usr << "The safety is on!" + user << "The safety is on!" return ..() diff --git a/code/modules/spells/aoe_turf/conjure/druidic_spells.dm b/code/modules/spells/aoe_turf/conjure/druidic_spells.dm index cec585c0cb6..dfc1c9f0e79 100644 --- a/code/modules/spells/aoe_turf/conjure/druidic_spells.dm +++ b/code/modules/spells/aoe_turf/conjure/druidic_spells.dm @@ -24,7 +24,7 @@ charge_max = 300 invocation = "Bla'yo daya!" invocation_type = SpI_SHOUT - level_max = list(Sp_TOTAL = 3, Sp_SPEED = 3, Sp_POWER = 3) + level_max = list(Sp_TOTAL = 3, Sp_SPEED = 4, Sp_POWER = 3) range = 1 diff --git a/code/modules/virus2/dishincubator.dm b/code/modules/virus2/dishincubator.dm index d6db4d4c2fc..b2e15414263 100644 --- a/code/modules/virus2/dishincubator.dm +++ b/code/modules/virus2/dishincubator.dm @@ -137,10 +137,10 @@ SSnanoui.update_uis(src) - if (locate(/datum/reagent/toxin) in beaker.reagents.reagent_list && toxins < 100) + if ((locate(/datum/reagent/toxin) in beaker.reagents.reagent_list) && toxins < 100) for(var/datum/reagent/toxin/T in beaker.reagents.reagent_list) toxins += max(T.strength,1) - beaker.reagents.remove_reagent(T.id,1) + beaker.reagents.remove_reagent(T.id, 1) if(toxins > 100) toxins = 100 break diff --git a/html/changelogs/skull132_bonanza.yml b/html/changelogs/skull132_bonanza.yml new file mode 100644 index 00000000000..e40dce79e12 --- /dev/null +++ b/html/changelogs/skull132_bonanza.yml @@ -0,0 +1,14 @@ +author: Skull132 +delete-after: True + +changes: + - bugfix: "Sleepers will no longer jettison their stored components when you exit them." + - bugfix: "Vampires approaching frenzy will now get their appropriate messages again." + - balance: "For vampires: capped the maximum time you can accumulate for frenzy. And having more blood will now reduce frenzy faster: the more humans you succ dry, the faster you become human again!" + - bugfix: "Fixed a runtime in robot/put_in_hands, which bugged out numerous gripper interactions. To include building robots as a science borg." + - bugfix: "Toxins can now be added to the pathogenic dish incubator again." + - balance: "Robotic eyes (not assisted ones!) are now partially immune to pepperspray effects. Because robots." + - bugfix: "Death timers no longer reset if you re-enter your corpse." + - bugfix: "Holocall fixes: icons are generated properly, caller view is moved properly, icons are cleaned up properly, AI interaction is now fine." + - imageadd: "Added a second lobby screen, courtesy of NursieKitty and Zelm." + - tweak: "Wizards can no longer upgrade spacebats into an instant-summon. The ability to spam mobs is bad ju-ju." diff --git a/icons/misc/title.dmi b/icons/misc/title.dmi index ef874221976..7fdcaf43ddb 100644 Binary files a/icons/misc/title.dmi and b/icons/misc/title.dmi differ