diff --git a/code/__HELPERS/atmospherics.dm b/code/__HELPERS/atmospherics.dm index 940418f2ebc..3ac3bfaed56 100644 --- a/code/__HELPERS/atmospherics.dm +++ b/code/__HELPERS/atmospherics.dm @@ -199,3 +199,10 @@ GLOBAL_LIST_EMPTY(gas_handbook) if(boundaries && boundaries[1] > 0) return FALSE return TRUE + +/proc/print_gas_mixture(datum/gas_mixture/gas_mixture) + var/message = "TEMPERATURE: [gas_mixture.temperature]K, QUANTITY: [gas_mixture.total_moles()] mols, VOLUME: [gas_mixture.volume]L; " + for(var/key in gas_mixture.gases) + var/list/gaslist = gas_mixture.gases[key] + message += "[gaslist[GAS_META][META_GAS_ID]]=[gaslist[MOLES]] mols;" + return message diff --git a/code/__HELPERS/logging/atmos.dm b/code/__HELPERS/logging/atmos.dm index 0fcded5c7ab..644c9e65625 100644 --- a/code/__HELPERS/logging/atmos.dm +++ b/code/__HELPERS/logging/atmos.dm @@ -1,8 +1,48 @@ /// Logs the contents of the gasmix to the game log, prefixed by text -/proc/log_atmos(text, datum/gas_mixture/mix) - var/message = text - message += "TEMP=[mix.temperature], MOL=[mix.total_moles()], VOL=[mix.volume] " - for(var/key in mix.gases) - var/list/gaslist = mix.gases[key] - message += "[gaslist[GAS_META][META_GAS_ID]]=[gaslist[MOLES]];" - log_game(message) +/proc/log_atmos(text, datum/gas_mixture/gas_mixture) + var/message = "[text]\"[print_gas_mixture(gas_mixture)]\"" + //Cache commonly accessed information. + var/list/gases = gas_mixture.gases //List of gas datum paths that are associated with a list of information related to the gases. + var/heat_capacity = gas_mixture.heat_capacity() + var/temperature = gas_mixture.return_temperature() + var/thermal_energy = temperature * heat_capacity + var/volume = gas_mixture.return_volume() + var/pressure = gas_mixture.return_pressure() + var/total_moles = gas_mixture.total_moles() + ///The total value of the gas mixture in credits. + var/total_value = 0 + var/list/specific_gas_data = list() + + //Gas specific information assigned to each gas. + for(var/datum/gas/gas_path as anything in gases) + var/list/gas = gases[gas_path] + var/moles = gas[MOLES] + var/composition = moles / total_moles + var/energy = temperature * moles * gas[GAS_META][META_GAS_SPECIFIC_HEAT] + var/value = initial(gas_path.base_value) * moles + total_value += value + specific_gas_data[gas[GAS_META][META_GAS_NAME]] = list( + "moles" = moles, + "composition" = composition, + "molar concentration" = moles / volume, + "partial pressure" = composition * pressure, + "energy" = energy, + "energy density" = energy / volume, + "value" = value, + ) + + log_game( + message, + data = list( + "total moles" = total_moles, + "volume" = volume, + "molar density" = total_moles / volume, + "temperature" = temperature, + "pressure" = pressure, + "heat capacity" = heat_capacity, + "energy" = thermal_energy, + "energy density" = thermal_energy / volume, + "value" = total_value, + "gases" = specific_gas_data, + ) + ) diff --git a/code/datums/elements/frozen.dm b/code/datums/elements/frozen.dm index b88cc2afa22..434968dd4d5 100644 --- a/code/datums/elements/frozen.dm +++ b/code/datums/elements/frozen.dm @@ -55,9 +55,13 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 Detach(source) ///signal handler for COMSIG_MOVABLE_POST_THROW that shatters our target after impacting after a throw -/datum/element/frozen/proc/shatter_on_throw(datum/target) +/datum/element/frozen/proc/shatter_on_throw(datum/target, datum/thrownthing/throwingdatum) SIGNAL_HANDLER var/obj/obj_target = target + if(ismob(throwingdatum.thrower)) + log_combat(throwingdatum.thrower, target, "shattered", addition = "from being thrown due to [target] being frozen.") + else + log_combat(throwingdatum.thrower, target, "launched", addition = "shattering it due to being frozen.") obj_target.visible_message(span_danger("[obj_target] shatters into a million pieces!")) obj_target.obj_flags |= NO_DECONSTRUCTION // disable item spawning obj_target.deconstruct(FALSE) // call pre-deletion specialized code -- internals release gas etc diff --git a/code/game/machinery/computer/records/records.dm b/code/game/machinery/computer/records/records.dm index a1292bb5e86..76ee1f19bca 100644 --- a/code/game/machinery/computer/records/records.dm +++ b/code/game/machinery/computer/records/records.dm @@ -35,6 +35,7 @@ return FALSE var/value = trim(params["value"], MAX_BROADCAST_LEN) + investigate_log("[key_name(usr)] changed the field: \"[field]\" with value: \"[target.vars[field]]\" to new value: \"[value || "Unknown"]\"", INVESTIGATE_RECORDS) target.vars[field] = value || "Unknown" return TRUE @@ -56,6 +57,7 @@ if("login") authenticated = secure_login(usr) + investigate_log("[key_name(usr)] [authenticated ? "successfully logged" : "failed to log"] into the [src].", INVESTIGATE_RECORDS) return TRUE if("logout") diff --git a/code/game/machinery/computer/records/security.dm b/code/game/machinery/computer/records/security.dm index 27b8e75e545..6e44d112b4b 100644 --- a/code/game/machinery/computer/records/security.dm +++ b/code/game/machinery/computer/records/security.dm @@ -159,6 +159,7 @@ return TRUE if("delete_record") + investigate_log("[usr] deleted record: \"[target]\".", INVESTIGATE_RECORDS) qdel(target) return TRUE @@ -175,8 +176,9 @@ return TRUE if("set_note") - var/note = params["note"] - target.security_note = trim(note, MAX_MESSAGE_LEN) + var/note = trim(params["note"], MAX_MESSAGE_LEN) + investigate_log("[usr] has changed the security note of record: \"[target]\" from \"[target.security_note]\" to \"[note]\".") + target.security_note = note return TRUE if("set_wanted") @@ -239,14 +241,19 @@ return FALSE if(user != editing_crime.author && !has_armory_access(user)) // only warden/hos/command can edit crimes they didn't author + investigate_log("[user] attempted to edit crime: \"[editing_crime.name]\" for target: \"[target.name]\" but failed due to lacking armoury access and not being the author of the crime.", INVESTIGATE_RECORDS) return FALSE if(params["name"] && length(params["name"]) > 2 && params["name"] != editing_crime.name) - editing_crime.name = trim(params["name"], MAX_CRIME_NAME_LEN) + var/new_name = trim(params["name"], MAX_CRIME_NAME_LEN) + investigate_log("[user] edited crime: \"[editing_crime.name]\" for target: \"[target.name]\", changing the name to: \"[new_name]\".", INVESTIGATE_RECORDS) + editing_crime.name = new_name return TRUE if(params["details"] && length(params["description"]) > 2 && params["name"] != editing_crime.name) - editing_crime.details = trim(params["details"], MAX_MESSAGE_LEN) + var/new_details = trim(params["details"], MAX_MESSAGE_LEN) + investigate_log("[user] edited crime \"[editing_crime.name]\" for target: \"[target.name]\", changing the details to: \"[new_details]\" from: \"[editing_crime.details]\".", INVESTIGATE_RECORDS) + editing_crime.details = new_details return TRUE return FALSE diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm index f7ed18da053..1564e4e4029 100644 --- a/code/game/objects/items/flamethrower.dm +++ b/code/game/objects/items/flamethrower.dm @@ -85,12 +85,13 @@ return // too close if(HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, span_warning("You can't bring yourself to fire \the [src]! You don't want to risk harming anyone...")) + log_combat(user, target, "attempted to flamethrower", src, "with gas mixture: {[print_gas_mixture(ptank.return_analyzable_air())]}, flamethrower: \"[name]\" ([src]), igniter: \"[igniter.name]\", tank: \"[ptank.name]\" and tank distribution pressure: \"[siunit(1000 * ptank.distribute_pressure, unit = "Pa", maxdecimals = INFINITY)]\"" + lit ? " while lit" : "" + " but failed due to pacifism.") return if(user && user.get_active_held_item() == src) // Make sure our user is still holding us var/turf/target_turf = get_turf(target) if(target_turf) var/turflist = get_line(user, target_turf) - log_combat(user, target, "flamethrowered", src) + log_combat(user, target, "flamethrowered", src, "with gas mixture: {[print_gas_mixture(ptank.return_analyzable_air())]}, flamethrower: \"[name]\", igniter: \"[igniter.name]\", tank: \"[ptank.name]\" and tank distribution pressure: \"[siunit(1000 * ptank.distribute_pressure, unit = "Pa", maxdecimals = INFINITY)]\"" + lit ? " while lit." : ".") flame_turf(turflist) /obj/item/flamethrower/wrench_act(mob/living/user, obj/item/tool) diff --git a/code/game/objects/items/rcd/RCD.dm b/code/game/objects/items/rcd/RCD.dm index 9570614b400..025571a90a7 100644 --- a/code/game/objects/items/rcd/RCD.dm +++ b/code/game/objects/items/rcd/RCD.dm @@ -219,7 +219,10 @@ delay *= FREQUENT_USE_DEBUFF_MULTIPLIER current_active_effects += 1 - _rcd_create_effect(target, user, delay, rcd_results) + var/target_name = target.name //Store the name before it gets mutated due to deconstruction. + var/target_path = target.type + if(_rcd_create_effect(target, user, delay, rcd_results)) + log_tool("used RCD with design path: \"[rcd_results["[RCD_DESIGN_MODE]"] == RCD_DECONSTRUCT ? "deconstruction" : rcd_results["[RCD_DESIGN_PATH]"]]\" with delay: \"[delay / (1 SECONDS)]s\" at target: \"[target_name] ([target_path])\" in location: \"[AREACOORD(target)]\".", user) current_active_effects -= 1 /** diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index a670a966805..e198f7d75d7 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -440,7 +440,7 @@ if(LAZYLEN(assembly.assemblies) == igniter_count) return - + if(isitem(loc)) // we are in a storage item balloon_alert(user, "can't reach!") return @@ -553,7 +553,7 @@ var/turf/T = get_turf(src) if(!T) return - log_atmos("[type] released its contents of ", air_contents) + log_atmos("[type] released its contents of ", removed) T.assume_air(removed) #undef ASSEMBLY_BOMB_BASE diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index 87523034f3e..cfb87ce7cb3 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -184,7 +184,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) if(amount <= 0) return null var/ratio = amount / sum - var/datum/gas_mixture/removed = new type + var/datum/gas_mixture/removed = new type(volume) var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars removed.temperature = temperature @@ -206,7 +206,7 @@ GLOBAL_LIST_INIT(gaslist_cache, init_gaslist_cache()) ratio = min(ratio, 1) var/list/cached_gases = gases - var/datum/gas_mixture/removed = new type + var/datum/gas_mixture/removed = new type(volume) var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars removed.temperature = temperature diff --git a/code/modules/hallucination/stray_bullet.dm b/code/modules/hallucination/stray_bullet.dm index 97f75f95061..9281bc65343 100644 --- a/code/modules/hallucination/stray_bullet.dm +++ b/code/modules/hallucination/stray_bullet.dm @@ -34,6 +34,7 @@ damage = 0 projectile_type = /obj/projectile/hallucination log_override = TRUE + do_not_log = TRUE /// Our parent hallucination that's created us var/datum/hallucination/parent /// The image that represents our projectile itself diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 682baac7927..d1dd5364477 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -182,6 +182,8 @@ var/catastropic_dismemberment = FALSE //If TRUE, this projectile deals its damage to the chest if it dismembers a limb. var/impact_effect_type //what type of impact effect to show when hitting something var/log_override = FALSE //is this type spammed enough to not log? (KAs) + /// If true, the projectile won't cause any logging. Used for hallucinations and shit. + var/do_not_log = FALSE /// We ignore mobs with these factions. var/list/ignored_factions @@ -359,7 +361,7 @@ if(reagents?.reagent_list) reagent_note = "REAGENTS: [pretty_string_from_reagent_list(reagents.reagent_list)]" - if(ismob(firer)) + if(ismob(firer) && !do_not_log) log_combat(firer, living_target, "shot", src, reagent_note) return BULLET_ACT_HIT @@ -369,11 +371,12 @@ var/list/logging_mobs = firing_vehicle.return_controllers_with_flag(VEHICLE_CONTROL_EQUIPMENT) if(!LAZYLEN(logging_mobs)) logging_mobs = firing_vehicle.return_drivers() - for(var/mob/logged_mob as anything in logging_mobs) - log_combat(logged_mob, living_target, "shot", src, "from inside [firing_vehicle][logging_mobs.len > 1 ? " with multiple occupants" : null][reagent_note ? " and contained [reagent_note]" : null]") + if(!do_not_log) + for(var/mob/logged_mob as anything in logging_mobs) + log_combat(logged_mob, living_target, "shot", src, "from inside [firing_vehicle][logging_mobs.len > 1 ? " with multiple occupants" : null][reagent_note ? " and contained [reagent_note]" : null]") return BULLET_ACT_HIT - - living_target.log_message("has been shot by [firer] with [src][reagent_note ? " containing [reagent_note]" : null]", LOG_ATTACK, color="orange") + if(!do_not_log) + living_target.log_message("has been shot by [firer] with [src][reagent_note ? " containing [reagent_note]" : null]", LOG_ATTACK, color="orange") return BULLET_ACT_HIT /obj/projectile/proc/vol_by_damage() @@ -771,7 +774,7 @@ SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_BEFORE_FIRE, src, original) if(firer) SEND_SIGNAL(firer, COMSIG_PROJECTILE_FIRER_BEFORE_FIRE, src, fired_from, original) - if(!log_override && firer && original) + if(!log_override && firer && original && !do_not_log) log_combat(firer, original, "fired at", src, "from [get_area_name(src, TRUE)]") //note: mecha projectile logging is handled in /obj/item/mecha_parts/mecha_equipment/weapon/action(). try to keep these messages roughly the sameish just for consistency's sake. if(direct_target && (get_dist(direct_target, get_turf(src)) <= 1)) // point blank shots