diff --git a/code/__DEFINES/__game.dm b/code/__DEFINES/__game.dm index 865308664975..498846e69622 100644 --- a/code/__DEFINES/__game.dm +++ b/code/__DEFINES/__game.dm @@ -36,9 +36,6 @@ #define MAP_NEW_VARADERO "New Varadero"//ice colony underground but as its own map #define MAP_CHINOOK "Chinook 91 GSO" //admin level -#define GAMEMODE_WHISKEY_OUTPOST "Whiskey Outpost" -#define GAMEMODE_HIVE_WARS "Hive Wars" - /// Number of players before we switch to lowpop maps only (LV, BR, Prison). #define PLAYERCOUNT_LOWPOP_MAP_LIMIT 130 /// Time before the round starts. diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 89deef2aafe9..beef3af309c2 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -191,60 +191,9 @@ #define EMERGENCY_PLATE_OD_WARNING 1 #define EMERGENCY_PLATE_ADJUSTED_WARNING 2 - // RESEARCH UPGRADES DEFINES END -// Statistics defines -#define STATISTIC_XENO "xeno" -#define STATISTIC_HUMAN "human" - -#define STATISTICS_DEATH_LIST_LEN 10 - -#define STATISTICS_NICHE_EXECUTION "Executions Made" -#define STATISTICS_NICHE_MEDALS "Medals Received" -#define STATISTICS_NICHE_MEDALS_GIVE "Medals Given" -#define STATISTICS_NICHE_SHOCK "Times Shocked" -#define STATISTICS_NICHE_GRENADES "Grenades Thrown" -#define STATISTICS_NICHE_FLIGHT "Flights Piloted" -#define STATISTICS_NICHE_HANDCUFF "Handcuffs Applied" -#define STATISTICS_NICHE_PILLS "Pills Fed" -#define STATISTICS_NICHE_DISCHARGE "Accidental Discharges" -#define STATISTICS_NICHE_FULTON "Fultons Deployed" -#define STATISTICS_NICHE_DISK "Disks Decrypted" -#define STATISTICS_NICHE_UPLOAD "Data Uploaded" -#define STATISTICS_NICHE_CHEMS "Chemicals Discovered" -#define STATISTICS_NICHE_CRATES "Supplies Airdropped" -#define STATISTICS_NICHE_OB "Bombardments Fired" - -#define STATISTICS_NICHE_CADES "Barricades Built" -#define STATISTICS_NICHE_UPGRADE_CADES "Barricades Upgraded" -#define STATISTICS_NICHE_REPAIR_CADES "Barricades Repaired" -#define STATISTICS_NICHE_REPAIR_GENERATOR "Generators Repaired" -#define STATISTICS_NICHE_REPAIR_APC "APCs Repaired" -#define STATISTICS_NICHE_DEFENSES_BUILT "Defenses Built" - -#define STATISTICS_NICHE_CORGI "Corgis Murdered" -#define STATISTICS_NICHE_CAT "Cats Murdered" -#define STATISTICS_NICHE_COW "Cows Murdered" -#define STATISTICS_NICHE_CHICKEN "Chickens Murdered" - -#define STATISTICS_NICHE_SURGERY_BONES "Bones Mended" -#define STATISTICS_NICHE_SURGERY_IB "Internal Bleedings Stopped" -#define STATISTICS_NICHE_SURGERY_BRAIN "Brains Mended" -#define STATISTICS_NICHE_SURGERY_EYE "Eyes Mended" -#define STATISTICS_NICHE_SURGERY_LARVA "Larvae Removed" -#define STATISTICS_NICHE_SURGERY_SHRAPNEL "Shrapnel Removed" -#define STATISTICS_NICHE_SURGERY_AMPUTATE "Limbs Amputated" -#define STATISTICS_NICHE_SURGERY_ORGAN_REPAIR "Organs Repaired" -#define STATISTICS_NICHE_SURGERY_ORGAN_ATTACH "Organs Implanted" -#define STATISTICS_NICHE_SURGERY_ORGAN_REMOVE "Organs Harvested" - -#define STATISTICS_NICHE_DESTRUCTION_WALLS "Walls Destroyed" -#define STATISTICS_NICHE_DESTRUCTION_DOORS "Doors Destroyed" -#define STATISTICS_NICHE_DESTRUCTION_WINDOWS "Windows Destroyed" - //Multiplier for turning points into cash -#define DEFCON_TO_MONEY_MULTIPLIER 10000 #define SUPPLY_TO_MONEY_MUPLTIPLIER 100 //Force the config directory to be something other than "config" diff --git a/code/__DEFINES/mode.dm b/code/__DEFINES/mode.dm index 139cab978a11..632215bfac85 100644 --- a/code/__DEFINES/mode.dm +++ b/code/__DEFINES/mode.dm @@ -39,6 +39,16 @@ //================================================= +#define MODE_NAME_EXTENDED "Extended" +#define MODE_NAME_EXTENDED_NO_SPAWN "Extended - No Spawn" +#define MODE_NAME_DISTRESS_SIGNAL "Distress Signal" +#define MODE_NAME_FACTION_CLASH "Faction Clash" +#define MODE_NAME_WISKEY_OUTPOST "Whiskey Outpost" +#define MODE_NAME_HUNTER_GAMES "Hunter Games" +#define MODE_NAME_HIVE_WARS "Hive Wars" +#define MODE_NAME_INFECTION "Infection" + +//================================================= #define IS_MODE_COMPILED(MODE) (ispath(text2path("/datum/game_mode/"+(MODE)))) @@ -320,8 +330,11 @@ DEFINE_BITFIELD(whitelist_status, list( #define FACTION_XENOMORPH_BRAVO "Bravo Xenomorph" #define FACTION_XENOMORPH_CHARLIE "Charlie Xenomorph" #define FACTION_XENOMORPH_DELTA "Delta Xenomorph" +#define FACTION_XENOMORPH_FERAL "Feral Xenomorph" +#define FACTION_XENOMORPH_FORSAKEN "Forsaken Xenomorph" -#define FACTION_LIST_XENOMORPH list(FACTION_XENOMORPH, FACTION_XENOMORPH_CORRPUTED, FACTION_XENOMORPH_ALPHA, FACTION_XENOMORPH_BRAVO, FACTION_XENOMORPH_CHARLIE, FACTION_XENOMORPH_DELTA) +#define FACTION_LIST_XENOMORPH list(FACTION_XENOMORPH, FACTION_XENOMORPH_CORRPUTED, FACTION_XENOMORPH_ALPHA, FACTION_XENOMORPH_BRAVO, FACTION_XENOMORPH_CHARLIE, FACTION_XENOMORPH_DELTA, FACTION_XENOMORPH_FERAL, FACTION_XENOMORPH_FORSAKEN) +#define FACTION_LIST_ALL FACTION_LIST_HUMANOID + FACTION_LIST_XENOMORPH + FACTION_PREDALIEN // Faction allegiances within a certain faction. diff --git a/code/__DEFINES/statistic.dm b/code/__DEFINES/statistic.dm new file mode 100644 index 000000000000..ce025cbfb8ca --- /dev/null +++ b/code/__DEFINES/statistic.dm @@ -0,0 +1,94 @@ +#define FACEHUG_TIER_1 5 +#define FACEHUG_TIER_2 25 +#define FACEHUG_TIER_3 100 +#define FACEHUG_TIER_4 1000 + +// OOD mean Out Of Date (not used, please keep this list up to date, and remember sync in db changes, I'm hard against db wipe after every big change) + +// Statistics defines +#define STATISTIC_TYPE_MISC "Misc" +#define STATISTIC_TYPE_CASTE "Caste" +#define STATISTIC_TYPE_CASTE_ABILITIES "Caste Abilities" +#define STATISTIC_TYPE_JOB "Role" +#define STATISTIC_TYPE_WEAPON "Weapon" + +// Used to replace faction name +#define STATISTIC_TYPE_GLOBAL "Global Statistic"// Don't have link to a faction + +#define STATISTICS_DEATH_LIST_LEN 20 + +#define STATISTICS_FF_SHOT_HIT "FF Shot Hit" +#define STATISTICS_SHOT_HIT "Shot Hit" +#define STATISTICS_SHOT "Shot" +#define STATISTICS_DAMAGE "Damage" +#define STATISTICS_FF_DAMAGE "FF Damage" +#define STATISTICS_HEALED_DAMAGE "Healed Damage" +#define STATISTICS_SCREAM "Scream" +#define STATISTICS_HIT "Hit" +#define STATISTICS_FF_HIT "FF Hit" +#define STATISTICS_EXPLODED_MOBS "Blowjobs Done"// :clueless_face: +#define STATISTICS_SLASH "Slash" +#define STATISTICS_REVIVE "Revive" +#define STATISTICS_REVIVED "Revived" +#define STATISTICS_STEPS_WALKED "Steps" +#define STATISTICS_KILL "Kill" +#define STATISTICS_DEATH "Death" +#define STATISTICS_KILL_FF "Kill FF" +#define STATISTICS_DEATH_FF "Death FF" +#define STATISTICS_ROUNDS_PLAYED "Rounds Played" + +#define STATISTICS_ABILITES "Abilites" +#define STATISTICS_FACEHUGGE "Facehugge" +#define STATISTIC_XENO_STRUCTURES_BUILD "Builded" + +#define STATISTICS_EXECUTION "Executions Made" +#define STATISTICS_MEDALS "Medals Received" +#define STATISTICS_MEDALS_GIVE "Medals Given" +#define STATISTICS_SHOCK "Times Shocked" +#define STATISTICS_GRENADES "Grenades Thrown" +#define STATISTICS_FLIGHT "Flights Piloted" +#define STATISTICS_HANDCUFF "Handcuffs Applied" +#define STATISTICS_PILLS "Pills Fed" +#define STATISTICS_DISCHARGE "Accidental Discharges" +#define STATISTICS_FULTON "Fultons Deployed" +#define STATISTICS_DISK "Disks Decrypted" +#define STATISTICS_UPLOAD "Data Uploaded" +#define STATISTICS_CHEMS "Chemicals Discovered" +#define STATISTICS_CRATES "Supplies Airdropped" +#define STATISTICS_OB "Bombardments Fired" +#define STATISTICS_AMMO_CONVERTED "Ammo Converted" +#define STATISTICS_IMPLANTS_IMPLANTED "Implants Implanted" +#define STATISTICS_REVIVED_BY_IMPLANT "Revive Implant Saved Lifes" +#define STATISTICS_SD_ACTIVATION "SD Activated"// OOD +#define STATISTICS_SACRIFICE "Sacrificed"// OOD +#define STATISTICS_ESCAPE "Escaped" + +#define STATISTICS_CADES "Barricades Built" +#define STATISTICS_UPGRADE_CADES "Barricades Upgraded" +#define STATISTICS_REPAIR_CADES "Barricades Repaired" +#define STATISTICS_REPAIR_GENERATOR "Generators Repaired" +#define STATISTICS_REPAIR_SENSORTOWER "Sensor Towers Repaired" +#define STATISTICS_REPAIR_APC "APCs Repaired" +#define STATISTICS_UPGRADE_TURRETS "Defenses Upgraded" +#define STATISTICS_DEFENSES_BUILT "Defenses Built"// OOD + +#define STATISTICS_CORGI "Corgis Murdered" +#define STATISTICS_CAT "Cats Murdered" +#define STATISTICS_COW "Cows Murdered" +#define STATISTICS_CHICKEN "Chickens Murdered" + +#define STATISTICS_SURGERY_BONES "Bones Mended" +#define STATISTICS_SURGERY_IB "Internal Bleedings Stopped" +#define STATISTICS_SURGERY_BRAIN "Brains Mended" +#define STATISTICS_SURGERY_EYE "Eyes Mended" +#define STATISTICS_SURGERY_LARVA "Larvae Removed" +#define STATISTICS_SURGERY_NECRO "Necro Limbs Fixed"// OOD +#define STATISTICS_SURGERY_SHRAPNEL "Shrapnel Removed" +#define STATISTICS_SURGERY_AMPUTATE "Limbs Amputated" +#define STATISTICS_SURGERY_ORGAN_REPAIR "Organs Repaired" +#define STATISTICS_SURGERY_ORGAN_ATTACH "Organs Implanted"// OOD +#define STATISTICS_SURGERY_ORGAN_REMOVE "Organs Harvested"// OOD + +#define STATISTICS_DESTRUCTION_WALLS "Walls Destroyed" +#define STATISTICS_DESTRUCTION_DOORS "Doors Destroyed" +#define STATISTICS_DESTRUCTION_WINDOWS "Windows Destroyed" diff --git a/code/__DEFINES/stats.dm b/code/__DEFINES/stats.dm deleted file mode 100644 index 1810d01e1d93..000000000000 --- a/code/__DEFINES/stats.dm +++ /dev/null @@ -1,14 +0,0 @@ -#define get_client_stat(client, stat) (client.player_data ? LAZYACCESS(client.player_data.stats, stat) ? client.player_data.stats[stat].stat_number : 0 : 0) - -// Stat IDs -#define PLAYER_STAT_FACEHUGS "facehugs" - -#define FACEHUG_TIER_1 5 -#define FACEHUG_TIER_2 25 -#define FACEHUG_TIER_3 100 -#define FACEHUG_TIER_4 1000 - -// Stat Categories -#define STAT_CATEGORY_MARINE "marine" -#define STAT_CATEGORY_XENO "xeno" -#define STAT_CATEGORY_YAUTJA "yautja" diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 9b709b9be3e5..69da521222da 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -114,6 +114,13 @@ #define SS_INIT_TOPIC 83 #define SS_INIT_LOBBYART 82 #define SS_INIT_INFLUXDRIVER 28 +// Do not break this braket +#define SS_INIT_DATABASE 27.9 +#define SS_INIT_ENTITYMANAGER 27.8 +#define SS_INIT_TICKER 27.7 +#define SS_INIT_PREF_LOGGING 27.6 +#define SS_INIT_PLAYTIME 27.5 +// Do not break this braket #define SS_INIT_GARBAGE 24 #define SS_INIT_EVENTS 23.5 #define SS_INIT_HIJACK 22.6 @@ -143,11 +150,7 @@ #define SS_INIT_UNSPECIFIED 0 #define SS_INIT_PREDSHIPS -19 #define SS_INIT_ASSETS -20 -#define SS_INIT_TICKER -21 #define SS_INIT_VOTE -23 -#define SS_INIT_DATABASE -27 -#define SS_INIT_ENTITYMANAGER -28 -#define SS_INIT_PLAYTIME -29 #define SS_INIT_STICKY -30 #define SS_INIT_OBJECTIVES -32 #define SS_INIT_MINIMAP -34 diff --git a/code/_globalvars/global_lists.dm b/code/_globalvars/global_lists.dm index 9b241b007d16..054c56d994bf 100644 --- a/code/_globalvars/global_lists.dm +++ b/code/_globalvars/global_lists.dm @@ -56,6 +56,8 @@ GLOBAL_LIST_EMPTY(cached_maps) GLOB.minimap_icons = base64_icons +GLOBAL_DATUM(round_statistics, /datum/entity/statistic_round) +GLOBAL_LIST_EMPTY_TYPED(player_entities, /datum/player_entity) // Xeno stuff // // Resin constructions parameters diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm index b976c647527e..2924973db763 100644 --- a/code/_globalvars/misc.dm +++ b/code/_globalvars/misc.dm @@ -83,7 +83,7 @@ GLOBAL_VAR_INIT(perf_flags, NO_FLAGS) GLOBAL_LIST_INIT(bitflags, list((1<<0), (1<<1), (1<<2), (1<<3), (1<<4), (1<<5), (1<<6), (1<<7), (1<<8), (1<<9), (1<<10), (1<<11), (1<<12), (1<<13), (1<<14), (1<<15), (1<<16), (1<<17), (1<<18), (1<<19), (1<<20), (1<<21), (1<<22), (1<<23))) -GLOBAL_VAR_INIT(master_mode, "Distress Signal") +GLOBAL_VAR_INIT(master_mode, MODE_NAME_DISTRESS_SIGNAL) GLOBAL_VAR_INIT(timezoneOffset, 0) diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 1631bc7bd12e..abb3d9bf2138 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -111,11 +111,17 @@ if("fire") M.apply_damage(power,BURN) to_chat(M, SPAN_WARNING("It burns!")) + + if(user.faction == M.faction) + user.track_friendly_hit(initial(name)) + user.track_friendly_damage(initial(name), M, power) + else + user.track_hit(initial(name)) + user.track_damage(initial(name), M, power) + if(power > 5) M.last_damage_data = create_cause_data(initial(name), user) - user.track_hit(initial(name)) - if(user.faction == M.faction) - user.track_friendly_fire(initial(name)) + M.updatehealth() else var/mob/living/carbon/human/H = M diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index a41a619e602f..10dd90dfebab 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -271,7 +271,7 @@ Voting // Gamemode to auto-switch to at the start of the round /datum/config_entry/string/gamemode_default - config_entry_value = "Extended" + config_entry_value = MODE_NAME_EXTENDED /datum/config_entry/number/rounds_until_hard_restart config_entry_value = -1 // -1 is disabled by default, 0 is every round, x is after so many rounds diff --git a/code/controllers/subsystem/influxstats.dm b/code/controllers/subsystem/influxstats.dm index 066c94cc2593..530277c112c5 100644 --- a/code/controllers/subsystem/influxstats.dm +++ b/code/controllers/subsystem/influxstats.dm @@ -44,13 +44,6 @@ SUBSYSTEM_DEF(influxstats) step = 1 -/datum/controller/subsystem/influxstats/proc/flatten_entity_list(list/data) - var/list/result = list() - for(var/key in data) - var/datum/entity/statistic/entry = data[key] - result[key] = entry.value - return result - /datum/controller/subsystem/influxstats/proc/run_special_round_statistics() for(var/hive_tag in GLOB.hive_datum) var/datum/hive_status/hive = GLOB.hive_datum[hive_tag] @@ -59,21 +52,20 @@ SUBSYSTEM_DEF(influxstats) SSinfluxdriver.enqueue_stats("burst_larva", list("hive" = hive.reporting_id), list("count" = burst_larvas)) /datum/controller/subsystem/influxstats/proc/run_round_statistics() - var/datum/entity/statistic/round/stats = SSticker?.mode?.round_stats + var/datum/entity/statistic_round/stats = GLOB.round_statistics if(!stats) return // Sadge SSinfluxdriver.enqueue_stats_crude("chestbursts", stats.total_larva_burst) SSinfluxdriver.enqueue_stats_crude("hugged", stats.total_huggers_applied) SSinfluxdriver.enqueue_stats_crude("friendlyfire", stats.total_friendly_fire_instances) + SSinfluxdriver.enqueue_stats_crude("friendlykills", stats.total_friendly_kills) - var/list/participants = flatten_entity_list(stats.participants) - if(length(participants)) - SSinfluxdriver.enqueue_stats("participants", list(), participants) + if(length(stats.participants)) + SSinfluxdriver.enqueue_stats("participants", list(), stats.participants) - var/list/total_deaths = flatten_entity_list(stats.total_deaths) - if(length(total_deaths)) - SSinfluxdriver.enqueue_stats("deaths", list(), total_deaths) + if(length(stats.total_deaths)) + SSinfluxdriver.enqueue_stats("deaths", list(), stats.total_deaths) SSinfluxdriver.enqueue_stats("shots", list(), list("fired" = stats.total_projectiles_fired, "hits" = stats.total_projectiles_hit, diff --git a/code/controllers/subsystem/perf_logging.dm b/code/controllers/subsystem/perf_logging.dm index 4a3066b758ba..cf530bdd4cdf 100644 --- a/code/controllers/subsystem/perf_logging.dm +++ b/code/controllers/subsystem/perf_logging.dm @@ -1,7 +1,10 @@ +#define WAIT_SSPERFLOGGING_READY while(!SSperf_logging.round) {stoplag();} + SUBSYSTEM_DEF(perf_logging) name = "Perf Logging" wait = 60 SECONDS - flags = SS_NO_INIT | SS_KEEP_TIMING + init_order = SS_INIT_PREF_LOGGING + flags = SS_KEEP_TIMING priority = SS_PRIORITY_PERFLOGGING var/datum/entity/mc_round/round var/list/datum/entity/mc_controller/controller_assoc = list() @@ -9,14 +12,11 @@ SUBSYSTEM_DEF(perf_logging) var/ord = 0 // Amount of measurements var/tcost = 0 // Total cost for current tick +/datum/controller/subsystem/perf_logging/Initialize(timeofday) + start_logging() + return SS_INIT_SUCCESS + /datum/controller/subsystem/perf_logging/fire(resumed = FALSE) - if(SSticker?.current_state < GAME_STATE_PLAYING) - return // Not started yet - if(!SSentity_manager?.ready) - return // DB not ready - if(!round) // Init - start_logging() - return if(!resumed) ord++ tcost = 0 @@ -26,8 +26,8 @@ SUBSYSTEM_DEF(perf_logging) if(SS?.cost > 0.1) currentrun += SS - while(length(currentrun)) - var/datum/controller/subsystem/SS = currentrun[length(currentrun)] + while(currentrun.len) + var/datum/controller/subsystem/SS = currentrun[currentrun.len] currentrun.len-- var/datum/entity/mc_controller/C = controller_assoc[SS.type] new_record(SS, C) @@ -39,15 +39,18 @@ SUBSYSTEM_DEF(perf_logging) /// Setup to begin performance logging when game starts /datum/controller/subsystem/perf_logging/proc/start_logging() SHOULD_NOT_SLEEP(TRUE) - var/datum/map_config/ground = SSmapping.configs[GROUND_MAP] - if(!ground) return + var/datum/map_config/ground = SSmapping.configs?[GROUND_MAP] + if(!ground) + return ord = 0 round = SSentity_manager.round round.map_name = ground.map_name + round.save() var/datum/entity/mc_controller/C for(var/datum/controller/subsystem/SS in Master.subsystems) C = SSentity_manager.select_by_key(/datum/entity/mc_controller, "[SS.type]") - if(!C) continue + if(!C) + continue C.wait_time = SS.wait C.save() controller_assoc[SS.type] = C diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index adcffbd07b5e..2870f71655f9 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -53,6 +53,9 @@ SUBSYSTEM_DEF(ticker) var/tutorial_disabled = FALSE /datum/controller/subsystem/ticker/Initialize(timeofday) + if(!SSmapping.configs) + SSmapping.HACK_LoadMapConfig() + load_mode() var/all_music = CONFIG_GET(keyed_list/lobby_music) @@ -172,8 +175,6 @@ SUBSYSTEM_DEF(ticker) /datum/controller/subsystem/ticker/proc/setup() to_chat(world, SPAN_BOLDNOTICE("Enjoy the game!")) var/init_start = world.timeofday - //Create and announce mode - mode = config.pick_mode(GLOB.master_mode) CHECK_TICK if(!mode.can_start(bypass_checks)) @@ -198,13 +199,11 @@ SUBSYSTEM_DEF(ticker) handle_map_reboot() else to_chat(world, "Attempting again...") - QDEL_NULL(mode) GLOB.RoleAuthority.reset_roles() return FALSE CHECK_TICK if(!mode.pre_setup() && !bypass_checks) - QDEL_NULL(mode) to_chat(world, "Error in pre-setup for [GLOB.master_mode]. Reverting to pre-game lobby.") GLOB.RoleAuthority.reset_roles() return FALSE @@ -231,9 +230,6 @@ SUBSYSTEM_DEF(ticker) LAZYCLEARLIST(round_start_events) CHECK_TICK - // We need stats to track roundstart role distribution. - mode.setup_round_stats() - //Configure mode and assign player to special mode stuff if (!(mode.flags_round_type & MODE_NO_SPAWN)) var/roles_to_roll = null @@ -353,11 +349,17 @@ SUBSYSTEM_DEF(ticker) /datum/controller/subsystem/ticker/proc/load_mode() - var/mode = trim(file2text("data/mode.txt")) - if(mode) - GLOB.master_mode = SSmapping.configs[GROUND_MAP].force_mode ? SSmapping.configs[GROUND_MAP].force_mode : mode + var/cfg_mode = trim(file2text("data/mode.txt")) + if(SSmapping?.configs?[GROUND_MAP].force_mode) + GLOB.master_mode = SSmapping.configs[GROUND_MAP].force_mode + else if(cfg_mode) + GLOB.master_mode = cfg_mode else - GLOB.master_mode = "Extended" + GLOB.master_mode = MODE_NAME_EXTENDED + + mode = config.pick_mode(GLOB.master_mode) + mode.setup_round_stats() + log_game("Saved mode is '[GLOB.master_mode]'") diff --git a/code/datums/ammo/bullet/bullet.dm b/code/datums/ammo/bullet/bullet.dm index 9adc4ba2ae50..3479886c711b 100644 --- a/code/datums/ammo/bullet/bullet.dm +++ b/code/datums/ammo/bullet/bullet.dm @@ -69,7 +69,7 @@ execution_target.visible_message(SPAN_HIGHDANGER(uppertext("[execution_target] WAS EXECUTED!")), SPAN_HIGHDANGER("You WERE EXECUTED!")) - user.count_niche_stat(STATISTICS_NICHE_EXECUTION, 1, firing_projectile.weapon_cause_data?.cause_name) + user.count_statistic_stat(STATISTICS_EXECUTION) var/area/execution_area = get_area(execution_target) diff --git a/code/datums/components/disk_reader.dm b/code/datums/components/disk_reader.dm index 6292519893e9..b8971f2e11a2 100644 --- a/code/datums/components/disk_reader.dm +++ b/code/datums/components/disk_reader.dm @@ -61,7 +61,7 @@ inserter.drop_inv_item_to_loc(potential_disk, parent) disk = potential_disk to_chat(inserter, SPAN_NOTICE("You insert [potential_disk] and enter the decryption key.")) - inserter.count_niche_stat(STATISTICS_NICHE_DISK) + inserter.count_statistic_stat(STATISTICS_DISK) /datum/component/disk_reader/proc/on_disk_complete(datum/source) SIGNAL_HANDLER diff --git a/code/datums/effects/xeno_strains/prae_acid_stacks.dm b/code/datums/effects/xeno_strains/prae_acid_stacks.dm index 30218d1164e6..7756afbe5b3a 100644 --- a/code/datums/effects/xeno_strains/prae_acid_stacks.dm +++ b/code/datums/effects/xeno_strains/prae_acid_stacks.dm @@ -71,7 +71,12 @@ return var/mob/living/carbon/human/H = affected_atom + var/mob/cause_mob = cause_data.resolve_mob() H.apply_damage(proc_damage, BURN) + if(cause_mob.faction == H.faction) + cause_mob.track_friendly_damage("Acid", H, proc_damage) + else + cause_mob.track_damage("Acid", H, proc_damage) to_chat(H, SPAN_XENODANGER("You feel acid eat into your skin!")) qdel(src) return diff --git a/code/datums/elements/suturing.dm b/code/datums/elements/suturing.dm index eee65b0ba7df..4a7df46361e0 100644 --- a/code/datums/elements/suturing.dm +++ b/code/datums/elements/suturing.dm @@ -155,7 +155,7 @@ YOU TO 200 DAMAGE. I ASK NOT FOR MY OWN MEDIC EGOSTROKING, BUT FOR THE GOOD OF T //Add the sutures. var/added_sutures = SEND_SIGNAL(target_limb, COMSIG_LIMB_ADD_SUTURES, suture_brute, suture_burn) if(!added_sutures) //No suture datum to answer the signal - new /datum/suture_handler(target_limb) + new /datum/suture_handler(target_limb, suturing_item, user, target) added_sutures = SEND_SIGNAL(target_limb, COMSIG_LIMB_ADD_SUTURES, suture_brute, suture_burn) //This time, with feeling. if(added_sutures & SUTURED_FULLY) @@ -181,8 +181,15 @@ YOU TO 200 DAMAGE. I ASK NOT FOR MY OWN MEDIC EGOSTROKING, BUT FOR THE GOOD OF T var/remaining_brute var/remaining_burn -/datum/suture_handler/New(obj/limb/target_limb) + var/obj/suturing_item + var/mob/healing + var/mob/healed + +/datum/suture_handler/New(obj/limb/target_limb, obj/item, mob/user, mob/target) . = ..() + suturing_item = item + healing = user + healed = target remaining_brute = target_limb.brute_dam remaining_burn = target_limb.burn_dam RegisterSignal(target_limb, COMSIG_LIMB_TAKEN_DAMAGE, PROC_REF(update_sutures)) @@ -276,6 +283,7 @@ maximum_heal = total amount of each damage type that can be healed - IE TRUE/TRU W.salved |= WOUND_SUTURED target_limb.heal_damage(brute_to_heal, burn_to_heal) + healing.track_heal_damage(initial(suturing_item.name), healed, brute_to_heal + burn_to_heal) if(!suture_brute && !suture_burn) return SUTURED_FULLY diff --git a/code/datums/entities/player.dm b/code/datums/entities/player.dm index 41ee35fbe179..ba37c2c6f246 100644 --- a/code/datums/entities/player.dm +++ b/code/datums/entities/player.dm @@ -51,7 +51,7 @@ var/list/datum/entity/player_note/notes var/list/datum/entity/player_job_ban/job_bans var/list/datum/entity/player_time/playtimes - var/list/datum/entity/player_stat/stats + var/datum/player_entity/player_entity var/list/playtime_data // For the NanoUI menu var/client/owning_client @@ -408,7 +408,6 @@ BSQL_PROTECT_DATUM(/datum/entity/player) INVOKE_ASYNC(src, TYPE_PROC_REF(/datum/entity/player, migrate_jobbans)) DB_FILTER(/datum/entity/player_time, DB_COMP("player_id", DB_EQUALS, id), CALLBACK(src, TYPE_PROC_REF(/datum/entity/player, on_read_timestat))) - DB_FILTER(/datum/entity/player_stat, DB_COMP("player_id", DB_EQUALS, id), CALLBACK(src, TYPE_PROC_REF(/datum/entity/player, on_read_stats))) if(!migrated_bans && !migrating_bans) migrating_bans = TRUE @@ -428,6 +427,14 @@ BSQL_PROTECT_DATUM(/datum/entity/player) if(whitelist in GLOB.bitfields["whitelist_status"]) whitelist_flags |= GLOB.bitfields["whitelist_status"]["[whitelist]"] + setup_statistics() + +/datum/entity/player/proc/setup_statistics() + if(!player_entity) + player_entity = setup_player_entity(ckey) + player_entity.player = src + player_entity.setup_entity() + /datum/entity/player/proc/on_read_notes(list/datum/entity/player_note/_notes) notes_loaded = TRUE if(notes) @@ -454,11 +461,6 @@ BSQL_PROTECT_DATUM(/datum/entity/player) for(var/datum/entity/player_time/S in _stat) LAZYSET(playtimes, S.role_id, S) -/datum/entity/player/proc/on_read_stats(list/datum/entity/player_stat/_stat) - if(_stat) - for(var/datum/entity/player_stat/S as anything in _stat) - LAZYSET(stats, S.stat_id, S) - /datum/entity/player/proc/load_byond_account_age() var/list/http_request = world.Export("http://byond.com/members/[ckey]?format=text") if(!http_request) @@ -726,20 +728,6 @@ BSQL_PROTECT_DATUM(/datum/entity/player) migrated_jobbans = TRUE save() -/datum/entity/player/proc/adjust_stat(stat_id, stat_category, num, set_to_num = FALSE) - var/datum/entity/player_stat/stat = LAZYACCESS(stats, stat_id) - if(!stat) - stat = DB_ENTITY(/datum/entity/player_stat) - stat.player_id = id - stat.stat_id = stat_id - stat.stat_category = stat_category - LAZYSET(stats, stat_id, stat) - if(set_to_num) - stat.stat_number = num - else - stat.stat_number += num - stat.save() - /datum/entity/player/proc/check_whitelist_status(flag_to_check) if(whitelist_flags & flag_to_check) return TRUE diff --git a/code/datums/map_config.dm b/code/datums/map_config.dm index 929f133dd7a5..f0572a172bda 100644 --- a/code/datums/map_config.dm +++ b/code/datums/map_config.dm @@ -392,10 +392,10 @@ if(!(g in gamemode_names)) log_world("map_config has an invalid gamemode name!") return - if(g == "Extended") // always allow extended + if(g == MODE_NAME_EXTENDED) // always allow extended continue gamemodes += g - gamemodes += "Extended" + gamemodes += MODE_NAME_EXTENDED else if(!isnull(json["gamemodes"])) log_world("map_config gamemodes is not a list!") return diff --git a/code/datums/medal_awards.dm b/code/datums/medal_awards.dm index 772bdebbed23..99551dcbc699 100644 --- a/code/datums/medal_awards.dm +++ b/code/datums/medal_awards.dm @@ -74,7 +74,7 @@ GLOBAL_LIST_INIT(human_medals, list(MARINE_CONDUCT_MEDAL, MARINE_BRONZE_HEART_ME if(!as_admin && mob == usr) // Giver: Increment their medals given stat giver_mob = mob - mob.count_niche_stat(STATISTICS_NICHE_MEDALS_GIVE) + track_statistic_earned(giver_mob.faction, STATISTIC_TYPE_MISC, STATISTICS_MEDALS_GIVE, 1, giver_mob.client.player_data) if(found_other) break found_other = TRUE @@ -153,7 +153,7 @@ GLOBAL_LIST_INIT(human_medals, list(MARINE_CONDUCT_MEDAL, MARINE_BRONZE_HEART_ME // Recipient: Add the medal to the player's stats if(recipient_ckey) - var/datum/entity/player_entity/recipient_player = setup_player_entity(recipient_ckey) + var/datum/player_entity/recipient_player = setup_player_entity(recipient_ckey) if(recipient_player) recipient_player.track_medal_earned(medal_type, recipient_mob, recipient_rank, citation, usr) @@ -246,9 +246,9 @@ GLOBAL_LIST_INIT(human_medals, list(MARINE_CONDUCT_MEDAL, MARINE_BRONZE_HEART_ME // Recipient: Add the medal to the player's stats if(recipient_ckey) - var/datum/entity/player_entity/recipient_player = setup_player_entity(recipient_ckey) + var/datum/player_entity/recipient_player = setup_player_entity(recipient_ckey) if(recipient_player) - recipient_player.track_medal_earned(medal_type, recipient_mob, recipient_rank, citation, giving_mob) + recipient_player.track_medal_earned(medal_type, recipient_mob, recipient_rank, citation, usr) // Inform staff of success message_admins("[key_name_admin(giving_mob)] awarded a [medal_type] to [chosen_recipient] for: \'[citation]\'.") @@ -342,7 +342,7 @@ GLOBAL_LIST_INIT(xeno_medals, list(XENO_SLAUGHTER_MEDAL, XENO_RESILIENCE_MEDAL, if(mob == usr) // Giver: Increment their medals given stat giver_mob = mob - mob.count_niche_stat(STATISTICS_NICHE_MEDALS_GIVE) + track_statistic_earned(giver_mob.faction, STATISTIC_TYPE_MISC, STATISTICS_MEDALS_GIVE, 1, giver_mob.client.player_data) break // Create the recipient_award @@ -376,7 +376,7 @@ GLOBAL_LIST_INIT(xeno_medals, list(XENO_SLAUGHTER_MEDAL, XENO_RESILIENCE_MEDAL, // Recipient: Add the medal to the player's stats if(recipient_ckey) - var/datum/entity/player_entity/recipient_player = setup_player_entity(recipient_ckey) + var/datum/player_entity/recipient_player = setup_player_entity(recipient_ckey) if(recipient_player) recipient_player.track_medal_earned(medal_type, recipient_mob, recipient_caste, citation, usr) @@ -446,11 +446,11 @@ GLOBAL_LIST_INIT(xeno_medals, list(XENO_SLAUGHTER_MEDAL, XENO_RESILIENCE_MEDAL, // Remove giver's stat if(giver_mob) - giver_mob.count_niche_stat(STATISTICS_NICHE_MEDALS_GIVE, -1) + track_statistic_earned(giver_mob.faction, STATISTIC_TYPE_MISC, STATISTICS_MEDALS_GIVE, -1, giver_mob.client.player_data) // Remove stats for recipient (this has a weakref to the mob, but theres a possibility of recipient.statistic_exempt) if(recipient_mob) - var/datum/entity/player_entity/recipient_player = setup_player_entity(recipient_mob.persistent_ckey) + var/datum/player_entity/recipient_player = setup_player_entity(recipient_mob.persistent_ckey) if(recipient_player) recipient_player.untrack_medal_earned(medal_type, recipient_mob, citation) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 945f4d0a5351..d64d8eb2979c 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -10,8 +10,6 @@ var/memory - var/datum/entity/player_entity/player_entity = null - //put this here for easier tracking ingame var/datum/money_account/initial_account @@ -23,7 +21,6 @@ /datum/mind/New(key, ckey) src.key = key src.ckey = ckey - player_entity = setup_player_entity(ckey) objective_memory = new() objective_interface = new() research_objective_interface = new() @@ -36,7 +33,6 @@ current = null original = null ghost_mob = null - player_entity = null return ..() /datum/mind/proc/transfer_to(mob/living/new_character, force = FALSE) @@ -76,7 +72,6 @@ if(ui.allowed_user_stat == -1) ui.close() continue - player_entity = setup_player_entity(ckey) SEND_SIGNAL(src, COMSIG_MIND_TRANSFERRED, old_current) SEND_SIGNAL(new_character, COMSIG_MOB_NEW_MIND, current.client) @@ -109,23 +104,6 @@ for(var/obj/item/W in current) current.drop_inv_item_on_ground(W) -/datum/mind/proc/setup_human_stats() - if(!player_entity) - player_entity = setup_player_entity(ckey) - if(!player_entity) - return - return player_entity.setup_human_stats() - -/datum/mind/proc/setup_xeno_stats() - if(!player_entity) - player_entity = setup_player_entity(ckey) - if(!player_entity) - return - return player_entity.setup_xeno_stats() - -/datum/mind/proc/wipe_entity() - player_entity = null - //Initialisation procs /mob/proc/mind_initialize() if(mind) mind.key = key diff --git a/code/datums/statistics/entities/caste_stats.dm b/code/datums/statistics/entities/caste_stats.dm deleted file mode 100644 index 6bfc18d124b7..000000000000 --- a/code/datums/statistics/entities/caste_stats.dm +++ /dev/null @@ -1,24 +0,0 @@ -/datum/entity/player_stats/caste - var/name = null - var/total_hits = 0 - var/list/abilities_used = list() // types of /datum/entity/statistic, "tail sweep" = 10, "screech" = 2 - -/datum/entity/player_stats/caste/Destroy(force) - . = ..() - QDEL_LIST_ASSOC_VAL(abilities_used) - -/datum/entity/player_stats/caste/proc/setup_ability(ability) - if(!ability) - return - var/ability_key = strip_improper(ability) - if(abilities_used["[ability_key]"]) - return abilities_used["[ability_key]"] - var/datum/entity/statistic/S = new() - S.name = ability_key - S.value = 0 - abilities_used["[ability_key]"] = S - return S - -/datum/entity/player_stats/caste/proc/track_personal_abilities_used(ability, amount = 1) - var/datum/entity/statistic/S = setup_ability(ability) - S.value += amount diff --git a/code/datums/statistics/entities/death_stats.dm b/code/datums/statistics/entities/death_stats.dm index de2d9cc71526..8fe88386f196 100644 --- a/code/datums/statistics/entities/death_stats.dm +++ b/code/datums/statistics/entities/death_stats.dm @@ -1,4 +1,4 @@ -/datum/entity/statistic/death +/datum/entity/statistic_death var/player_id var/round_id @@ -7,8 +7,6 @@ var/mob_name var/area_name - var/is_xeno - var/cause_name var/cause_player_id var/cause_role_name @@ -31,9 +29,17 @@ var/y var/z +BSQL_PROTECT_DATUM(/datum/entity/statistic_death) + +/datum/entity/statistic_death/Destroy() + if(GLOB.round_statistics) + GLOB.round_statistics.death_stats_list -= src + + . = ..() + /datum/entity_meta/statistic_death - entity_type = /datum/entity/statistic/death - table_name = "log_player_statistic_death" + entity_type = /datum/entity/statistic_death + table_name = "player_statistic_death" field_types = list( "player_id" = DB_FIELDTYPE_BIGINT, "round_id" = DB_FIELDTYPE_BIGINT, @@ -63,8 +69,69 @@ "x" = DB_FIELDTYPE_INT, "y" = DB_FIELDTYPE_INT, - "z" = DB_FIELDTYPE_INT + "z" = DB_FIELDTYPE_INT, + ) + +/datum/view_record/statistic_death + var/player_id + var/round_id + + var/role_name + var/faction_name + var/mob_name + var/area_name + + var/cause_name + var/cause_player_id + var/cause_role_name + var/cause_faction_name + + var/total_steps = 0 + var/total_kills = 0 + var/time_of_death + var/total_time_alive + + var/total_brute = 0 + var/total_burn = 0 + var/total_oxy = 0 + var/total_tox = 0 + + var/x + var/y + var/z + +/datum/entity_view_meta/statistic_death_ordered + root_record_type = /datum/entity/statistic_death + destination_entity = /datum/view_record/statistic_death + fields = list( + "player_id", + "round_id", + + "role_name", + "faction_name", + "mob_name", + "area_name", + + "cause_name", + "cause_player_id", + "cause_role_name", + "cause_faction_name", + + "total_steps", + "total_kills", + "time_of_death", + "total_time_alive", + + "total_brute", + "total_burn", + "total_oxy", + "total_tox", + + "x", + "y", + "z", ) + order_by = list("round_id" = DB_ORDER_BY_DESC) /mob/proc/track_mob_death(datum/cause_data/cause_data, turf/death_loc) if(cause_data && !istype(cause_data)) @@ -76,6 +143,7 @@ log_message += "[cause_data.cause_name]" else log_message += "unknown causes" + var/mob/cause_mob = cause_data?.resolve_mob() if(cause_mob) log_message += " from [key_name(cause_data.resolve_mob())]" @@ -83,25 +151,23 @@ attack_log += "[log_message]." - if(!mind || statistic_exempt) + if(statistic_exempt) return var/area/area = get_area(death_loc) handle_observer_message(cause_data, cause_mob, death_loc, area) - // Perform logging above before get_player_from_key to avoid delays - var/datum/entity/statistic/death/new_death = DB_ENTITY(/datum/entity/statistic/death) - var/datum/entity/player/player_entity = get_player_from_key(mind.ckey) + var/datum/entity/statistic_death/new_death = DB_ENTITY(/datum/entity/statistic_death) + var/datum/entity/player/player_entity = get_player_from_key(mind ? mind.ckey : ckey) if(player_entity) new_death.player_id = player_entity.id - if(SSperf_logging) - new_death.round_id = SSperf_logging.round.id + new_death.round_id = SSperf_logging.round?.id new_death.role_name = get_role_name() new_death.mob_name = real_name new_death.faction_name = faction - new_death.is_xeno = FALSE + new_death.area_name = area.name new_death.cause_name = cause_data?.cause_name @@ -136,31 +202,31 @@ new_death.total_revives_done = life_revives_total new_death.total_ib_fixed = life_ib_total + var/ff_type = new_death.cause_faction_name == new_death.faction_name ? 1 : 0 if(GLOB.round_statistics) - GLOB.round_statistics.track_death(new_death) + GLOB.round_statistics.track_dead_participant(new_death.faction_name) + if(ff_type) + GLOB.round_statistics.total_friendly_kills++ - new_death.save() - new_death.detach() - return new_death + if(cause_player) + if(isxeno(cause_mob)) + track_statistic_earned(new_death.cause_faction_name, STATISTIC_TYPE_CASTE, new_death.cause_role_name, ff_type ? STATISTICS_KILL_FF : STATISTICS_KILL, 1, cause_player) + else if(ishuman(cause_mob)) + track_statistic_earned(new_death.cause_faction_name, STATISTIC_TYPE_JOB, new_death.cause_role_name, ff_type ? STATISTICS_KILL_FF : STATISTICS_KILL, 1, cause_player) + if(new_death.cause_role_name) + track_statistic_earned(new_death.cause_faction_name, STATISTIC_TYPE_WEAPON, new_death.cause_role_name, ff_type ? STATISTICS_KILL_FF : STATISTICS_KILL, 1, cause_player) -/mob/living/carbon/human/track_mob_death(datum/cause_data/cause_data, turf/death_loc) - . = ..() - if(statistic_exempt || !mind) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - if(human_stats && human_stats.death_list) - human_stats.death_list.Insert(1, .) + if(player_entity) + if(isxeno(src)) + track_statistic_earned(new_death.faction_name, STATISTIC_TYPE_CASTE, new_death.role_name, ff_type ? STATISTICS_DEATH_FF : STATISTICS_DEATH, 1, player_entity) + else if(ishuman(src)) + track_statistic_earned(new_death.faction_name, STATISTIC_TYPE_JOB, new_death.cause_name, ff_type ? STATISTICS_DEATH_FF : STATISTICS_DEATH, 1, player_entity) -/mob/living/carbon/xenomorph/track_mob_death(datum/cause_data/cause_data, turf/death_loc) - var/datum/entity/statistic/death/new_death = ..() - if(!new_death) - return - new_death.is_xeno = TRUE // this was placed beneath the if below, which meant gibbing as a xeno wouldn't track properly in stats - if(statistic_exempt || !mind) - return - var/datum/entity/player_stats/xeno/xeno_stats = mind.setup_xeno_stats() - if(xeno_stats && xeno_stats.death_list) - xeno_stats.death_list.Insert(1, new_death) + if(GLOB.round_statistics && new_death.cause_name != "existing") + GLOB.round_statistics.death_stats_list += new_death + + new_death.save() + return new_death /mob/proc/handle_observer_message(datum/cause_data/cause_data, mob/cause_mob, turf/death_loc, area/death_area) var/observer_message = "[real_name] has died" diff --git a/code/datums/statistics/entities/human_stats.dm b/code/datums/statistics/entities/human_stats.dm deleted file mode 100644 index 20d5a284becd..000000000000 --- a/code/datums/statistics/entities/human_stats.dm +++ /dev/null @@ -1,415 +0,0 @@ -/datum/entity/player_stats/human - var/total_friendly_fire = 0 - var/total_revives = 0 - var/total_lives_saved = 0 - var/total_shots = 0 - var/total_shots_hit = 0 - var/total_screams = 0 - var/list/weapon_stats_list = list() //! indexed list of types /datum/entity/weapon_stats - var/list/job_stats_list = list() //! indexed list of types /datum/entity/job_stats - var/datum/entity/weapon_stats/top_weapon //! reference to /datum/entity/weapon_stats (like tac-shotty) - var/list/datum/entity/statistic/medal/medal_list = list() //! list of all medals earned - -/datum/entity/player_stats/human/Destroy(force) - . = ..() - QDEL_LIST_ASSOC_VAL(weapon_stats_list) - QDEL_LIST_ASSOC_VAL(job_stats_list) - QDEL_NULL(top_weapon) - QDEL_LIST(medal_list) - -/datum/entity/player_stats/human/get_playtime(type) - if(!type) - return ..() - if(type == "Squad Roles") - var/total_squad_time = 0 - for(var/squad_type in GLOB.job_squad_roles) - var/datum/entity/player_stats/job/squad_stat = job_stats_list["[squad_type]"] - if(!squad_stat) // Have not played the squad role yet - continue - total_squad_time += squad_stat.get_playtime() - return total_squad_time - else if(type == "CIC Roles") - var/total_command_time = 0 - for(var/command_type in GLOB.job_command_roles) - var/datum/entity/player_stats/job/command_stat = job_stats_list["[command_type]"] - if(!command_stat) // Have not played the command role yet - continue - total_command_time += command_stat.get_playtime() - return total_command_time - else if(!job_stats_list["[type]"]) // Have not played the role yet - return 0 - var/datum/entity/player_stats/job/S = job_stats_list["[type]"] - return S.get_playtime() - -//****************** -//Stat Procs - setup -//****************** - -/datum/entity/player_stats/human/proc/setup_job_stats(job, noteworthy = TRUE) - if(!job) - return - var/job_key = strip_improper(job) - if(job_stats_list["[job_key]"]) - var/datum/entity/player_stats/job/S = job_stats_list["[job_key]"] - if(!S.display_stat && noteworthy) - S.display_stat = noteworthy - return S - var/datum/entity/player_stats/job/new_stat = new() - new_stat.display_stat = noteworthy - new_stat.player = player - new_stat.name = job_key - job_stats_list["[job_key]"] = new_stat - return new_stat - -/datum/entity/player_stats/human/proc/setup_weapon_stats(weapon, noteworthy = TRUE) - if(!weapon) - return - var/weapon_key = strip_improper(weapon) - if(weapon_stats_list["[weapon_key]"]) - var/datum/entity/weapon_stats/S = weapon_stats_list["[weapon_key]"] - if(!S.display_stat && noteworthy) - S.display_stat = noteworthy - return S - var/datum/entity/weapon_stats/new_stat = new() - new_stat.display_stat = noteworthy - new_stat.player = src - new_stat.name = weapon_key - weapon_stats_list["[weapon_key]"] = new_stat - return new_stat - -//****************** -//Stat Procs - death -//****************** - -/mob/living/carbon/human/track_death_calculations() - if(statistic_exempt || statistic_tracked || !mind || !mind.player_entity) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - if(isnull(human_stats)) - return - var/job_actual = get_actual_job_name(src) - if(!human_stats.round_played) - human_stats.total_rounds_played++ - human_stats.round_played = TRUE - human_stats.total_playtime += life_time_total - human_stats.track_job_playtime(job_actual, life_time_total) - human_stats.recalculate_top_weapon() - human_stats.recalculate_nemesis() - ..() - -/datum/entity/player_stats/human/recalculate_nemesis() - for(var/job_statistic in job_stats_list) - var/datum/entity/player_stats/job/job_entity = job_stats_list[job_statistic] - job_entity.recalculate_nemesis() - ..() - -/datum/entity/player_stats/human/proc/recalculate_top_weapon() - for(var/statistics in weapon_stats_list) - var/datum/entity/weapon_stats/stat_entity = weapon_stats_list[statistics] - if(!top_weapon) - top_weapon = stat_entity - continue - if(stat_entity.total_kills > top_weapon.total_kills) - top_weapon = stat_entity - -/datum/entity/player_stats/human/proc/track_job_playtime(job, time = 0) - if(!job) - return - var/datum/entity/player_stats/job/S = setup_job_stats(job) - if(!S) - return - if(!S.round_played) - S.total_rounds_played++ - S.round_played = TRUE - S.total_playtime += time - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job) - R.total_playtime += time - -/datum/entity/player_stats/human/count_personal_death(job) - var/datum/entity/player_stats/job/S = setup_job_stats(job) - S.total_deaths++ - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job) - R.total_deaths++ - -//****************** -//Stat Procs - kills -//****************** - -/datum/entity/player_stats/human/count_personal_human_kill(job_name, cause, job) - var/datum/entity/player_stats/job/S = setup_job_stats(job) - S.count_human_kill(job_name, cause) - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job) - R.count_human_kill(job_name, cause) - if(cause) - var/datum/entity/weapon_stats/W = setup_weapon_stats(cause) - W.count_human_kill(job_name) - if(GLOB.round_statistics) - var/datum/entity/weapon_stats/R = GLOB.round_statistics.setup_weapon_stats(cause) - R.count_human_kill(job_name) - -/datum/entity/player_stats/human/count_personal_xeno_kill(caste_type, cause, job) - var/datum/entity/player_stats/job/S = setup_job_stats(job) - S.count_xeno_kill(caste_type, cause) - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job) - R.count_xeno_kill(caste_type, cause) - if(cause) - var/datum/entity/weapon_stats/W = setup_weapon_stats(cause) - W.count_xeno_kill(caste_type) - if(GLOB.round_statistics) - var/datum/entity/weapon_stats/R = GLOB.round_statistics.setup_weapon_stats(cause) - R.count_xeno_kill(caste_type) - -/datum/entity/player_stats/human/count_human_kill(job_name, cause, job) - if(!job_name) - return - if(cause) - var/datum/entity/weapon_stats/W = setup_weapon_stats(cause) - W.total_kills++ - if(GLOB.round_statistics) - var/datum/entity/weapon_stats/R = GLOB.round_statistics.setup_weapon_stats(cause) - R.total_kills++ - recalculate_top_weapon() - ..() - -/datum/entity/player_stats/human/count_xeno_kill(job_name, cause, caste) - if(!job_name) - return - if(cause) - var/datum/entity/weapon_stats/W = setup_weapon_stats(cause) - W.total_kills++ - if(GLOB.round_statistics) - var/datum/entity/weapon_stats/R = GLOB.round_statistics.setup_weapon_stats(cause) - R.total_kills++ - recalculate_top_weapon() - ..() - -//***************** -//Mob Procs - minor -//***************** - -/datum/entity/player_stats/human/count_personal_niche_stat(niche_name, amount = 1, job) - var/datum/entity/player_stats/job/S = setup_job_stats(job) - S.count_niche_stat(niche_name, amount) - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job) - R.count_niche_stat(niche_name, amount) - -/datum/entity/player_stats/human/count_niche_stat(niche_name, amount = 1, job, weapon) - if(!niche_name) - return - if(weapon) - var/datum/entity/weapon_stats/W = setup_weapon_stats(weapon) - W.count_niche_stat(niche_name, amount) - if(GLOB.round_statistics) - var/datum/entity/weapon_stats/R = GLOB.round_statistics.setup_weapon_stats(weapon) - R.count_niche_stat(niche_name, amount) - recalculate_top_weapon() - ..() - -/datum/entity/player_stats/human/count_personal_steps_walked(job, amount = 1) - if(!job) - return - var/datum/entity/player_stats/job/S = setup_job_stats(job, FALSE) - S.steps_walked += amount - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job, FALSE) - R.steps_walked += amount - -/mob/living/carbon/human/track_steps_walked(amount = 1) - if(statistic_exempt || !client || !ishuman(src) || !mind) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - if(isnull(human_stats)) - return - human_stats.steps_walked += amount - var/job_actual = get_actual_job_name(src) - if(job_actual) - human_stats.count_personal_steps_walked(job_actual, amount) - -/datum/entity/player_stats/human/proc/count_weapon_hit(weapon, amount = 1) - if(!weapon) - return - var/datum/entity/weapon_stats/S = setup_weapon_stats(weapon) - if(isnull(S.total_hits)) - S.total_hits = 0 - S.total_hits += amount - if(GLOB.round_statistics) - var/datum/entity/weapon_stats/R = GLOB.round_statistics.setup_weapon_stats(weapon) - R.total_hits +=amount - -/mob/proc/track_hit(weapon, amount = 1) - if(statistic_exempt || !client || !ishuman(src) || !mind) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - if(isnull(human_stats)) - return - human_stats.count_weapon_hit(weapon, amount) - -/datum/entity/player_stats/human/proc/count_weapon_shot(weapon, amount = 1) - if(!weapon) - return - var/datum/entity/weapon_stats/S = setup_weapon_stats(weapon) - if(isnull(S.total_shots)) - S.total_shots = 0 - S.total_shots += amount - if(GLOB.round_statistics) - var/datum/entity/weapon_stats/R = GLOB.round_statistics.setup_weapon_stats(weapon) - R.total_shots +=amount - -/datum/entity/player_stats/human/proc/count_personal_shot(job, amount = 1) - if(!job) - return - var/datum/entity/player_stats/job/S = setup_job_stats(job) - if(isnull(S.total_shots)) - S.total_shots = 0 - S.total_shots += amount - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job) - R.total_shots += amount - -/mob/proc/track_shot(weapon, amount = 1) - if(statistic_exempt || !client || !ishuman(src) || !mind) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - if(isnull(human_stats)) - return - human_stats.total_shots += amount - human_stats.count_weapon_shot(weapon, amount) - human_stats.count_personal_shot(job, amount) - -/datum/entity/player_stats/human/proc/count_weapon_shot_hit(weapon, amount = 1) - if(!weapon) - return - var/datum/entity/weapon_stats/S = setup_weapon_stats(weapon) - if(isnull(S.total_shots_hit)) - S.total_shots_hit = 0 - S.total_shots_hit += amount - if(GLOB.round_statistics) - var/datum/entity/weapon_stats/R = GLOB.round_statistics.setup_weapon_stats(weapon) - R.total_shots_hit += amount - -/datum/entity/player_stats/human/proc/count_personal_shot_hit(job, amount = 1) - if(!job) - return - var/datum/entity/player_stats/job/S = setup_job_stats(job) - if(isnull(S.total_shots_hit)) - S.total_shots_hit = 0 - S.total_shots_hit += amount - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job) - R.total_shots_hit += amount - -/mob/proc/track_shot_hit(weapon, shot_mob, amount = 1) - if(statistic_exempt || !client || !ishuman(src) || !mind) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - if(isnull(human_stats)) - return - human_stats.total_shots_hit += amount - human_stats.count_weapon_shot_hit(weapon, amount) - human_stats.count_personal_shot_hit(job, amount) - if(GLOB.round_statistics) - GLOB.round_statistics.total_projectiles_hit += amount - if(shot_mob) - if(ishuman(shot_mob)) - GLOB.round_statistics.total_projectiles_hit_human += amount - else if(isxeno(shot_mob)) - GLOB.round_statistics.total_projectiles_hit_xeno += amount - -/datum/entity/player_stats/human/proc/count_weapon_friendly_fire(weapon, amount = 1) - if(!weapon) - return - var/datum/entity/weapon_stats/S = setup_weapon_stats(weapon) - if(isnull(S.total_friendly_fire)) - S.total_friendly_fire = 0 - S.total_friendly_fire += amount - if(GLOB.round_statistics) - var/datum/entity/weapon_stats/R = GLOB.round_statistics.setup_weapon_stats(weapon) - R.total_friendly_fire += amount - -/datum/entity/player_stats/human/proc/count_personal_friendly_fire(job, amount = 1) - if(!job) - return - var/datum/entity/player_stats/job/S = setup_job_stats(job) - if(isnull(S.total_friendly_fire)) - S.total_friendly_fire = 0 - S.total_friendly_fire += amount - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job) - R.total_friendly_fire += amount - -/mob/proc/track_friendly_fire(weapon, amount = 1) - if(statistic_exempt || !client || !ishuman(src) || !mind) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - if(isnull(human_stats)) - return - human_stats.total_friendly_fire++ - human_stats.count_weapon_friendly_fire(weapon, amount) - human_stats.count_personal_friendly_fire(job, amount) - -/datum/entity/player_stats/human/proc/count_personal_revive(job, amount = 1) - if(!job) - return - var/datum/entity/player_stats/job/S = setup_job_stats(job) - if(isnull(S.total_revives)) - S.total_revives = 0 - S.total_revives += amount - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job) - R.total_revives += amount - -/mob/proc/track_revive(job, amount = 1) - if(statistic_exempt || !client || !ishuman(src) || !mind) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - if(isnull(human_stats)) - return - human_stats.total_revives += amount - human_stats.count_personal_revive(job, amount) - -/datum/entity/player_stats/human/proc/count_personal_life_saved(job, amount = 1) - if(!job) - return - var/datum/entity/player_stats/job/S = setup_job_stats(job) - if(isnull(S.total_lives_saved)) - S.total_lives_saved = 0 - S.total_lives_saved += amount - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job) - R.total_lives_saved += amount - -/mob/proc/track_life_saved(job, amount = 1) - if(statistic_exempt || !client || !ishuman(src) || !mind) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - if(isnull(human_stats)) - return - human_stats.total_lives_saved += amount - human_stats.count_personal_life_saved(job, amount) - -/datum/entity/player_stats/human/proc/count_personal_scream(job, amount = 1) - if(!job) - return - var/datum/entity/player_stats/job/S = setup_job_stats(job) - if(isnull(S.total_screams)) - S.total_screams = 0 - S.total_screams += amount - if(GLOB.round_statistics) - var/datum/entity/player_stats/job/R = GLOB.round_statistics.setup_job_stats(job) - R.total_screams += amount - -/mob/proc/track_scream(job, amount = 1) - if(statistic_exempt || !client || !ishuman(src) || !mind) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - if(isnull(human_stats)) - return - if(isnull(human_stats.total_screams)) - human_stats.total_screams = 0 - human_stats.total_screams++ - human_stats.count_personal_scream(job, amount) diff --git a/code/datums/statistics/entities/job_stats.dm b/code/datums/statistics/entities/job_stats.dm deleted file mode 100644 index 199c2adb3160..000000000000 --- a/code/datums/statistics/entities/job_stats.dm +++ /dev/null @@ -1,8 +0,0 @@ -/datum/entity/player_stats/job - var/name - var/total_friendly_fire - var/total_revives - var/total_lives_saved - var/total_shots - var/total_shots_hit - var/total_screams diff --git a/code/datums/statistics/entities/map_stats.dm b/code/datums/statistics/entities/map_stats.dm index ec3ebb79b448..67d9b7c71e72 100644 --- a/code/datums/statistics/entities/map_stats.dm +++ b/code/datums/statistics/entities/map_stats.dm @@ -1,15 +1,14 @@ -/datum/entity/statistic/map +/datum/entity/statistic_map var/map_name var/total_rounds = 0 var/total_hijacks = 0 - var/total_marine_victories = 0 - var/total_marine_majors = 0 - var/total_xeno_victories = 0 - var/total_xeno_majors = 0 - var/total_draws = 0 + var/total_victories + var/list/victories + +BSQL_PROTECT_DATUM(/datum/entity/statistic_map) /datum/entity_meta/statistic_map - entity_type = /datum/entity/statistic/map + entity_type = /datum/entity/statistic_map table_name = "maps" key_field = "map_name" field_types = list( @@ -17,10 +16,15 @@ "total_rounds" = DB_FIELDTYPE_BIGINT, "total_hijacks" = DB_FIELDTYPE_BIGINT, - "total_marine_victories" = DB_FIELDTYPE_BIGINT, - "total_marine_majors" = DB_FIELDTYPE_BIGINT, - "total_xeno_victories" = DB_FIELDTYPE_BIGINT, - "total_xeno_majors" = DB_FIELDTYPE_BIGINT, - "total_draws" = DB_FIELDTYPE_BIGINT + "total_victories" = DB_FIELDTYPE_STRING_MAX, ) +/datum/entity_meta/statistic_map/map(datum/entity/statistic_map/map_entity, list/values) + ..() + if(values["total_victories"]) + map_entity.victories = json_decode(values["total_victories"]) + +/datum/entity_meta/statistic_map/unmap(datum/entity/statistic_map/map_entity) + . = ..() + if(length(map_entity.victories)) + .["total_victories"] = json_encode(map_entity.victories) diff --git a/code/datums/statistics/entities/medal_stats.dm b/code/datums/statistics/entities/medal_stats.dm index c5684e3cd9a4..7b3dcaeaafd2 100644 --- a/code/datums/statistics/entities/medal_stats.dm +++ b/code/datums/statistics/entities/medal_stats.dm @@ -1,18 +1,18 @@ -/datum/entity/statistic/medal +/datum/entity/statistic_medal var/player_id var/round_id - var/medal_type var/recipient_name var/recipient_role var/citation - var/giver_name var/giver_player_id +BSQL_PROTECT_DATUM(/datum/entity/statistic_medal) + /datum/entity_meta/statistic_medal - entity_type = /datum/entity/statistic/medal - table_name = "log_player_statistic_medal" + entity_type = /datum/entity/statistic_medal + table_name = "player_statistic_medal" field_types = list( "player_id" = DB_FIELDTYPE_BIGINT, "round_id" = DB_FIELDTYPE_BIGINT, @@ -23,10 +23,10 @@ "citation" = DB_FIELDTYPE_STRING_MAX, "giver_name" = DB_FIELDTYPE_STRING_LARGE, - "giver_player_id" = DB_FIELDTYPE_BIGINT + "giver_player_id" = DB_FIELDTYPE_BIGINT, ) -/datum/view_record/medal_view +/datum/view_record/statistic_medal var/player_id var/round_id var/medal_type @@ -37,9 +37,9 @@ var/giver_player_id var/id -/datum/entity_view_meta/medal_view - root_record_type = /datum/entity/statistic/medal - destination_entity = /datum/view_record/medal_view +/datum/entity_view_meta/statistic_medal_ordered + root_record_type = /datum/entity/statistic_medal + destination_entity = /datum/view_record/statistic_medal fields = list( "player_id", "round_id", @@ -52,16 +52,17 @@ "id", ) -/datum/entity/player_entity/proc/track_medal_earned(new_medal_type, mob/new_recipient, new_recipient_role, new_citation, mob/giver) + +/datum/player_entity/proc/track_medal_earned(new_medal_type, mob/new_recipient, new_recipient_role, new_citation, mob/giver) if(!new_medal_type || !new_recipient || new_recipient.statistic_exempt || !new_recipient_role || !new_citation || !giver) return - var/datum/entity/statistic/medal/new_medal = DB_ENTITY(/datum/entity/statistic/medal) - var/datum/entity/player/player_entity = get_player_from_key(new_recipient.persistent_ckey) + var/datum/entity/statistic_medal/new_medal = DB_ENTITY(/datum/entity/statistic_medal) + var/datum/entity/player/player_entity = get_player_from_key(new_recipient.ckey) if(player_entity) new_medal.player_id = player_entity.id - new_medal.round_id = SSperf_logging.round.id + new_medal.round_id = SSperf_logging.round?.id new_medal.medal_type = new_medal_type new_medal.recipient_name = new_recipient.real_name new_medal.recipient_role = new_recipient_role @@ -73,56 +74,30 @@ if(giver_player) new_medal.giver_player_id = giver_player.id + var/datum/entity/player/recipient_player = get_player_from_key(new_recipient.ckey) + if(recipient_player) + track_statistic_earned(new_recipient.faction, STATISTICS_MEDALS, 1, recipient_player) + + statistics_medals += new_medal new_medal.save() new_medal.detach() - if (isxeno(new_recipient)) - var/datum/entity/player_stats/xeno/xeno_stats = setup_xeno_stats() - xeno_stats.count_niche_stat(STATISTICS_NICHE_MEDALS, 1, new_recipient_role) - xeno_stats.medal_list.Insert(1, new_medal) - else - var/datum/entity/player_stats/human/human_stats = setup_human_stats() - human_stats.count_niche_stat(STATISTICS_NICHE_MEDALS, 1, new_recipient_role) - human_stats.medal_list.Insert(1, new_medal) - -/datum/entity/player_entity/proc/untrack_medal_earned(medal_type, mob/recipient, citation) +/datum/player_entity/proc/untrack_medal_earned(medal_type, mob/recipient, citation) if(!medal_type || !recipient || recipient.statistic_exempt || !citation) return FALSE if(!check_rights(R_MOD)) return FALSE - // Remove the stats for the job/caste, individual, and the stat's list of medals - var/round_id = SSperf_logging.round.id - if (isxeno(recipient)) - // Xeno jellies - var/mob/living/carbon/xenomorph/xeno = recipient - var/caste = xeno.caste_type - var/datum/entity/player_stats/xeno/xeno_stats = setup_xeno_stats() - xeno_stats.count_niche_stat(STATISTICS_NICHE_MEDALS, -1, caste) - - for(var/datum/entity/statistic/medal/medal as anything in xeno_stats.medal_list) - if(medal.round_id == round_id && medal.recipient_name == recipient.real_name && medal.medal_type == medal_type && medal.citation == citation) - xeno_stats.medal_list.Remove(medal) - medal.delete() - break - else - // Marine medals - var/rank - var/weak_ref_recipient = WEAKREF(recipient) - for(var/list/marine_manifest_list in list(GLOB.data_core.general)) - for(var/datum/data/record/record in marine_manifest_list) - if(record.fields["ref"] == weak_ref_recipient) - rank = record.fields["rank"] - break - var/datum/entity/player_stats/human/human_stats = setup_human_stats() - human_stats.count_niche_stat(STATISTICS_NICHE_MEDALS, -1, rank) - - for(var/datum/entity/statistic/medal/medal as anything in human_stats.medal_list) - if(medal.round_id == round_id && medal.recipient_name == recipient.real_name && medal.medal_type == medal_type && medal.citation == citation) - human_stats.medal_list.Remove(medal) - medal.delete() - break - return TRUE + var/datum/entity/player/recipient_player = get_player_from_key(recipient.ckey) + if(recipient_player) + track_statistic_earned(recipient.faction, STATISTICS_MEDALS, 1, recipient_player) + var/round_id = SSperf_logging.round?.id + for(var/datum/entity/statistic_medal/new_medal as anything in statistics_medals) + if(new_medal.round_id == round_id && new_medal.recipient_name == recipient.real_name && new_medal.medal_type == medal_type && new_medal.citation == citation) + statistics_medals -= new_medal + new_medal.delete() + break + return TRUE diff --git a/code/datums/statistics/entities/panel_stats.dm b/code/datums/statistics/entities/panel_stats.dm index c62925673622..24dbd88e7de1 100644 --- a/code/datums/statistics/entities/panel_stats.dm +++ b/code/datums/statistics/entities/panel_stats.dm @@ -1,739 +1,193 @@ -//******************************************************* -//*******************STAT PANEL************************** -//******************************************************* - - -/datum/entity/player_entity/proc/show_statistics(mob/user, datum/entity/statistic/round/viewing_round = GLOB.round_statistics, update_data = FALSE) - if(update_data) - update_panel_data(GLOB.round_statistics) - ui_interact(user) - -/datum/entity/player_entity/proc/ui_interact(mob/user, ui_key = "statistics", datum/nanoui/ui, force_open = 1) - data["menu"] = menu - data["subMenu"] = subMenu - data["dataMenu"] = dataMenu - - ui = SSnano.nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) - - if(!ui) - ui = new(user, src, ui_key, "cm_stat_panel.tmpl", "Statistics", 450, 700, null, -1) - ui.set_initial_data(data) - ui.open() - -/datum/entity/player_entity/Topic(href, href_list) - var/mob/user = usr - user.set_interaction(src) - - if(href_list["menu"]) - menu = href_list["menu"] - if(href_list["subMenu"]) - subMenu = href_list["subMenu"] - if(href_list["dataMenu"]) - dataMenu = href_list["dataMenu"] - - SSnano.nanomanager.update_uis(src) - -/datum/entity/player_entity/proc/check_eye() - return - -//******************************************************* -//*******************KILL PANEL************************** -//******************************************************* - - -/datum/entity/statistic/round/proc/show_kill_feed(mob/user) - tgui_interact(user) - -/datum/entity/statistic/round/tgui_interact(mob/user, datum/tgui/ui) +/datum/player_entity/tgui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, "KillPanel", "Killfeed") + ui = new(user, src, "Statistic", "Statistic") ui.open() - ui.set_autoupdate(FALSE) + ui.set_autoupdate(TRUE) -/datum/entity/statistic/round/ui_state(mob/user) +/datum/player_entity/ui_state(mob/user) return GLOB.always_state -/datum/entity/statistic/round/ui_data(mob/user) - var/list/data = list() - - data["death_data"] = death_data - - return data - -/datum/entity/statistic/round/proc/check_eye() - return - -//******************************************************* -//*******************PLAYER DATA************************* -//******************************************************* - -/datum/entity/player_entity/proc/update_panel_data(datum/entity/statistic/round/viewing_round = GLOB.round_statistics) - data["current_time"] = worldtime2text() +/datum/player_entity/ui_status(mob/user, datum/ui_state/state) + . = ..() + if(isliving(user)) + return UI_CLOSE +/datum/player_entity/ui_data(mob/user, datum/entity/statistic_round/viewing_round = GLOB.round_statistics) + . = list() + .["data_tabs"] = list() if(viewing_round) - viewing_round.update_panel_data() - data["round"] = viewing_round.round_data["round"] + .["round"] = viewing_round.cached_tgui_data + .["data_tabs"] += "Round" - if(player_stats["human"]) - var/datum/entity/player_stats/human/H = player_stats["human"] - var/list/humans_killed = list() - var/list/xenos_killed = list() + if(length(statistics_medals)) var/list/medal_list = list() - var/list/death_list = list() - var/list/weapon_stats_list = list() - var/list/job_stats_list = list() - var/list/niche_stats_list = list() - var/list/top_weapon = null - var/list/human_nemesis = null - - if(H.nemesis) - human_nemesis = list("name" = H.nemesis.name, "value" = H.nemesis.value) - - if(H.top_weapon) - top_weapon = list( - "name" = sanitize(H.top_weapon.name), - "total_kills" = H.top_weapon.total_kills, - "total_hits" = H.top_weapon.total_hits, - "total_shots" = H.top_weapon.total_shots, - "total_shots_hit" = H.top_weapon.total_shots_hit, - "total_friendly_fire" = H.top_weapon.total_friendly_fire - ) - - for(var/iteration in H.humans_killed) - var/datum/entity/statistic/S = H.humans_killed[iteration] - humans_killed += list(list("name" = S.name, "value" = S.value)) - - for(var/iteration in H.xenos_killed) - var/datum/entity/statistic/S = H.xenos_killed[iteration] - xenos_killed += list(list("name" = S.name, "value" = S.value)) - - for(var/iteration in H.niche_stats) - var/datum/entity/statistic/S = H.niche_stats[iteration] - niche_stats_list += list(list("name" = S.name, "value" = S.value)) - - for(var/datum/entity/statistic/medal/S in H.medal_list) + for(var/datum/entity/statistic_medal/medal as anything in statistics_medals) medal_list += list(list( - "medal_type" = sanitize(S.medal_type), - "recipient" = sanitize(S.recipient_name), - "recipient_job" = sanitize(S.recipient_role), - "citation" = sanitize(S.citation), - "giver" = sanitize(S.giver_name) - )) - - for(var/datum/entity/statistic/death/S in H.death_list) - var/list/damage_list = list() - if(S.total_brute) - damage_list += list(list("name" = "brute", "value" = S.total_brute)) - if(S.total_burn) - damage_list += list(list("name" = "burn", "value" = S.total_burn)) - if(S.total_oxy) - damage_list += list(list("name" = "oxy", "value" = S.total_oxy)) - if(S.total_tox) - damage_list += list(list("name" = "tox", "value" = S.total_tox)) - death_list += list(list( - "mob_name" = sanitize(S.mob_name), - "job_name" = S.role_name, - "area_name" = sanitize_area(S.area_name), - "cause_name" = sanitize(S.cause_name), - "total_kills" = S.total_kills, - "total_damage" = damage_list, - "time_of_death" = duration2text(S.time_of_death), - "total_time_alive" = duration2text(S.total_time_alive), - "total_damage_taken" = S.total_damage_taken, - "x" = S.x, - "y" = S.y, - "z" = S.z - )) - - for(var/iteration in H.weapon_stats_list) - var/datum/entity/weapon_stats/S = H.weapon_stats_list[iteration] - if(!S.display_stat) - continue - var/list/weapon_humans_killed = list() - var/list/weapon_xenos_killed = list() - var/list/weapon_niche_stats_list = list() - - for(var/sub_iteration in S.humans_killed) - var/datum/entity/statistic/D = S.humans_killed[sub_iteration] - weapon_humans_killed += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.xenos_killed) - var/datum/entity/statistic/D = S.xenos_killed[sub_iteration] - weapon_xenos_killed += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.niche_stats) - var/datum/entity/statistic/D = S.niche_stats[sub_iteration] - weapon_niche_stats_list += list(list("name" = D.name, "value" = D.value)) - - weapon_stats_list += list(list( - "name" = sanitize(S.name), - "total_kills" = S.total_kills, - "total_hits" = S.total_hits, - "total_shots" = S.total_shots, - "total_shots_hit" = S.total_shots_hit, - "total_friendly_fire" = S.total_friendly_fire, - "humans_killed" = weapon_humans_killed, - "xenos_killed" = weapon_xenos_killed, - "niche_stats" = weapon_niche_stats_list - )) - - for(var/iteration in H.job_stats_list) - var/datum/entity/player_stats/job/S = H.job_stats_list[iteration] - if(!S.display_stat) - continue - var/list/job_humans_killed = list() - var/list/job_xenos_killed = list() - var/list/job_death_list = list() - var/list/job_niche_stats_list = list() - var/list/job_nemesis = null - - if(S.nemesis) - job_nemesis = list("name" = S.nemesis.name, "value" = S.nemesis.value) - - for(var/sub_iteration in S.humans_killed) - var/datum/entity/statistic/D = S.humans_killed[sub_iteration] - job_humans_killed += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.xenos_killed) - var/datum/entity/statistic/D = S.xenos_killed[sub_iteration] - job_xenos_killed += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.niche_stats) - var/datum/entity/statistic/D = S.niche_stats[sub_iteration] - job_niche_stats_list += list(list("name" = D.name, "value" = D.value)) - - for(var/datum/entity/statistic/death/DS in S.death_list) - var/list/damage_list = list() - if(DS.total_brute) - damage_list += list(list("name" = "brute", "value" = DS.total_brute)) - if(DS.total_burn) - damage_list += list(list("name" = "burn", "value" = DS.total_burn)) - if(DS.total_oxy) - damage_list += list(list("name" = "oxy", "value" = DS.total_oxy)) - if(DS.total_tox) - damage_list += list(list("name" = "tox", "value" = DS.total_tox)) - death_list += list(list( - "mob_name" = sanitize(DS.mob_name), - "job_name" = DS.role_name, - "area_name" = sanitize_area(DS.area_name), - "cause_name" = sanitize(DS.cause_name), - "total_kills" = DS.total_kills, - "total_damage" = damage_list, - "time_of_death" = duration2text(DS.time_of_death), - "total_time_alive" = duration2text(DS.total_time_alive), - "total_damage_taken" = DS.total_damage_taken, - "x" = DS.x, - "y" = DS.y, - "z" = DS.z - )) - - job_stats_list += list(list( - "name" = S.name, - "total_kills" = S.total_kills, - "total_deaths" = S.total_deaths, - "total_playtime" = duration2text(S.total_playtime), - "total_rounds_played" = S.total_rounds_played, - "steps_walked" = S.steps_walked, - "total_friendly_fire" = S.total_friendly_fire, - "total_revives" = S.total_revives, - "total_lives_saved" = S.total_lives_saved, - "total_shots" = S.total_shots, - "total_shots_hit" = S.total_shots_hit, - "total_screams" = S.total_screams, - "nemesis" = job_nemesis, - "humans_killed" = job_humans_killed, - "xenos_killed" = job_xenos_killed, - "job_death_list" = job_death_list, - "niche_stats" = job_niche_stats_list + "round_id" = "[medal.round_id]", + "medal_type" = medal.medal_type, + "recipient" = sanitize(medal.recipient_name), + "recipient_job" = medal.recipient_role, + "citation" = sanitize(medal.citation), + "giver" = sanitize(medal.giver_name), )) - data["human"] = list( - "total_kills" = H.total_kills, - "total_deaths" = H.total_deaths, - "total_playtime" = duration2text(H.total_playtime), - "total_rounds_played" = H.total_rounds_played, - "steps_walked" = H.steps_walked, - "total_friendly_fire" = H.total_friendly_fire, - "total_revives" = H.total_revives, - "total_lives_saved" = H.total_lives_saved, - "total_shots" = H.total_shots, - "total_shots_hit" = H.total_shots_hit, - "total_screams" = H.total_screams, - "nemesis" = human_nemesis, - "humans_killed" = humans_killed, - "xenos_killed" = xenos_killed, - "medal_list" = medal_list, - "death_list" = death_list, - "weapon_stats_list" = weapon_stats_list, - "job_stats_list" = job_stats_list, - "niche_stats" = niche_stats_list, - "top_weapon" = top_weapon - ) + .["medals"] = medal_list + .["data_tabs"] += "Medals" - if(player_stats["xeno"]) - var/datum/entity/player_stats/xeno/H = player_stats["xeno"] - var/list/humans_killed = list() - var/list/xenos_killed = list() - var/list/medal_list = list() + .["factions"] = list() + for(var/faction_to_get in statistics_groups) + var/datum/grouped_statistic/statistics_group = statistics_groups[faction_to_get] + var/list/nemesis = list() var/list/death_list = list() - var/list/caste_stats_list = list() - var/list/niche_stats_list = list() - var/list/top_caste = null - var/list/xeno_nemesis = null - - if(H.nemesis) - xeno_nemesis = list("name" = H.nemesis.name, "value" = H.nemesis.value) + var/list/top_statistics = list() + var/list/total_statistics = list() + var/list/statistics_list = list() + if(statistics_group.nemesis) + nemesis = list("name" = statistics_group.nemesis.nemesis_name, "value" = statistics_group.nemesis.value) - if(H.top_caste) - top_caste = list( - "name" = H.top_caste.name, - "total_kills" = H.top_caste.total_kills, - "total_deaths" = H.top_caste.total_deaths, - "total_playtime" = duration2text(H.top_caste.total_playtime), - "total_rounds_played" = H.top_caste.total_rounds_played, - ) + for(var/datum/entity/statistic_death/statistic_death as anything in statistics_group.statistic_deaths) + if(length(death_list) >= STATISTICS_DEATH_LIST_LEN) + break - for(var/iteration in H.humans_killed) - var/datum/entity/statistic/S = H.humans_killed[iteration] - humans_killed += list(list("name" = S.name, "value" = S.value)) + var/list/damage_list = list() + if(statistic_death.total_brute) + damage_list += list(list("name" = "brute", "value" = statistic_death.total_brute)) - for(var/iteration in H.xenos_killed) - var/datum/entity/statistic/S = H.xenos_killed[iteration] - xenos_killed += list(list("name" = S.name, "value" = S.value)) + if(statistic_death.total_burn) + damage_list += list(list("name" = "burn", "value" = statistic_death.total_burn)) - for(var/iteration in H.niche_stats) - var/datum/entity/statistic/S = H.niche_stats[iteration] - niche_stats_list += list(list("name" = S.name, "value" = S.value)) + if(statistic_death.total_oxy) + damage_list += list(list("name" = "oxy", "value" = statistic_death.total_oxy)) - for(var/datum/entity/statistic/medal/S in H.medal_list) - medal_list += list(list( - "medal_type" = sanitize(S.medal_type), - "recipient" = sanitize(S.recipient_name), - "recipient_job" = sanitize(S.recipient_role), - "citation" = sanitize(S.citation), - "giver" = sanitize(S.giver_name) - )) + if(statistic_death.total_tox) + damage_list += list(list("name" = "tox", "value" = statistic_death.total_tox)) - for(var/datum/entity/statistic/death/S in H.death_list) - var/list/damage_list = list() - if(S.total_brute) - damage_list += list(list("name" = "brute", "value" = S.total_brute)) - if(S.total_burn) - damage_list += list(list("name" = "burn", "value" = S.total_burn)) - if(S.total_oxy) - damage_list += list(list("name" = "oxy", "value" = S.total_oxy)) - if(S.total_tox) - damage_list += list(list("name" = "tox", "value" = S.total_tox)) death_list += list(list( - "mob_name" = sanitize(S.mob_name), - "job_name" = S.role_name, - "area_name" = sanitize_area(S.area_name), - "cause_name" = sanitize(S.cause_name), - "total_kills" = S.total_kills, + "mob_name" = sanitize(statistic_death.mob_name), + "job_name" = statistic_death.role_name, + "area_name" = sanitize_area(statistic_death.area_name), + "cause_name" = sanitize(statistic_death.cause_name), + "total_kills" = statistic_death.total_kills, "total_damage" = damage_list, - "time_of_death" = duration2text(S.time_of_death), - "total_time_alive" = duration2text(S.total_time_alive), - "total_damage_taken" = S.total_damage_taken, - "x" = S.x, - "y" = S.y, - "z" = S.z + "time_of_death" = duration2text(statistic_death.time_of_death), + "total_time_alive" = duration2text(statistic_death.total_time_alive), + "total_damage_taken" = statistic_death.total_damage_taken, + "x" = statistic_death.x, + "y" = statistic_death.y, + "z" = statistic_death.z, )) - for(var/iteration in H.caste_stats_list) - var/datum/entity/player_stats/caste/S = H.caste_stats_list[iteration] - if(!S.display_stat) - continue - var/list/caste_abilities_used = list() - var/list/caste_humans_killed = list() - var/list/caste_xenos_killed = list() - var/list/caste_death_list = list() - var/list/caste_niche_stats_list = list() - var/list/caste_nemesis = null - - if(S.nemesis) - caste_nemesis = list("name" = S.nemesis.name, "value" = S.nemesis.value) - - for(var/sub_iteration in S.abilities_used) - var/datum/entity/statistic/D = S.abilities_used[sub_iteration] - caste_abilities_used += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.humans_killed) - var/datum/entity/statistic/D = S.humans_killed[sub_iteration] - caste_humans_killed += list(list("name" = D.name, "value" = D.value)) + for(var/group_subtype in statistics_group.statistics_infos) + var/list/statistic_info = list() + var/datum/player_statistic/statistics_info = statistics_group.statistics_infos[group_subtype] + if(statistics_info.statistic_name == STATISTIC_TYPE_CASTE || statistics_info.statistic_name == STATISTIC_TYPE_JOB) + for(var/subtype in statistics_info.total_statistic) + total_statistics += list(list("name" = subtype, "value" = statistics_info.total_statistic[subtype])) + + if(statistics_info.top_statistic) + var/list/top_statistic_list = list() + var/datum/player_statistic_detail/detail_statistic = statistics_info.top_statistic + for(var/datum/entity/statistic/top_statistic_entity as anything in detail_statistic.statistics) + top_statistic_list += list(list("name" = top_statistic_entity.statistic_name, "value" = top_statistic_entity.value)) + + top_statistics += list(list( + "name" = detail_statistic.detail_name, + "statistics" = top_statistic_list, + )) - for(var/sub_iteration in S.xenos_killed) - var/datum/entity/statistic/D = S.xenos_killed[sub_iteration] - caste_xenos_killed += list(list("name" = D.name, "value" = D.value)) + for(var/statistic_subtype in statistics_info.statistics_details) + var/datum/player_statistic_detail/detail_statistic = statistics_info.statistics_details[statistic_subtype] + var/list/subtype_statistics = list() + var/list/subtype_top_statistics = list() + for(var/datum/entity/statistic/statistic as anything in detail_statistic.statistics) + subtype_statistics += list(list("name" = statistic.statistic_name, "value" = statistic.value)) - for(var/sub_iteration in S.niche_stats) - var/datum/entity/statistic/D = S.niche_stats[sub_iteration] - caste_niche_stats_list += list(list("name" = D.name, "value" = D.value)) + for(var/datum/entity/statistic/statistic as anything in detail_statistic.top_values_statistics) + subtype_top_statistics += list(list("name" = statistic.statistic_name, "value" = statistic.value)) - for(var/datum/entity/statistic/death/DS in S.death_list) - var/list/damage_list = list() - if(DS.total_brute) - damage_list += list(list("name" = "brute", "value" = DS.total_brute)) - if(DS.total_burn) - damage_list += list(list("name" = "burn", "value" = DS.total_burn)) - if(DS.total_oxy) - damage_list += list(list("name" = "oxy", "value" = DS.total_oxy)) - if(DS.total_tox) - damage_list += list(list("name" = "tox", "value" = DS.total_tox)) - death_list += list(list( - "mob_name" = sanitize(DS.mob_name), - "job_name" = DS.role_name, - "area_name" = sanitize_area(DS.area_name), - "cause_name" = sanitize(DS.cause_name), - "total_kills" = DS.total_kills, - "total_damage" = damage_list, - "time_of_death" = duration2text(DS.time_of_death), - "total_time_alive" = duration2text(DS.total_time_alive), - "total_damage_taken" = DS.total_damage_taken, - "x" = DS.x, - "y" = DS.y, - "z" = DS.z + statistic_info += list(list( + "name" = detail_statistic.detail_name, + "statistics" = subtype_statistics, + "top_statistics" = subtype_top_statistics, )) - caste_stats_list += list(list( - "name" = S.name, - "total_kills" = S.total_kills, - "total_hits" = S.total_hits, - "total_deaths" = S.total_deaths, - "total_playtime" = duration2text(S.total_playtime), - "total_rounds_played" = S.total_rounds_played, - "steps_walked" = S.steps_walked, - "nemesis" = caste_nemesis, - "humans_killed" = caste_humans_killed, - "xenos_killed" = caste_xenos_killed, - "death_list" = caste_death_list, - "abilities_used" = caste_abilities_used, - "niche_stats" = caste_niche_stats_list + statistics_list += list(list( + "name" = statistics_info.statistic_name, + "value" = statistic_info, )) - data["xeno"] = list( - "total_kills" = H.total_kills, - "total_deaths" = H.total_deaths, - "total_playtime" = duration2text(H.total_playtime), - "total_rounds_played" = H.total_rounds_played, - "steps_walked" = H.steps_walked, - "total_hits" = H.total_hits, - "nemesis" = xeno_nemesis, - "humans_killed" = humans_killed, - "xenos_killed" = xenos_killed, - "medal_list" = medal_list, - "death_list" = death_list, - "caste_stats_list" = caste_stats_list, - "niche_stats" = niche_stats_list, - "top_caste" = top_caste - ) - -//******************************************************* -//*******************ROUND DATA************************** -//******************************************************* - -/datum/entity/statistic/round/proc/update_panel_data() - var/map_name - if(current_map) - map_name = current_map.name - - var/list/participants_list = list() - var/list/hijack_participants_list = list() - var/list/final_participants_list = list() - var/list/total_deaths_list = list() - var/list/new_death_stats_list = list() - var/list/new_weapon_stats_list = list() - var/list/new_job_stats_list = list() - var/list/new_caste_stats_list = list() - - for(var/iteration in participants) - var/datum/entity/statistic/S = participants[iteration] - participants_list += list(list("name" = S.name, "value" = S.value)) - - for(var/iteration in hijack_participants) - var/datum/entity/statistic/S = hijack_participants[iteration] - hijack_participants_list += list(list("name" = S.name, "value" = S.value)) - - for(var/iteration in final_participants) - var/datum/entity/statistic/S = final_participants[iteration] - final_participants_list += list(list("name" = S.name, "value" = S.value)) - - for(var/iteration in total_deaths) - var/datum/entity/statistic/S = total_deaths[iteration] - total_deaths_list += list(list("name" = S.name, "value" = S.value)) + if(length(total_statistics)) + .["data_tabs"] += statistics_group.group_name + .["factions"][statistics_group.group_name] = list( + "name" = statistics_group.group_name, + "nemesis" = nemesis, + "total_deaths" = length(statistics_group.statistic_deaths), + "death_list" = death_list, + "total_statistics" = total_statistics, + "top_statistics" = top_statistics, + "statistics_list" = statistics_list, + ) - for(var/datum/entity/statistic/death/S in death_stats_list) - if(length(new_death_stats_list) >= STATISTICS_DEATH_LIST_LEN) +/datum/entity/statistic_round/process() + var/list/all_participants_list = list() + var/list/last_deaths_list = list() + + if(length(participants)) + var/list/participants_list = list() + all_participants_list += list(list("name" = "Participants", "value" = participants_list)) + for(var/stat_name in participants) + participants_list += list(list("name" = stat_name, "value" = participants[stat_name])) + + if(length(hijack_participants)) + var/list/hijack_participants_list = list() + all_participants_list += list(list("name" = "Hijack Participants", "value" = hijack_participants_list)) + for(var/stat_name in hijack_participants) + hijack_participants_list += list(list("name" = stat_name, "value" = hijack_participants[stat_name])) + + if(length(final_participants)) + var/list/final_participants_list = list() + all_participants_list += list(list("name" = "Final Participants", "value" = final_participants_list)) + for(var/stat_name in final_participants) + final_participants_list += list(list("name" = stat_name, "value" = final_participants[stat_name])) + + for(var/datum/entity/statistic_death/statistic_death as anything in death_stats_list) + if(length(last_deaths_list) >= STATISTICS_DEATH_LIST_LEN) break var/list/damage_list = list() - if(S.total_brute) - damage_list += list(list("name" = "brute", "value" = S.total_brute)) - if(S.total_burn) - damage_list += list(list("name" = "burn", "value" = S.total_burn)) - if(S.total_oxy) - damage_list += list(list("name" = "oxy", "value" = S.total_oxy)) - if(S.total_tox) - damage_list += list(list("name" = "tox", "value" = S.total_tox)) - - var/new_time_of_death - if(S.time_of_death) - new_time_of_death = duration2text(S.time_of_death) - var/new_total_time_alive - if(S.total_time_alive) - new_total_time_alive = duration2text(S.total_time_alive) - - var/death = list(list( - "mob_name" = sanitize(S.mob_name), - "job_name" = S.role_name, - "area_name" = sanitize_area(S.area_name), - "cause_name" = sanitize(S.cause_name), - "total_kills" = S.total_kills, + if(statistic_death.total_brute) + damage_list += list(list("name" = "brute", "value" = statistic_death.total_brute)) + if(statistic_death.total_burn) + damage_list += list(list("name" = "burn", "value" = statistic_death.total_burn)) + if(statistic_death.total_oxy) + damage_list += list(list("name" = "oxy", "value" = statistic_death.total_oxy)) + if(statistic_death.total_tox) + damage_list += list(list("name" = "tox", "value" = statistic_death.total_tox)) + + last_deaths_list += list(list( + "mob_name" = sanitize(statistic_death.mob_name), + "job_name" = statistic_death.role_name, + "area_name" = sanitize_area(statistic_death.area_name), + "cause_name" = sanitize(statistic_death.cause_name), + "total_kills" = statistic_death.total_kills, "total_damage" = damage_list, - "time_of_death" = new_time_of_death, - "total_time_alive" = new_total_time_alive, - "total_damage_taken" = S.total_damage_taken, - "x" = S.x, - "y" = S.y, - "z" = S.z + "time_of_death" = duration2text(statistic_death.time_of_death), + "total_time_alive" = duration2text(statistic_death.total_time_alive), + "total_damage_taken" = statistic_death.total_damage_taken, + "x" = statistic_death.x, + "y" = statistic_death.y, + "z" = statistic_death.z, )) - if(length(new_death_stats_list) < STATISTICS_DEATH_LIST_LEN) - new_death_stats_list += death - - for(var/iteration in weapon_stats_list) - var/datum/entity/weapon_stats/S = weapon_stats_list[iteration] - if(!S.display_stat) - continue - var/list/weapon_humans_killed = list() - var/list/weapon_xenos_killed = list() - var/list/weapon_niche_stats_list = list() - - for(var/sub_iteration in S.humans_killed) - var/datum/entity/statistic/D = S.humans_killed[sub_iteration] - if(!D) - continue - weapon_humans_killed += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.xenos_killed) - var/datum/entity/statistic/D = S.xenos_killed[sub_iteration] - if(!D) - continue - weapon_xenos_killed += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.niche_stats) - var/datum/entity/statistic/D = S.niche_stats[sub_iteration] - if(!D) - continue - weapon_niche_stats_list += list(list("name" = D.name, "value" = D.value)) - - new_weapon_stats_list += list(list( - "name" = sanitize(S.name), - "total_kills" = S.total_kills, - "total_hits" = S.total_hits, - "total_shots" = S.total_shots, - "total_shots_hit" = S.total_shots_hit, - "total_friendly_fire" = S.total_friendly_fire, - "humans_killed" = weapon_humans_killed, - "xenos_killed" = weapon_xenos_killed, - "niche_stats" = weapon_niche_stats_list - )) - - for(var/iteration in job_stats_list) - var/datum/entity/player_stats/job/S = job_stats_list[iteration] - if(!S.display_stat) - continue - var/list/job_humans_killed = list() - var/list/job_xenos_killed = list() - var/list/job_death_list = list() - var/list/job_niche_stats_list = list() - var/list/job_nemesis = null - - if(S.nemesis) - job_nemesis = list("name" = S.nemesis.name, "value" = S.nemesis.value) - - for(var/sub_iteration in S.humans_killed) - var/datum/entity/statistic/D = S.humans_killed[sub_iteration] - if(!D) - continue - job_humans_killed += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.xenos_killed) - var/datum/entity/statistic/D = S.xenos_killed[sub_iteration] - if(!D) - continue - job_xenos_killed += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.niche_stats) - var/datum/entity/statistic/D = S.niche_stats[sub_iteration] - if(!D) - continue - job_niche_stats_list += list(list("name" = D.name, "value" = D.value)) - - for(var/datum/entity/statistic/death/DS in S.death_list) - var/list/damage_list = list() - if(DS.total_brute) - damage_list += list(list("name" = "brute", "value" = DS.total_brute)) - if(DS.total_burn) - damage_list += list(list("name" = "burn", "value" = DS.total_burn)) - if(DS.total_oxy) - damage_list += list(list("name" = "oxy", "value" = DS.total_oxy)) - if(DS.total_tox) - damage_list += list(list("name" = "tox", "value" = DS.total_tox)) - - var/new_time_of_death - if(DS.time_of_death) - new_time_of_death = duration2text(DS.time_of_death) - var/new_total_time_alive - if(DS.total_time_alive) - new_total_time_alive = duration2text(DS.total_time_alive) - - job_death_list += list(list( - "mob_name" = sanitize(DS.mob_name), - "job_name" = DS.role_name, - "area_name" = sanitize_area(DS.area_name), - "cause_name" = sanitize(DS.cause_name), - "total_kills" = DS.total_kills, - "total_damage" = damage_list, - "time_of_death" = new_time_of_death, - "total_time_alive" = new_total_time_alive, - "total_damage_taken" = DS.total_damage_taken, - "x" = DS.x, - "y" = DS.y, - "z" = DS.z - )) - - new_job_stats_list += list(list( - "name" = S.name, - "total_kills" = S.total_kills, - "total_deaths" = S.total_deaths, - "total_playtime" = duration2text(S.total_playtime), - "total_rounds_played" = S.total_rounds_played, - "steps_walked" = S.steps_walked, - "total_friendly_fire" = S.total_friendly_fire, - "total_revives" = S.total_revives, - "total_lives_saved" = S.total_lives_saved, - "total_shots" = S.total_shots, - "total_shots_hit" = S.total_shots_hit, - "total_screams" = S.total_screams, - "nemesis" = job_nemesis, - "humans_killed" = job_humans_killed, - "xenos_killed" = job_xenos_killed, - "job_death_list" = job_death_list, - "niche_stats" = job_niche_stats_list - )) - - for(var/iteration in caste_stats_list) - var/datum/entity/player_stats/caste/S = caste_stats_list[iteration] - if(!S.display_stat) - continue - var/list/caste_abilities_used = list() - var/list/caste_humans_killed = list() - var/list/caste_xenos_killed = list() - var/list/caste_death_list = list() - var/list/caste_niche_stats_list = list() - var/list/caste_nemesis = null - - if(S.nemesis) - caste_nemesis = list("name" = S.nemesis.name, "value" = S.nemesis.value) - - for(var/sub_iteration in S.abilities_used) - var/datum/entity/statistic/D = S.abilities_used[sub_iteration] - if(!D) - continue - caste_abilities_used += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.humans_killed) - var/datum/entity/statistic/D = S.humans_killed[sub_iteration] - if(!D) - continue - caste_humans_killed += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.xenos_killed) - var/datum/entity/statistic/D = S.xenos_killed[sub_iteration] - if(!D) - continue - caste_xenos_killed += list(list("name" = D.name, "value" = D.value)) - - for(var/sub_iteration in S.niche_stats) - var/datum/entity/statistic/D = S.niche_stats[sub_iteration] - if(!D) - continue - caste_niche_stats_list += list(list("name" = D.name, "value" = D.value)) - - for(var/datum/entity/statistic/death/DS in S.death_list) - var/list/damage_list = list() - if(DS.total_brute) - damage_list += list(list("name" = "brute", "value" = DS.total_brute)) - if(DS.total_burn) - damage_list += list(list("name" = "burn", "value" = DS.total_burn)) - if(DS.total_oxy) - damage_list += list(list("name" = "oxy", "value" = DS.total_oxy)) - if(DS.total_tox) - damage_list += list(list("name" = "tox", "value" = DS.total_tox)) - - var/new_time_of_death - if(DS.time_of_death) - new_time_of_death = duration2text(DS.time_of_death) - var/new_total_time_alive - if(DS.total_time_alive) - new_total_time_alive = duration2text(DS.total_time_alive) - - caste_death_list += list(list( - "mob_name" = sanitize(DS.mob_name), - "job_name" = DS.role_name, - "area_name" = sanitize_area(DS.area_name), - "cause_name" = sanitize(DS.cause_name), - "total_kills" = DS.total_kills, - "total_damage" = damage_list, - "time_of_death" = new_time_of_death, - "total_time_alive" = new_total_time_alive, - "total_damage_taken" = DS.total_damage_taken, - "x" = DS.x, - "y" = DS.y, - "z" = DS.z - )) - - new_caste_stats_list += list(list( - "name" = S.name, - "total_kills" = S.total_kills, - "total_hits" = S.total_hits, - "total_deaths" = S.total_deaths, - "total_playtime" = duration2text(S.total_playtime), - "total_rounds_played" = S.total_rounds_played, - "steps_walked" = S.steps_walked, - "nemesis" = caste_nemesis, - "humans_killed" = caste_humans_killed, - "xenos_killed" = caste_xenos_killed, - "death_list" = caste_death_list, - "abilities_used" = caste_abilities_used, - "niche_stats" = caste_niche_stats_list - )) - - var/new_time_start - if(real_time_start) - new_time_start = time2text(real_time_start) - - var/new_round_length - if(round_length) - new_round_length = duration2text(round_length) - - var/new_hijack_time - if(round_hijack_time) - new_hijack_time = time2text(round_hijack_time) - - var/new_time_end - if(real_time_end) - new_time_end = time2text(real_time_end) - death_data["death_stats_list"] = new_death_stats_list - round_data["round"] = list( - "name" = name, + cached_tgui_data = list( + "name" = round_name, "game_mode" = game_mode, - "map_name" = map_name, + "map_name" = current_map?.map_name, "round_result" = round_result, - "real_time_start" = new_time_start, - "real_time_end" = new_time_end, - "round_length" = new_round_length, - "round_hijack_time" = new_hijack_time, + "real_time_start" = real_time_start ? time2text(real_time_start, "YYYY-MM-DD hh:mm:ss") : 0, + "real_time_end" = real_time_end ? time2text(real_time_end, "YYYY-MM-DD hh:mm:ss") : 0, + "round_length" = round_length ? time2text(round_length, "YYYY-MM-DD hh:mm:ss") : 0, + "round_hijack_time" = round_hijack_time ? duration2text(round_hijack_time) : 0, "end_round_player_population" = end_round_player_population, "total_projectiles_fired" = total_projectiles_fired, "total_projectiles_hit" = total_projectiles_hit, @@ -741,14 +195,10 @@ "total_projectiles_hit_xeno" = total_projectiles_hit_xeno, "total_slashes" = total_slashes, "total_friendly_fire_instances" = total_friendly_fire_instances, + "total_friendly_kills" = total_friendly_kills, "total_huggers_applied" = total_huggers_applied, "total_larva_burst" = total_larva_burst, - "participants" = participants_list, - "hijack_participants" = hijack_participants_list, - "final_participants" = final_participants_list, - "total_deaths" = total_deaths_list, - "death_stats_list" = new_death_stats_list, - "weapon_stats_list" = new_weapon_stats_list, - "job_stats_list" = new_job_stats_list, - "caste_stats_list" = new_caste_stats_list + "participants_list" = all_participants_list, + "total_deaths" = length(death_stats_list), + "death_list" = last_deaths_list, ) diff --git a/code/datums/statistics/entities/player_entity.dm b/code/datums/statistics/entities/player_entity.dm index f0b3d37ede7e..0797d06a8c1c 100644 --- a/code/datums/statistics/entities/player_entity.dm +++ b/code/datums/statistics/entities/player_entity.dm @@ -1,47 +1,255 @@ -#define PREFFILE_VERSION_MIN 3 -#define PREFFILE_VERSION_MAX 3 + +///////////////////////////////////////////////////////////////////////////////////// +//Statistic entity /datum/entity/statistic - var/name = null - var/value = null - -/datum/entity/player_entity - var/name - var/ckey // "cakey" - var/list/player_stats = list() //! Indeed list of /datum/entity/player_stats - var/list/death_stats = list() //! Indexed list of /datum/entity/statistic/death - var/menu = 0 - var/subMenu = 0 - var/dataMenu = 0 - var/data[0] - var/path - var/savefile_version - var/save_loaded = FALSE - -/datum/entity/player_entity/Destroy(force) - QDEL_LIST_ASSOC_VAL(player_stats) - QDEL_LIST_ASSOC_VAL(death_stats) - return ..() - -/datum/entity/player_entity/proc/get_playtime(branch, type) - var/playtime = 0 - if(player_stats["[branch]"]) - var/datum/entity/player_stats/branch_stat = player_stats["[branch]"] - playtime += branch_stat.get_playtime(type) - return playtime - -/datum/entity/player_entity/proc/setup_human_stats() - if(player_stats["human"] && !isnull(player_stats["human"])) - return player_stats["human"] - var/datum/entity/player_stats/human/new_stat = new() - new_stat.player = src - player_stats["human"] = new_stat - return new_stat - -/datum/entity/player_entity/proc/setup_xeno_stats() - if(player_stats["xeno"] && !isnull(player_stats["xeno"])) - return player_stats["xeno"] - var/datum/entity/player_stats/xeno/new_stat = new() - new_stat.player = src - player_stats["xeno"] = new_stat - return new_stat + var/player_id + var/faction + var/statistic_type + var/general_name + var/statistic_name + var/value + +BSQL_PROTECT_DATUM(/datum/entity/statistic) + +/datum/entity_meta/statistic + entity_type = /datum/entity/statistic + table_name = "player_statistic" + field_types = list( + "player_id" = DB_FIELDTYPE_BIGINT, + "faction" = DB_FIELDTYPE_STRING_LARGE, + "statistic_type" = DB_FIELDTYPE_STRING_LARGE, + "general_name" = DB_FIELDTYPE_STRING_LARGE, + "statistic_name" = DB_FIELDTYPE_STRING_LARGE, + "value" = DB_FIELDTYPE_INT, + ) + +/proc/track_statistic_earned(faction, statistic_type, general_name, statistic_name, value, datum/entity/player/player) + set waitfor = FALSE + + if(!player || !player.player_entity || !faction || !statistic_type || !general_name || !statistic_name) + return + + if(!(faction in (FACTION_LIST_ALL + list(STATISTIC_TYPE_GLOBAL)))) + faction = FACTION_NEUTRAL + + var/datum/player_entity/player_entity = player.player_entity + if(player_entity.statistic_logged) + return + + var/datum/grouped_statistic/statistics_group = player_entity.statistics_groups[faction] + var/datum/entity/statistic/statistic = player_entity.get_statistic(faction, statistic_type, general_name, statistic_name) + if(statistic) + statistic.value += value + statistic.save() + if(statistics_group) + statistics_group.waiting_for_recalculate = TRUE + return + + if(!statistics_group) + return + + statistic = DB_ENTITY(/datum/entity/statistic) + statistic.faction = faction + statistic.statistic_type = statistic_type + statistic.general_name = general_name + statistic.statistic_name = statistic_name + statistic.value = value + statistic.player_id = player.id + statistic.save() + statistics_group.load_statistic_group(list(statistic), FALSE) + statistics_group.waiting_for_recalculate = TRUE + +///////////////////////////////////////////////////////////////////////////////////// +//Statistic groups + +/datum/grouped_statistic + var/group_name = "" + var/group_parameter = "" + + var/datum/player_statistic_nemesis/nemesis = new() + var/list/datum/entity/statistic_death/statistic_deaths = list() + // Sub group, used by us so we can easy group them UP + var/list/datum/player_statistic/statistics_infos = list() + // List of all statistic grouped by type and general name + var/list/statistic_all = list() + + // Don't recalculate if we didn't gather any data + var/waiting_for_recalculate = FALSE + +BSQL_PROTECT_DATUM(/datum/grouped_statistic) + +/datum/grouped_statistic/proc/load_statistic_deaths(list/datum/entity/statistic_death/statistics) + nemesis.nemesis_name = "" + nemesis.value = 0 + statistic_deaths.Cut() + var/list/causes = list() + for(var/datum/entity/statistic_death/statistic as anything in statistics) + statistic_deaths += statistic + if(!statistic.cause_name) + continue + + causes[statistic.cause_name]++ + if(causes[statistic.cause_name] > nemesis.value) + nemesis.nemesis_name = statistic.cause_name + nemesis.value = causes[statistic.cause_name] + +/datum/grouped_statistic/proc/load_statistic_group(list/datum/entity/statistic/statistics, recalculate = TRUE) + for(var/datum/entity/statistic/statistic as anything in statistics) + if(!statistic_all[statistic.statistic_type]) + statistic_all[statistic.statistic_type] = list() + + if(!statistic_all[statistic.statistic_type][statistic.general_name]) + statistic_all[statistic.statistic_type][statistic.general_name] = list() + + statistic.sync() + statistic_all[statistic.statistic_type][statistic.general_name] |= statistic + + recalculate_statistic_group(recalculate) + +/datum/grouped_statistic/proc/recalculate_statistic_group(recalculate) + for(var/subtype in statistic_all) + if(statistics_infos[subtype]) + if(recalculate) + statistics_infos[subtype].recalculate_statistic() + continue + + var/datum/player_statistic/statistics_info = new() + statistics_info.statistic_name = subtype + statistics_info.statistic_all = statistic_all[subtype] + statistics_info.load_statistic() + statistics_infos[subtype] = statistics_info + +///////////////////////////////////////////////////////////////////////////////////// +//Player detail statistic + +/datum/player_statistic + var/statistic_name + + var/datum/player_statistic_detail/top_statistic = list() + var/list/datum/player_statistic_detail/statistics_details = list() + var/list/statistic_all = list() + + var/list/total_statistic = list() + +BSQL_PROTECT_DATUM(/datum/player_statistic) + +/datum/player_statistic/proc/load_statistic() + for(var/subtype in statistic_all) + if(statistics_details[subtype]) + continue + + var/datum/player_statistic_detail/detail_statistic = new() + detail_statistic.detail_name = subtype + statistics_details[subtype] = detail_statistic + detail_statistic.statistics = statistic_all[subtype] + + recalculate_statistic() + +/datum/player_statistic/proc/recalculate_statistic() + total_statistic.Cut() + for(var/subtype in statistic_all) + for(var/datum/entity/statistic/statistic as anything in statistic_all[subtype]) + if(total_statistic[statistic.statistic_name]) + total_statistic[statistic.statistic_name] += statistic.value + else + total_statistic[statistic.statistic_name] = statistic.value + + var/list/potential_top_statistic = list("", 0) + for(var/subtype in statistics_details) + var/datum/player_statistic_detail/detail_statistic = statistics_details[subtype] + for(var/datum/entity/statistic/potential_statistic as anything in detail_statistic.statistics) + var/top = TRUE + for(var/datum/entity/statistic/statistic as anything in statistic_all[potential_statistic.general_name] - potential_statistic) + if(potential_statistic.value <= statistic.value) + top = FALSE + break + + if(top) + detail_statistic.top_values_statistics += potential_statistic + + if(potential_top_statistic[2] < length(detail_statistic.top_values_statistics)) + potential_top_statistic = list(detail_statistic, length(detail_statistic.top_values_statistics)) + + top_statistic = potential_top_statistic[1] + +/datum/player_statistic_detail + var/detail_name + + var/list/datum/entity/statistic/top_values_statistics = list() + var/list/datum/entity/statistic/statistics = list() + +BSQL_PROTECT_DATUM(/datum/player_statistic_detail) + +/datum/player_statistic_nemesis + var/nemesis_name + var/value + +BSQL_PROTECT_DATUM(/datum/player_statistic_nemesis) + +///////////////////////////////////////////////////////////////////////////////////// +//Player Entity + +/datum/player_entity + var/ckey + var/datum/entity/player/player = null + var/list/datum/entity/statistic_medal/statistics_medals = list() + var/list/datum/grouped_statistic/statistics_groups = list() + + // Oh god. Just don't mess with it further please... + var/statistic_logged = FALSE + +BSQL_PROTECT_DATUM(/datum/player_entity) + +/datum/player_entity/proc/get_statistic(faction, statistic_type, general_name, statistic_name) + var/datum/grouped_statistic/statistics_group = statistics_groups[faction] + if(!statistics_group) + return FALSE + + var/list/refs_holder = statistics_group.statistic_all[statistic_type] + if(!refs_holder || !refs_holder[general_name]) + return FALSE + + for(var/datum/entity/statistic/statistic as anything in refs_holder[general_name]) + if(statistic.statistic_name != statistic_name) + continue + return statistic + return FALSE + +/datum/player_entity/proc/try_recalculate() + for(var/faction_to_get in statistics_groups) + var/datum/grouped_statistic/statistics_group = statistics_groups[faction_to_get] + if(statistics_group.waiting_for_recalculate) + statistics_group.waiting_for_recalculate = FALSE + statistics_group.recalculate_statistic_group(TRUE) + +/datum/player_entity/proc/setup_entity() + set waitfor = FALSE + WAIT_DB_READY + if(!player) + return + + for(var/faction_to_get in FACTION_LIST_ALL + list(STATISTIC_TYPE_GLOBAL)) + var/datum/grouped_statistic/statistics_group = statistics_groups[faction_to_get] + if(!statistics_group) + statistics_group = new() +// statistics_group.group_name = GLOB.faction_datums[faction_to_get].name // One day... dream come true... + statistics_group.group_name = faction_to_get + statistics_group.group_parameter = faction_to_get + statistics_groups[faction_to_get] = statistics_group + + DB_FILTER(/datum/entity/statistic_death, DB_AND( + DB_COMP("player_id", DB_EQUALS, player.id), + DB_COMP("faction_name", DB_EQUALS, faction_to_get)), + CALLBACK(statistics_group, TYPE_PROC_REF(/datum/grouped_statistic, load_statistic_deaths))) + + DB_FILTER(/datum/entity/statistic, DB_AND( + DB_COMP("player_id", DB_EQUALS, player.id), + DB_COMP("faction", DB_EQUALS, faction_to_get)), + CALLBACK(statistics_group, TYPE_PROC_REF(/datum/grouped_statistic, load_statistic_group))) + + DB_FILTER(/datum/entity/statistic_medal, DB_COMP("player_id", DB_EQUALS, player.id), CALLBACK(src, TYPE_PROC_REF(/datum/player_entity, statistic_load_medals))) + +/datum/player_entity/proc/statistic_load_medals(list/datum/entity/statistic_medal/statistics) + for(var/datum/entity/statistic_medal/statistic as anything in statistics) + statistics_medals |= statistic diff --git a/code/datums/statistics/entities/player_save.dm b/code/datums/statistics/entities/player_save.dm deleted file mode 100644 index 05507bfcc4b4..000000000000 --- a/code/datums/statistics/entities/player_save.dm +++ /dev/null @@ -1,330 +0,0 @@ - -/datum/entity/player_entity/proc/setup_save(key) - if(key && !IsGuestKey(key)) - load_path(lowertext(key)) - load_statistics() - savefile_version = PREFFILE_VERSION_MAX - -/datum/entity/player_entity/proc/load_path(ckey,filename="statistics.sav") - if(!ckey) - return - path = "data/player_saves/[copytext(ckey,1,2)]/[ckey]/[filename]" - savefile_version = PREFFILE_VERSION_MAX - -/datum/entity/player_entity/proc/save_statistics() - if(!path || !save_loaded) - log_debug("STATISTICS: stats failed to save for [ckey] in [path] (save_loaded: [save_loaded])") - return FALSE - var/savefile/S = new /savefile(path) - if(!S) - return FALSE - S.cd = "/" - - update_panel_data() - - S["version"] << savefile_version - S["xeno"] << data["xeno"] - S["human"] << data["human"] - - return TRUE - -/datum/entity/player_entity/proc/load_statistics() - if(!path || !fexists(path)) - save_loaded = TRUE - return FALSE - var/savefile/S = new /savefile(path) - if(!S) - log_debug("STATISTICS: fexists but load failed for [ckey] in [path]") - return FALSE - S.cd = "/" - - if(S["version"] < PREFFILE_VERSION_MIN) - return FALSE - - S["version"] >> savefile_version - - var/list/human_save = list() - var/list/xeno_save = list() - - S["human"] >> human_save - S["xeno"] >> xeno_save - - if(human_save) - setup_human_stats() - var/datum/entity/player_stats/human/human_stats = player_stats["human"] - human_stats.total_kills = human_save["total_kills"] - human_stats.total_deaths = human_save["total_deaths"] - human_stats.total_playtime = text2duration(human_save["total_playtime"]) - human_stats.total_rounds_played = human_save["total_rounds_played"] - human_stats.steps_walked = human_save["steps_walked"] - - human_stats.total_friendly_fire = human_save["total_friendly_fire"] - human_stats.total_revives = human_save["total_revives"] - human_stats.total_lives_saved = human_save["total_lives_saved"] - human_stats.total_shots = human_save["total_shots"] - human_stats.total_shots_hit = human_save["total_shots_hit"] - human_stats.total_screams = human_save["total_screams"] - - if(human_save["nemesis"]) - var/save_nemesis = human_save["nemesis"] - var/datum/entity/statistic/new_nemesis = new() - new_nemesis.name = save_nemesis["name"] - new_nemesis.value = save_nemesis["value"] - human_stats.nemesis = new_nemesis - - if(human_save["humans_killed"]) - var/save_humans_killed = human_save["humans_killed"] - var/list/new_humans_killed_list = new() - for(var/save_kill in save_humans_killed) - var/datum/entity/statistic/new_human_killed = new() - new_human_killed.name = save_kill["name"] - new_human_killed.value = save_kill["value"] - new_humans_killed_list["[new_human_killed.name]"] = new_human_killed - human_stats.humans_killed = new_humans_killed_list - - if(human_save["xenos_killed"]) - var/save_xeno_killed = human_save["xenos_killed"] - var/list/new_xenos_killed_list = new() - for(var/save_kill in save_xeno_killed) - var/datum/entity/statistic/new_xeno_killed = new() - new_xeno_killed.name = save_kill["name"] - new_xeno_killed.value = save_kill["value"] - new_xenos_killed_list["[new_xeno_killed.name]"] = new_xeno_killed - human_stats.xenos_killed = new_xenos_killed_list - - if(human_save["niche_stats"]) - var/save_niche_stats = human_save["niche_stats"] - var/list/new_niche_stat_list = new() - for(var/save_niche in save_niche_stats) - var/datum/entity/statistic/new_niche_stat = new() - new_niche_stat.name = save_niche["name"] - new_niche_stat.value = save_niche["value"] - new_niche_stat_list["[new_niche_stat.name]"] = new_niche_stat - human_stats.niche_stats = new_niche_stat_list - - if(human_save["weapon_stats_list"]) - var/save_weapon_list = human_save["weapon_stats_list"] - var/list/new_weapon_list = new() - for(var/save_weapon in save_weapon_list) - var/datum/entity/weapon_stats/new_weapon = new() - new_weapon.player = src - new_weapon.name = save_weapon["name"] - new_weapon.total_kills = save_weapon["total_kills"] - new_weapon.total_hits = save_weapon["total_hits"] - new_weapon.total_shots = save_weapon["total_shots"] - new_weapon.total_shots_hit = save_weapon["total_shots_hit"] - new_weapon.total_friendly_fire = save_weapon["total_friendly_fire"] - - if(save_weapon["humans_killed"]) - var/save_humans_killed = save_weapon["humans_killed"] - var/list/new_humans_killed_list = new() - for(var/save_kill in save_humans_killed) - var/datum/entity/statistic/new_human_killed = new() - new_human_killed.name = save_kill["name"] - new_human_killed.value = save_kill["value"] - new_humans_killed_list["[new_human_killed.name]"] = new_human_killed - new_weapon.humans_killed = new_humans_killed_list - - if(save_weapon["xenos_killed"]) - var/save_xeno_killed = save_weapon["xenos_killed"] - var/list/new_xenos_killed_list = new() - for(var/save_kill in save_xeno_killed) - var/datum/entity/statistic/new_xeno_killed = new() - new_xeno_killed.name = save_kill["name"] - new_xeno_killed.value = save_kill["value"] - new_xenos_killed_list["[new_xeno_killed.name]"] = new_xeno_killed - new_weapon.xenos_killed = new_xenos_killed_list - - if(save_weapon["niche_stats"]) - var/save_niche_stats = save_weapon["niche_stats"] - var/list/new_niche_stat_list = new() - for(var/save_niche in save_niche_stats) - var/datum/entity/statistic/new_niche_stat = new() - new_niche_stat.name = save_niche["name"] - new_niche_stat.value = save_niche["value"] - new_niche_stat_list["[new_niche_stat.name]"] = new_niche_stat - new_weapon.niche_stats = new_niche_stat_list - - new_weapon_list["[new_weapon.name]"] = new_weapon - human_stats.weapon_stats_list = new_weapon_list - - if(human_save["job_stats_list"]) - var/save_job_list = human_save["job_stats_list"] - var/list/new_job_list = new() - for(var/save_job in save_job_list) - var/datum/entity/player_stats/job/new_job = new() - new_job.total_kills = save_job["total_kills"] - new_job.total_deaths = save_job["total_deaths"] - new_job.total_playtime = text2duration(save_job["total_playtime"]) - new_job.total_rounds_played = save_job["total_rounds_played"] - new_job.steps_walked = save_job["steps_walked"] - - new_job.name = save_job["name"] - new_job.total_friendly_fire = save_job["total_friendly_fire"] - new_job.total_revives = save_job["total_revives"] - new_job.total_lives_saved = save_job["total_lives_saved"] - new_job.total_shots = save_job["total_shots"] - new_job.total_shots_hit = save_job["total_shots_hit"] - new_job.total_screams = save_job["total_screams"] - - if(save_job["nemesis"]) - var/save_nemesis = save_job["nemesis"] - var/datum/entity/statistic/new_nemesis = new() - new_nemesis.name = save_nemesis["name"] - new_nemesis.value = save_nemesis["value"] - new_job.nemesis = new_nemesis - - if(save_job["humans_killed"]) - var/save_humans_killed = save_job["humans_killed"] - var/list/new_humans_killed_list = new() - for(var/save_kill in save_humans_killed) - var/datum/entity/statistic/new_human_killed = new() - new_human_killed.name = save_kill["name"] - new_human_killed.value = save_kill["value"] - new_humans_killed_list["[new_human_killed.name]"] = new_human_killed - new_job.humans_killed = new_humans_killed_list - - if(save_job["xenos_killed"]) - var/save_xeno_killed = save_job["xenos_killed"] - var/list/new_xenos_killed_list = new() - for(var/save_kill in save_xeno_killed) - var/datum/entity/statistic/new_xeno_killed = new() - new_xeno_killed.name = save_kill["name"] - new_xeno_killed.value = save_kill["value"] - new_xenos_killed_list["[new_xeno_killed.name]"] = new_xeno_killed - new_job.xenos_killed = new_xenos_killed_list - - if(save_job["niche_stats"]) - var/save_niche_stats = save_job["niche_stats"] - var/list/new_niche_stat_list = new() - for(var/save_niche in save_niche_stats) - var/datum/entity/statistic/new_niche_stat = new() - new_niche_stat.name = save_niche["name"] - new_niche_stat.value = save_niche["value"] - new_niche_stat_list["[new_niche_stat.name]"] = new_niche_stat - new_job.niche_stats = new_niche_stat_list - - new_job_list["[new_job.name]"] = new_job - human_stats.job_stats_list = new_job_list - - human_stats.recalculate_nemesis() - human_stats.recalculate_top_weapon() - - if(xeno_save) - setup_xeno_stats() - var/datum/entity/player_stats/xeno/xeno_stats = player_stats["xeno"] - xeno_stats.total_kills = xeno_save["total_kills"] - xeno_stats.total_deaths = xeno_save["total_deaths"] - xeno_stats.total_playtime = text2duration(xeno_save["total_playtime"]) - xeno_stats.total_rounds_played = xeno_save["total_rounds_played"] - xeno_stats.steps_walked = xeno_save["steps_walked"] - - xeno_stats.total_hits = xeno_save["total_hits"] - - if(xeno_save["nemesis"]) - var/save_nemesis = xeno_save["nemesis"] - var/datum/entity/statistic/new_nemesis = new() - new_nemesis.name = save_nemesis["name"] - new_nemesis.value = save_nemesis["value"] - xeno_stats.nemesis = new_nemesis - - if(xeno_save["humans_killed"]) - var/save_humans_killed = xeno_save["humans_killed"] - var/list/new_humans_killed_list = new() - for(var/save_kill in save_humans_killed) - var/datum/entity/statistic/new_human_killed = new() - new_human_killed.name = save_kill["name"] - new_human_killed.value = save_kill["value"] - new_humans_killed_list["[new_human_killed.name]"] = new_human_killed - xeno_stats.humans_killed = new_humans_killed_list - - if(xeno_save["xenos_killed"]) - var/save_xeno_killed = xeno_save["xenos_killed"] - var/list/new_xenos_killed_list = new() - for(var/save_kill in save_xeno_killed) - var/datum/entity/statistic/new_xeno_killed = new() - new_xeno_killed.name = save_kill["name"] - new_xeno_killed.value = save_kill["value"] - new_xenos_killed_list["[new_xeno_killed.name]"] = new_xeno_killed - xeno_stats.xenos_killed = new_xenos_killed_list - - if(xeno_save["niche_stats"]) - var/save_niche_stats = xeno_save["niche_stats"] - var/list/new_niche_stat_list = new() - for(var/save_niche in save_niche_stats) - var/datum/entity/statistic/new_niche_stat = new() - new_niche_stat.name = save_niche["name"] - new_niche_stat.value = save_niche["value"] - new_niche_stat_list["[new_niche_stat.name]"] = new_niche_stat - xeno_stats.niche_stats = new_niche_stat_list - - if(xeno_save["caste_stats_list"]) - var/save_caste_list = xeno_save["caste_stats_list"] - var/list/new_caste_list = new() - for(var/save_caste in save_caste_list) - var/datum/entity/player_stats/caste/new_caste = new() - new_caste.total_kills = save_caste["total_kills"] - new_caste.total_deaths = save_caste["total_deaths"] - new_caste.total_playtime = text2duration(save_caste["total_playtime"]) - new_caste.total_rounds_played = save_caste["total_rounds_played"] - new_caste.steps_walked = save_caste["steps_walked"] - - new_caste.name = save_caste["name"] - new_caste.total_hits = save_caste["total_hits"] - - if(save_caste["nemesis"]) - var/save_nemesis = save_caste["nemesis"] - var/datum/entity/statistic/new_nemesis = new() - new_nemesis.name = save_nemesis["name"] - new_nemesis.value = save_nemesis["value"] - new_caste.nemesis = new_nemesis - - if(save_caste["abilities_used"]) - var/save_abilities_used = save_caste["abilities_used"] - var/list/new_abilities_used_list = new() - for(var/save_ability in save_abilities_used) - var/datum/entity/statistic/new_ability_used = new() - new_ability_used.name = save_ability["name"] - new_ability_used.value = save_ability["value"] - new_abilities_used_list["[new_ability_used.name]"] = new_ability_used - new_caste.abilities_used = new_abilities_used_list - - if(save_caste["humans_killed"]) - var/save_humans_killed = save_caste["humans_killed"] - var/list/new_humans_killed_list = new() - for(var/save_kill in save_humans_killed) - var/datum/entity/statistic/new_human_killed = new() - new_human_killed.name = save_kill["name"] - new_human_killed.value = save_kill["value"] - new_humans_killed_list["[new_human_killed.name]"] = new_human_killed - new_caste.humans_killed = new_humans_killed_list - - if(save_caste["xenos_killed"]) - var/save_xeno_killed = save_caste["xenos_killed"] - var/list/new_xenos_killed_list = new() - for(var/save_kill in save_xeno_killed) - var/datum/entity/statistic/new_xeno_killed = new() - new_xeno_killed.name = save_kill["name"] - new_xeno_killed.value = save_kill["value"] - new_xenos_killed_list["[new_xeno_killed.name]"] = new_xeno_killed - new_caste.xenos_killed = new_xenos_killed_list - - if(save_caste["niche_stats"]) - var/save_niche_stats = save_caste["niche_stats"] - var/list/new_niche_stat_list = new() - for(var/save_niche in save_niche_stats) - var/datum/entity/statistic/new_niche_stat = new() - new_niche_stat.name = save_niche["name"] - new_niche_stat.value = save_niche["value"] - new_niche_stat_list["[new_niche_stat.name]"] = new_niche_stat - new_caste.niche_stats = new_niche_stat_list - - new_caste_list["[new_caste.name]"] = new_caste - xeno_stats.caste_stats_list = new_caste_list - - xeno_stats.recalculate_nemesis() - xeno_stats.recalculate_top_caste() - - save_loaded = TRUE - update_panel_data() - return TRUE diff --git a/code/datums/statistics/entities/player_stats.dm b/code/datums/statistics/entities/player_stats.dm index a8444c1a5894..d89ee4ca3668 100644 --- a/code/datums/statistics/entities/player_stats.dm +++ b/code/datums/statistics/entities/player_stats.dm @@ -1,173 +1,364 @@ -/datum/entity/player_stats - var/datum/entity/player_entity/player = null // "mattatlas" - var/total_kills = 0 - var/total_deaths = 0 - var/total_playtime = 0 - var/total_rounds_played = 0 - var/steps_walked = 0 - var/round_played = FALSE - var/datum/entity/statistic/nemesis // "runner" = 3 - var/list/niche_stats = list() // list of type /datum/entity/statistic, "Total Executions" = number - var/list/humans_killed = list() // list of type /datum/entity/statistic, "jobname2" = number - var/list/xenos_killed = list() // list of type /datum/entity/statistic, "caste" = number - var/list/death_list = list() // list of type /datum/entity/death_stats - var/display_stat = TRUE - -/datum/entity/player_stats/Destroy(force) - QDEL_NULL(nemesis) - QDEL_LIST_ASSOC_VAL(niche_stats) - QDEL_LIST_ASSOC_VAL(humans_killed) - QDEL_LIST_ASSOC_VAL(xenos_killed) - QDEL_LIST_ASSOC_VAL(death_list) - return ..() - -/datum/entity/player_stats/proc/get_playtime() - return total_playtime - -/datum/entity/player_stats/proc/count_personal_human_kill(job_name, cause, job) - return - -/datum/entity/player_stats/proc/count_personal_xeno_kill(job_name, cause, job) - return - -/datum/entity/player_stats/proc/count_human_kill(job_name, cause, job) - if(!job_name) - return - if(!humans_killed["[job_name]"]) - var/datum/entity/statistic/N = new() - N.name = job_name - humans_killed["[job_name]"] = N - var/datum/entity/statistic/S = humans_killed["[job_name]"] - S.value++ - if(job) - count_personal_human_kill(job_name, cause, job) - total_kills++ - -/datum/entity/player_stats/proc/count_xeno_kill(caste, cause, job) - if(!caste) - return - if(!xenos_killed["[caste]"]) - var/datum/entity/statistic/N = new() - N.name = caste - xenos_killed["[caste]"] = N - var/datum/entity/statistic/S = xenos_killed["[caste]"] - S.value++ - if(job) - count_personal_xeno_kill(caste, cause, job) - total_kills++ - -//***************** -//Mob Procs - death -//***************** - -/datum/entity/player_stats/proc/recalculate_nemesis() - var/list/causes = list() - for(var/datum/entity/statistic/death/stat_entity in death_list) - if(!stat_entity.cause_name) - continue - causes["[stat_entity.cause_name]"]++ - if(!nemesis) - nemesis = new() - nemesis.name = stat_entity.cause_name - nemesis.value = 1 - continue - if(causes["[stat_entity.cause_name]"] > nemesis.value) - nemesis.name = stat_entity.cause_name - nemesis.value = causes["[stat_entity.cause_name]"] - -/datum/entity/player_stats/proc/count_personal_death(job) - return +// TODO: Some day do custom count effect on stats updated, so don't copy this procs and also do it flexible like right now (I don't wanna change it, because on next merge upstream in this rep it will fuck up all calls on that and fixing more flexible shit will be harder) +// Also, make it wait and count like every +-30 minutes, so our DB don't fuck up in INF!, funny... (Right now if you tru to update that very often it will fuck up all, so better make it affect already taken rows, in case if no rows, just make new) + +// Ignore above TODO and funny comment, I'll leave it remain here, until it's merged and I'll do new pr with creating finnal touchs (originaly this comment from mine offstream, but I forgot to remove it, plus this contain really useful information about what to do next with this to increase it realability and prettyisdajghhfh) + +///////////////////////////////////////////////////////////////////////////////////// +//Mob + +/mob/proc/can_track_statistic() + if(statistic_exempt || statistic_tracked || !client?.player_data || !faction) + return FALSE + return TRUE /mob/proc/track_death_calculations() - if(statistic_exempt || statistic_tracked) - return - if(GLOB.round_statistics) - GLOB.round_statistics.recalculate_nemesis() - if(mind && mind.player_entity) - mind.player_entity.update_panel_data(GLOB.round_statistics) + if(!can_track_statistic()) + return FALSE + statistic_tracked = TRUE + return TRUE + +/mob/proc/count_statistic_stat(statistic_name, amount = 1, weapon) + if(!can_track_statistic()) + return FALSE + return TRUE + +/mob/proc/track_steps_walked() + if(!can_track_statistic()) + return FALSE + return TRUE + +/mob/proc/track_hit(weapon, amount = 1, statistic_name = STATISTICS_HIT) + if(!can_track_statistic()) + return FALSE + return TRUE + +/mob/proc/track_friendly_hit(weapon, amount = 1, statistic_name = STATISTICS_FF_HIT) + if(!can_track_statistic()) + return FALSE + return TRUE + +/mob/proc/track_shot(weapon, amount = 1, statistic_name = STATISTICS_SHOT) + if(!can_track_statistic()) + return FALSE + return TRUE + +/mob/proc/track_shot_hit(weapon, mob/shot_mob, amount = 1, statistic_name = STATISTICS_SHOT_HIT) + if(!can_track_statistic()) + return FALSE + + if(GLOB.round_statistics) + GLOB.round_statistics.total_projectiles_hit += amount + if(shot_mob) + if(ishuman(shot_mob)) + GLOB.round_statistics.total_projectiles_hit_human += amount + else if(isxeno(shot_mob)) + GLOB.round_statistics.total_projectiles_hit_xeno += amount + return TRUE + +/mob/proc/track_damage(weapon, mob/damaged_mob, amount = 1, statistic_name = STATISTICS_DAMAGE) + if(!can_track_statistic()) + return FALSE + return TRUE + +/mob/proc/track_friendly_damage(weapon, mob/damaged_mob, amount = 1, statistic_name = STATISTICS_FF_DAMAGE) + if(!can_track_statistic()) + return FALSE + return TRUE + +/mob/proc/track_heal_damage(weapon, mob/healed_mob, amount = 1, statistic_name = STATISTICS_HEALED_DAMAGE) + if(!can_track_statistic()) + return FALSE + return TRUE + +/mob/proc/track_friendly_fire(weapon, amount = 1, statistic_name = STATISTICS_FF_SHOT_HIT) + if(!can_track_statistic()) + return FALSE + + if(GLOB.round_statistics) + GLOB.round_statistics.total_friendly_fire_instances += amount -//***************** -//Mob Procs - kills -//***************** + return TRUE -/mob/proc/count_human_kill(job_name, cause) - return +/mob/proc/track_revive(amount = 1, statistic_name = STATISTICS_REVIVED) + if(!can_track_statistic()) + return FALSE + return TRUE -/mob/proc/count_xeno_kill(killed_caste, cause) - return +/mob/proc/track_life_saved(amount = 1, statistic_name = STATISTICS_REVIVE) + if(!can_track_statistic()) + return FALSE + return TRUE -/mob/proc/count_niche_stat(niche_name, amount = 1) - return +/mob/proc/track_scream(amount = 1, statistic_name = STATISTICS_SCREAM) + if(!can_track_statistic()) + return FALSE + return TRUE +/mob/proc/track_slashes(caste, amount = 1, statistic_name = STATISTICS_SLASH) + if(!can_track_statistic()) + return FALSE + + if(GLOB.round_statistics) + GLOB.round_statistics.total_slashes += amount + + return TRUE + +/mob/proc/track_ability_usage(ability, caste, amount = 1) + if(!can_track_statistic()) + return FALSE + return TRUE + +///////////////////////////////////////////////////////////////////////////////////// //Human -/mob/living/carbon/human/count_human_kill(job_name, cause) - if(statistic_exempt || !mind) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - var/job_actual = get_actual_job_name(src) - human_stats.count_human_kill(job_name, cause, job_actual) -/mob/living/carbon/human/count_xeno_kill(killed_caste, cause) - if(statistic_exempt || !mind) - return - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - var/job_actual = get_actual_job_name(src) - human_stats.count_xeno_kill(killed_caste, cause, job_actual) -/mob/living/carbon/human/count_niche_stat(niche_name, amount = 1, weapon_name) - if(statistic_exempt || !mind) - return - var/job_actual = get_actual_job_name(src) - var/datum/entity/player_stats/human/human_stats = mind.setup_human_stats() - human_stats.count_niche_stat(niche_name, amount, job_actual, weapon_name) +/mob/living/carbon/human/track_death_calculations() + . = ..() + if(!.) + return FALSE -//Xeno -/mob/living/carbon/xenomorph/count_human_kill(job_name, cause) - if(statistic_exempt || !mind) - return - var/datum/entity/player_stats/xeno/xeno_stats = mind.setup_xeno_stats() - if(isnull(xeno_stats)) - return - xeno_stats.count_human_kill(job_name, cause, caste_type) + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), STATISTICS_ROUNDS_PLAYED, 1, client.player_data) -/mob/living/carbon/xenomorph/count_xeno_kill(killed_caste, cause) - if(statistic_exempt || !mind) - return - var/datum/entity/player_stats/xeno/xeno_stats = mind.setup_xeno_stats() - if(isnull(xeno_stats)) - return - xeno_stats.count_xeno_kill(killed_caste, cause, caste_type) +/mob/living/carbon/human/count_statistic_stat(statistic_name, amount = 1, weapon) + . = ..() + if(!.) + return FALSE -/mob/living/carbon/xenomorph/count_niche_stat(niche_name, amount = 1) - if(statistic_exempt || !mind) - return - var/datum/entity/player_stats/xeno/xeno_stats = mind.setup_xeno_stats() - if(isnull(xeno_stats)) - return - xeno_stats.count_niche_stat(niche_name, amount, caste_type) + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/human/track_steps_walked(amount = 1, statistic_name = STATISTICS_STEPS_WALKED) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + +/mob/living/carbon/human/track_hit(weapon, amount = 1, statistic_name = STATISTICS_HIT) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/human/track_friendly_hit(weapon, amount = 1, statistic_name = STATISTICS_FF_HIT) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/human/track_shot(weapon, amount = 1, statistic_name = STATISTICS_SHOT) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/human/track_shot_hit(weapon, mob/shot_mob, amount = 1, statistic_name = STATISTICS_SHOT_HIT) + . = ..() + if(!.) + return FALSE -//***************** -//Mob Procs - minor -//***************** + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) -/datum/entity/player_stats/proc/count_personal_niche_stat(niche_name, amount = 1, job) - return +/mob/living/carbon/human/track_damage(weapon, mob/damaged_mob, amount = 1, statistic_name = STATISTICS_DAMAGE) + . = ..() + if(!.) + return FALSE -/datum/entity/player_stats/proc/count_niche_stat(niche_name, amount = 1, job) - if(!niche_name) + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/human/track_friendly_damage(weapon, mob/damaged_mob, amount = 1, statistic_name = STATISTICS_FF_DAMAGE) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/human/track_heal_damage(weapon, mob/healed_mob, amount = 1, statistic_name = STATISTICS_HEALED_DAMAGE) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/human/track_friendly_fire(weapon, amount = 1, statistic_name = STATISTICS_FF_SHOT_HIT) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/human/track_revive(amount = 1, statistic_name = STATISTICS_REVIVED) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + +/mob/living/carbon/human/track_life_saved(amount = 1, statistic_name = STATISTICS_REVIVE) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + +/mob/living/carbon/human/track_scream(amount = 1, statistic_name = STATISTICS_SCREAM) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_JOB, get_role_name(), statistic_name, amount, client.player_data) + +///////////////////////////////////////////////////////////////////////////////////// +//Xenomorph + +/mob/living/carbon/xenomorph/track_death_calculations() + . = ..() + if(!. || !faction) return - if(!niche_stats["[niche_name]"]) - var/datum/entity/statistic/N = new() - N.name = niche_name - niche_stats["[niche_name]"] = N - var/datum/entity/statistic/S = niche_stats["[niche_name]"] - S.value += amount - if(job) - count_personal_niche_stat(niche_name, amount, job) - -/datum/entity/player_stats/proc/count_personal_steps_walked(job) - return -/mob/proc/track_steps_walked() - return + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), STATISTICS_ROUNDS_PLAYED, 1, client.player_data) + +/mob/living/carbon/xenomorph/count_statistic_stat(statistic_name, amount = 1, weapon) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, caste_type, statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_steps_walked(amount = 1, statistic_name = STATISTICS_STEPS_WALKED) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, caste_type, statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_hit(weapon, amount = 1, statistic_name = STATISTICS_HIT) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_friendly_hit(weapon, amount = 1, statistic_name = STATISTICS_FF_HIT) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_shot(weapon, amount = 1, statistic_name = STATISTICS_SHOT) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_shot_hit(weapon, mob/shot_mob, amount = 1, statistic_name = STATISTICS_SHOT_HIT) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_damage(weapon, mob/damaged_mob, amount = 1, statistic_name = STATISTICS_DAMAGE) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_friendly_damage(weapon, mob/damaged_mob, amount = 1, statistic_name = STATISTICS_FF_DAMAGE) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_heal_damage(weapon, mob/healed_mob, amount = 1, statistic_name = STATISTICS_HEALED_DAMAGE) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_friendly_fire(weapon, amount = 1, statistic_name = STATISTICS_FF_SHOT_HIT) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), statistic_name, amount, client.player_data) + if(weapon) + track_statistic_earned(faction, STATISTIC_TYPE_WEAPON, weapon, statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_revive(amount = 1, statistic_name = STATISTICS_REVIVED) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_life_saved(amount = 1, statistic_name = STATISTICS_REVIVE) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_scream(amount = 1, statistic_name = STATISTICS_SCREAM) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, get_role_name(), statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_slashes(caste, amount = 1, statistic_name = STATISTICS_SLASH) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, caste, statistic_name, amount, client.player_data) + +/mob/living/carbon/xenomorph/track_ability_usage(ability, caste, amount = 1) + . = ..() + if(!.) + return FALSE + + track_statistic_earned(faction, STATISTIC_TYPE_CASTE_ABILITIES, caste, ability, amount, client.player_data) + track_statistic_earned(faction, STATISTIC_TYPE_CASTE, caste, STATISTICS_ABILITES, amount, client.player_data) diff --git a/code/datums/statistics/entities/round_stats.dm b/code/datums/statistics/entities/round_stats.dm index d4941cb970e8..443cace0b06f 100644 --- a/code/datums/statistics/entities/round_stats.dm +++ b/code/datums/statistics/entities/round_stats.dm @@ -1,4 +1,4 @@ -/datum/entity/statistic/round +/datum/entity/statistic_round var/round_id var/round_name @@ -20,20 +20,24 @@ var/total_projectiles_hit_human = 0 var/total_projectiles_hit_xeno = 0 var/total_friendly_fire_instances = 0 + var/total_friendly_kills = 0 var/total_slashes = 0 // untracked data - var/datum/entity/statistic/map/current_map // reference to current map - var/list/datum/entity/statistic/death/death_stats_list = list() + var/list/cached_tgui_data + var/datum/entity/statistic_map/current_map = null // reference to current map + var/list/datum/entity/statistic_death/death_stats_list = list() var/list/abilities_used = list() // types of /datum/entity/statistic, "tail sweep" = 10, "screech" = 2 + var/list/participants = list() // types of /datum/entity/statistic, "[mob.faction]" = 10 + var/list/final_participants = list() // types of /datum/entity/statistic, "[mob.faction]" = 0 + var/list/hijack_participants = list() // types of /datum/entity/statistic, "[mob.faction]" = 0 + var/list/total_deaths = list() // types of /datum/entity/statistic, "[mob.faction]" = 0 + + //TODO: CHANGE IT var/list/castes_evolved = list() // dict of any caste that has been evolved into, and how many times, "Ravager" = 5, "Warrior" = 2 - var/list/participants = list() // types of /datum/entity/statistic, "[human.faction]" = 10, "xeno" = 2 - var/list/final_participants = list() // types of /datum/entity/statistic, "[human.faction]" = 0, "xeno" = 45 - var/list/hijack_participants = list() // types of /datum/entity/statistic, "[human.faction]" = 0, "xeno" = 45 - var/list/total_deaths = list() // types of /datum/entity/statistic, "[human.faction]" = 0, "xeno" = 45 var/list/caste_stats_list = list() // list of types /datum/entity/player_stats/caste var/list/weapon_stats_list = list() // list of types /datum/entity/weapon_stats var/list/job_stats_list = list() // list of types /datum/entity/job_stats @@ -41,26 +45,25 @@ /// A list of all player xenomorph deaths, type /datum/entity/xeno_death var/list/xeno_deaths = list() - // nanoui data - var/list/round_data = list() - var/list/death_data = list() +BSQL_PROTECT_DATUM(/datum/entity/statistic_round) -/datum/entity/statistic/round/Destroy(force) +/datum/entity/statistic_round/Destroy(force) . = ..() + QDEL_NULL(current_map) QDEL_LIST(death_stats_list) QDEL_LIST(xeno_deaths) - QDEL_LIST_ASSOC_VAL(castes_evolved) - QDEL_LIST_ASSOC_VAL(abilities_used) - QDEL_LIST_ASSOC_VAL(final_participants) - QDEL_LIST_ASSOC_VAL(hijack_participants) - QDEL_LIST_ASSOC_VAL(total_deaths) - QDEL_LIST_ASSOC_VAL(caste_stats_list) - QDEL_LIST_ASSOC_VAL(weapon_stats_list) - QDEL_LIST_ASSOC_VAL(job_stats_list) + castes_evolved = null + abilities_used = null + final_participants = null + hijack_participants = null + total_deaths = null + caste_stats_list = null + weapon_stats_list = null + job_stats_list = null /datum/entity_meta/statistic_round - entity_type = /datum/entity/statistic/round + entity_type = /datum/entity/statistic_round table_name = "rounds" key_field = "round_id" field_types = list( @@ -84,243 +87,121 @@ "total_projectiles_hit_human" = DB_FIELDTYPE_INT, "total_projectiles_hit_xeno" = DB_FIELDTYPE_INT, "total_friendly_fire_instances" = DB_FIELDTYPE_INT, - "total_slashes" = DB_FIELDTYPE_INT + "total_friendly_kills" = DB_FIELDTYPE_INT, + "total_slashes" = DB_FIELDTYPE_INT, ) /datum/game_mode/proc/setup_round_stats() - if(!round_stats) - var/datum/entity/mc_round/mc_round = SSentity_manager.select(/datum/entity/mc_round) + set waitfor = FALSE + + WAIT_SSPERFLOGGING_READY + + if(!GLOB.round_statistics) var/operation_name operation_name = "[pick(GLOB.operation_titles)]" operation_name += " [pick(GLOB.operation_prefixes)]" operation_name += "-[pick(GLOB.operation_postfixes)]" - // Round stats - round_stats = DB_ENTITY(/datum/entity/statistic/round) - round_stats.round_name = operation_name - round_stats.round_id = mc_round.id - round_stats.map_name = SSmapping.configs[GROUND_MAP].map_name - round_stats.game_mode = name - round_stats.real_time_start = world.realtime - round_stats.save() - - // Setup the global reference - GLOB.round_statistics = round_stats - - // Map stats - var/datum/entity/statistic/map/new_map = DB_EKEY(/datum/entity/statistic/map, SSmapping.configs[GROUND_MAP].map_name) - new_map.total_rounds++ - new_map.save() - - // Connect map to round - round_stats.current_map = new_map - -/datum/entity/statistic/round/proc/setup_job_stats(job, noteworthy = TRUE) - if(!job) - return - var/job_key = strip_improper(job) - if(job_stats_list["[job_key]"]) - var/datum/entity/player_stats/job/S = job_stats_list["[job_key]"] - if(!S.display_stat && noteworthy) - S.display_stat = noteworthy - return S - var/datum/entity/player_stats/job/new_stat = new() - new_stat.display_stat = noteworthy - new_stat.player = src - new_stat.name = job_key - new_stat.total_rounds_played++ - job_stats_list["[job_key]"] = new_stat - return new_stat - -/datum/entity/statistic/round/proc/setup_weapon_stats(weapon, noteworthy = TRUE) - if(!weapon) - return - var/weapon_key = strip_improper(weapon) - if(weapon_stats_list["[weapon_key]"]) - var/datum/entity/weapon_stats/S = weapon_stats_list["[weapon_key]"] - if(!S.display_stat && noteworthy) - S.display_stat = noteworthy - return S - var/datum/entity/weapon_stats/new_stat = new() - new_stat.display_stat = noteworthy - new_stat.player = src - new_stat.name = weapon_key - weapon_stats_list["[weapon_key]"] = new_stat - return new_stat - -/datum/entity/statistic/round/proc/setup_caste_stats(caste, noteworthy = TRUE) - if(!caste) - return - var/caste_key = strip_improper(caste) - if(caste_stats_list["[caste_key]"]) - var/datum/entity/player_stats/caste/S = caste_stats_list["[caste_key]"] - if(!S.display_stat && noteworthy) - S.display_stat = noteworthy - return S - var/datum/entity/player_stats/caste/new_stat = new() - new_stat.display_stat = noteworthy - new_stat.player = src - new_stat.name = caste_key - new_stat.total_rounds_played++ - caste_stats_list["[caste_key]"] = new_stat - return new_stat - -/datum/entity/statistic/round/proc/setup_ability(ability) - if(!ability) - return - var/ability_key = strip_improper(ability) - if(abilities_used["[ability_key]"]) - return abilities_used["[ability_key]"] - var/datum/entity/statistic/S = new() - S.name = ability_key - S.value = 0 - abilities_used["[ability_key]"] = S - return S - -/datum/entity/statistic/round/proc/recalculate_nemesis() - for(var/caste_statistic in caste_stats_list) - var/datum/entity/player_stats/caste/caste_entity = caste_stats_list[caste_statistic] - caste_entity.recalculate_nemesis() - for(var/job_statistic in job_stats_list) - var/datum/entity/player_stats/job/job_entity = job_stats_list[job_statistic] - job_entity.recalculate_nemesis() - -/datum/entity/statistic/round/proc/track_ability_usage(ability, amount = 1) - var/datum/entity/statistic/S = setup_ability(ability) - S.value += amount - -/datum/entity/statistic/round/proc/setup_faction(faction) + var/datum/entity/statistic_round/round = DB_ENTITY(/datum/entity/statistic_round) + round.round_name = operation_name + round.map_name = SSmapping.configs[GROUND_MAP].map_name + var/datum/entity/statistic_map/new_map = DB_EKEY(/datum/entity/statistic_map, round.map_name) + round.current_map = new_map + round.current_map.save() + round.round_id = SSperf_logging.round?.id + round.game_mode = name + round.real_time_start = world.realtime + round.save() + START_PROCESSING(SSobj, round) + GLOB.round_statistics = round + +/datum/entity/statistic_round/proc/setup_faction(faction) if(!faction) return - var/faction_key = strip_improper(faction) - if(!participants["[faction_key]"]) - var/datum/entity/statistic/S = new() - S.name = faction_key - S.value = 0 - participants["[faction_key]"] = S - if(!final_participants["[faction_key]"]) - var/datum/entity/statistic/S = new() - S.name = faction_key - S.value = 0 - final_participants["[faction_key]"] = S - if(!hijack_participants["[faction_key]"]) - var/datum/entity/statistic/S = new() - S.name = faction_key - S.value = 0 - hijack_participants["[faction_key]"] = S - if(!total_deaths["[faction_key]"]) - var/datum/entity/statistic/S = new() - S.name = faction_key - S.value = 0 - total_deaths["[faction_key]"] = S - -/datum/entity/statistic/round/proc/track_new_participant(faction, amount = 1) + + if(!participants[faction]) + participants[faction] = 0 + + if(!final_participants[faction]) + final_participants[faction] = 0 + + if(!hijack_participants[faction]) + hijack_participants[faction] = 0 + + if(!total_deaths[faction]) + total_deaths[faction] = 0 + +/datum/entity/statistic_round/proc/track_new_participant(faction, amount = 1) if(!faction) return - if(!participants["[faction]"]) + + if(!participants[faction]) setup_faction(faction) - var/datum/entity/statistic/S = participants["[faction]"] - S.value += amount -/datum/entity/statistic/round/proc/track_final_participant(faction, amount = 1) + participants[faction] += amount + +/datum/entity/statistic_round/proc/track_final_participant(faction, amount = 1) if(!faction) return - if(!final_participants["[faction]"]) + + if(!final_participants[faction]) setup_faction(faction) - var/datum/entity/statistic/S = final_participants["[faction]"] - S.value += amount -/datum/entity/statistic/round/proc/track_round_end() + final_participants[faction] += amount + +/datum/entity/statistic_round/proc/track_round_end() real_time_end = world.realtime for(var/i in GLOB.alive_mob_list) var/mob/M = i - if(M.mind) + if(M.mind && M.faction) track_final_participant(M.faction) + if(current_map) + current_map.total_rounds++ + current_map.save() + save() - detach() -/datum/entity/statistic/round/proc/track_hijack_participant(faction, amount = 1) +/datum/entity/statistic_round/proc/track_hijack_participant(faction, amount = 1) if(!faction) return - if(!hijack_participants["[faction]"]) + + if(!hijack_participants[faction]) setup_faction(faction) - var/datum/entity/statistic/S = hijack_participants["[faction]"] - S.value += amount -/datum/entity/statistic/round/proc/track_hijack() + hijack_participants[faction] += amount + +/datum/entity/statistic_round/proc/track_hijack() for(var/i in GLOB.alive_mob_list) var/mob/M = i if(M.mind) track_hijack_participant(M.faction) + round_hijack_time = world.time save() - if(current_map) current_map.total_hijacks++ current_map.save() -/datum/entity/statistic/round/proc/track_dead_participant(faction, amount = 1) +/datum/entity/statistic_round/proc/track_dead_participant(faction, amount = 1) if(!faction) return - if(!total_deaths["[faction]"]) + + if(!total_deaths[faction]) setup_faction(faction) - var/datum/entity/statistic/S = total_deaths["[faction]"] - S.value += amount - -/datum/entity/statistic/round/proc/track_death(datum/entity/statistic/death/new_death) - if(new_death) - death_stats_list.Insert(1, new_death) - var/list/damage_list = list() - - if(new_death.total_brute > 0) - damage_list += list(list("name" = "brute", "value" = new_death.total_brute)) - if(new_death.total_burn > 0) - damage_list += list(list("name" = "burn", "value" = new_death.total_burn)) - if(new_death.total_oxy > 0) - damage_list += list(list("name" = "oxy", "value" = new_death.total_oxy)) - if(new_death.total_tox > 0) - damage_list += list(list("name" = "tox", "value" = new_death.total_tox)) - - var/new_time_of_death - if(new_death.time_of_death) - new_time_of_death = duration2text(new_death.time_of_death) - var/new_total_time_alive - if(new_death.total_time_alive) - new_total_time_alive = duration2text(new_death.total_time_alive) - - var/death = list(list( - "mob_name" = sanitize(new_death.mob_name), - "job_name" = new_death.role_name, - "area_name" = sanitize_area(new_death.area_name), - "cause_name" = sanitize_area(new_death.cause_name), - "total_kills" = new_death.total_kills, - "total_damage" = damage_list, - "time_of_death" = new_time_of_death, - "total_time_alive" = new_total_time_alive, - "total_damage_taken" = new_death.total_damage_taken, - "x" = new_death.x, - "y" = new_death.y, - "z" = new_death.z - )) - var/list/new_death_list = list() - if(death_data["death_stats_list"]) - new_death_list = death_data["death_stats_list"] - new_death_list.Insert(1, death) - if(length(new_death_list) > STATISTICS_DEATH_LIST_LEN) - new_death_list.Cut(STATISTICS_DEATH_LIST_LEN+1, length(new_death_list)) - death_data["death_stats_list"] = new_death_list - track_dead_participant(new_death.faction_name) - -/datum/entity/statistic/round/proc/store_caste_evo_data() + total_deaths[faction] += amount + + +/datum/entity/statistic_round/proc/store_caste_evo_data() if(!istype(SSticker.mode, /datum/game_mode/colonialmarines)) return - var/datum/entity/round_caste_picks/caste_picks = SSentity_manager.tables[/datum/entity/round_caste_picks].make_new() + var/datum/entity/round_caste_picks/caste_picks = DB_ENTITY(/datum/entity/round_caste_picks) caste_picks.castes_picked = castes_evolved caste_picks.save() -/datum/entity/statistic/round/proc/log_round_statistics() +/datum/entity/statistic_round/proc/log_round_statistics() + save() if(!GLOB.round_stats) return @@ -328,46 +209,39 @@ var/total_xenos_created = 0 var/total_predators_spawned = 0 - var/total_predaliens = 0 + var/total_predaliens_spawned = 0 var/total_humans_created = 0 for(var/statistic in participants) - var/datum/entity/statistic/S = participants[statistic] - if(S.name in FACTION_LIST_XENOMORPH) - total_xenos_created += S.value - else if(S.name == FACTION_YAUTJA) - total_predators_spawned += S.value - else if(S.name == FACTION_PREDALIEN) - total_predators_spawned += S.value + if(statistic in FACTION_LIST_XENOMORPH) + total_xenos_created += participants[statistic] + if(statistic == FACTION_PREDALIEN) + total_predaliens_spawned += hijack_participants[statistic] + else if(statistic == FACTION_YAUTJA) + total_predators_spawned += participants[statistic] else - total_humans_created += S.value + total_humans_created += participants[statistic] var/xeno_count_during_hijack = 0 var/human_count_during_hijack = 0 for(var/statistic in hijack_participants) - var/datum/entity/statistic/S = hijack_participants[statistic] - if(S.name in FACTION_LIST_XENOMORPH) - xeno_count_during_hijack += S.value - else if(S.name == FACTION_PREDALIEN) - xeno_count_during_hijack += S.value - else if(S.name == FACTION_YAUTJA) + if(statistic == FACTION_PREDALIEN || (statistic in FACTION_LIST_XENOMORPH)) + xeno_count_during_hijack += hijack_participants[statistic] + else if(statistic == FACTION_YAUTJA) continue else - human_count_during_hijack += S.value + human_count_during_hijack += hijack_participants[statistic] var/end_of_round_marines = 0 var/end_of_round_xenos = 0 for(var/statistic in final_participants) - var/datum/entity/statistic/S = final_participants[statistic] - if(S.name in FACTION_LIST_XENOMORPH) - end_of_round_xenos += S.value - else if(S.name == FACTION_PREDALIEN) - end_of_round_xenos += S.value - else if(S.name == FACTION_YAUTJA) + if(statistic == FACTION_PREDALIEN || (statistic in FACTION_LIST_XENOMORPH)) + end_of_round_xenos += final_participants[statistic] + else if(statistic == FACTION_YAUTJA) continue else - end_of_round_marines += S.value + end_of_round_marines += final_participants[statistic] var/stats = "" stats += "[SSticker.mode.round_finished]\n" @@ -377,8 +251,10 @@ stats += "End round player population: [end_round_player_population]\n" stats += "Total xenos spawned: [total_xenos_created]\n" - stats += "Total preds spawned: [total_predators_spawned]\n" - stats += "Total predaliens spawned: [total_predaliens]\n" + if(total_predators_spawned) + stats += "Total Preds spawned: [total_predators_spawned]\n" + if(total_predaliens_spawned) + stats += "Total Predaliens spawned: [total_predaliens_spawned]\n" stats += "Total humans spawned: [total_humans_created]\n" stats += "Xeno count during hijack: [xeno_count_during_hijack]\n" @@ -389,6 +265,7 @@ stats += "Total shots fired: [total_projectiles_fired]\n" stats += "Total friendly fire instances: [total_friendly_fire_instances]\n" + stats += "Total friendly kills: [total_friendly_kills]\n" stats += "Marines remaining: [end_of_round_marines]\n" stats += "Xenos remaining: [end_of_round_xenos]\n" @@ -405,14 +282,14 @@ if(!..()) return FALSE - if(!owner.client || !owner.client.player_entity) + if(!owner.client || !owner?.client?.player_data?.player_entity) return FALSE - return TRUE /datum/action/show_round_statistics/action_activate() . = ..() + if(!can_use_action()) return - owner.client.player_entity.show_statistics(owner, GLOB.round_statistics, TRUE) + owner.client.player_data.player_entity.tgui_interact(owner) diff --git a/code/datums/statistics/entities/weapon_stats.dm b/code/datums/statistics/entities/weapon_stats.dm deleted file mode 100644 index 9fff5c514458..000000000000 --- a/code/datums/statistics/entities/weapon_stats.dm +++ /dev/null @@ -1,49 +0,0 @@ -/datum/entity/weapon_stats - var/datum/entity/player - var/list/niche_stats = list() //! Indexed list of /datum/entity/statistic, "Total Reloads" = number - var/list/humans_killed = list() //! Indexed list of /datum/entity/statistic, "jobname2" = number - var/list/xenos_killed = list() //! Indexed list of /datum/entity/statistic, "caste" = number - var/name - var/total_kills = 0 - var/total_hits - var/total_shots - var/total_shots_hit - var/total_friendly_fire - var/display_stat = TRUE - -/datum/entity/weapon_stats/Destroy(force) - player = null - QDEL_LIST_ASSOC_VAL(niche_stats) - QDEL_LIST_ASSOC_VAL(humans_killed) - QDEL_LIST_ASSOC_VAL(xenos_killed) - return ..() - -/datum/entity/weapon_stats/proc/count_human_kill(job_name) - if(!job_name) - return - if(!humans_killed["[job_name]"]) - var/datum/entity/statistic/N = new() - N.name = job_name - humans_killed["[job_name]"] = N - var/datum/entity/statistic/S = humans_killed["[job_name]"] - S.value++ - -/datum/entity/weapon_stats/proc/count_xeno_kill(caste) - if(!caste) - return - if(!xenos_killed["[caste]"]) - var/datum/entity/statistic/N = new() - N.name = caste - xenos_killed["[caste]"] = N - var/datum/entity/statistic/S = xenos_killed["[caste]"] - S.value++ - -/datum/entity/weapon_stats/proc/count_niche_stat(niche_name, amount = 1) - if(!niche_name) - return - if(!niche_stats["[niche_name]"]) - var/datum/entity/statistic/N = new() - N.name = niche_name - niche_stats["[niche_name]"] = N - var/datum/entity/statistic/S = niche_stats["[niche_name]"] - S.value += amount diff --git a/code/datums/statistics/entities/xeno_death.dm b/code/datums/statistics/entities/xeno_death.dm index 2581163d12ac..db9f68da8671 100644 --- a/code/datums/statistics/entities/xeno_death.dm +++ b/code/datums/statistics/entities/xeno_death.dm @@ -47,7 +47,8 @@ round_id = GLOB.round_id || -1 kill_count = dead_xeno.life_kills_total || 0 - SSticker?.mode?.round_stats?.xeno_deaths += src + if(GLOB.round_statistics) + GLOB.round_statistics.xeno_deaths += src save() /datum/entity_meta/xeno_death diff --git a/code/datums/statistics/entities/xeno_stats.dm b/code/datums/statistics/entities/xeno_stats.dm deleted file mode 100644 index 9703c8c5e397..000000000000 --- a/code/datums/statistics/entities/xeno_stats.dm +++ /dev/null @@ -1,171 +0,0 @@ -/datum/entity/player_stats/xeno - var/total_hits = 0 - var/datum/entity/player_stats/caste/top_caste = null // reference to /datum/entity/player_stats/caste (i.e. ravager) - var/list/caste_stats_list = list() // list of types /datum/entity/player_stats/caste - var/list/datum/entity/statistic/medal/medal_list = list() // list of all royal jelly earned - -/datum/entity/player_stats/xeno/Destroy(force) - . = ..() - QDEL_NULL(top_caste) - QDEL_LIST_ASSOC_VAL(caste_stats_list) - QDEL_LIST(medal_list) - -/datum/entity/player_stats/xeno/get_playtime(type) - if(!type || type == FACTION_XENOMORPH) - return ..() - if(!caste_stats_list["[type]"]) - return 0 - var/datum/entity/player_stats/caste/S = caste_stats_list["[type]"] - return S.get_playtime() - -//****************** -//Stat Procs - setup -//****************** - -/datum/entity/player_stats/xeno/proc/setup_caste_stats(caste, noteworthy = TRUE) - if(!caste) - return - var/caste_key = strip_improper(caste) - if(caste_stats_list["[caste_key]"]) - var/datum/entity/player_stats/caste/S = caste_stats_list["[caste_key]"] - if(!S.display_stat && noteworthy) - S.display_stat = noteworthy - return S - var/datum/entity/player_stats/caste/new_stat = new() - new_stat.display_stat = noteworthy - new_stat.player = player - new_stat.name = caste_key - caste_stats_list["[caste_key]"] = new_stat - return new_stat - -//****************** -//Stat Procs - death -//****************** - -/mob/living/carbon/xenomorph/track_death_calculations() - if(statistic_exempt || statistic_tracked || !mind || !mind.player_entity) - return - var/datum/entity/player_stats/xeno/xeno_stats = mind.setup_xeno_stats() - if(isnull(xeno_stats)) - return - if(!xeno_stats.round_played) - xeno_stats.total_rounds_played++ - xeno_stats.round_played = TRUE - xeno_stats.total_playtime += life_time_total - xeno_stats.track_caste_playtime(caste_type, life_time_total) - xeno_stats.recalculate_top_caste() - xeno_stats.recalculate_nemesis() - ..() - -/datum/entity/player_stats/xeno/recalculate_nemesis() - for(var/caste_statistic in caste_stats_list) - var/datum/entity/player_stats/caste/caste_entity = caste_stats_list[caste_statistic] - caste_entity.recalculate_nemesis() - ..() - -/datum/entity/player_stats/xeno/proc/recalculate_top_caste() - for(var/statistics in caste_stats_list) - var/datum/entity/player_stats/caste/stat_entity = caste_stats_list[statistics] - if(!top_caste) - top_caste = stat_entity - continue - if(stat_entity.total_kills > top_caste.total_kills) - top_caste = stat_entity - -/datum/entity/player_stats/xeno/proc/track_caste_playtime(caste, time = 0) - var/datum/entity/player_stats/caste/S = setup_caste_stats(caste) - if(!S.round_played) - S.total_rounds_played++ - S.round_played = TRUE - S.total_playtime += time - if(GLOB.round_statistics) - var/datum/entity/player_stats/caste/R = GLOB.round_statistics.setup_caste_stats(caste) - R.total_playtime += time - -/datum/entity/player_stats/xeno/count_personal_death(caste) - var/datum/entity/player_stats/caste/S = setup_caste_stats(caste) - S.total_deaths++ - if(GLOB.round_statistics) - var/datum/entity/player_stats/caste/R = GLOB.round_statistics.setup_caste_stats(caste) - R.total_deaths++ - -//****************** -//Stat Procs - kills -//****************** - -/datum/entity/player_stats/xeno/count_personal_human_kill(job_name, cause, caste) - var/datum/entity/player_stats/caste/S = setup_caste_stats(caste) - S.count_human_kill(job_name, cause) - if(GLOB.round_statistics) - var/datum/entity/player_stats/caste/R = GLOB.round_statistics.setup_caste_stats(caste) - R.count_human_kill(job_name, cause) - recalculate_top_caste() - -/datum/entity/player_stats/xeno/count_personal_xeno_kill(caste_type, cause, caste) - var/datum/entity/player_stats/caste/S = setup_caste_stats(caste) - S.count_xeno_kill(caste_type, cause) - if(GLOB.round_statistics) - var/datum/entity/player_stats/caste/R = GLOB.round_statistics.setup_caste_stats(caste) - R.count_xeno_kill(caste_type, cause) - recalculate_top_caste() - -//***************** -//Mob Procs - minor -//***************** - -/datum/entity/player_stats/xeno/count_personal_niche_stat(niche_name, amount = 1, caste) - var/datum/entity/player_stats/caste/S = setup_caste_stats(caste) - S.count_niche_stat(niche_name, amount) - if(GLOB.round_statistics) - var/datum/entity/player_stats/caste/R = GLOB.round_statistics.setup_caste_stats(caste) - R.count_niche_stat(niche_name, amount) - -/datum/entity/player_stats/xeno/proc/track_personal_abilities_used(caste, ability, amount = 1) - var/datum/entity/player_stats/caste/S = setup_caste_stats(caste) - S.track_personal_abilities_used(ability, amount) - if(GLOB.round_statistics) - var/datum/entity/player_stats/caste/R = GLOB.round_statistics.setup_caste_stats(caste) - R.track_personal_abilities_used(ability, amount) - -/mob/living/carbon/xenomorph/proc/track_ability_usage(ability, caste, amount = 1) - if(statistic_exempt || !client || !mind) - return - var/datum/entity/player_stats/xeno/xeno_stats = mind.setup_xeno_stats() - if(caste_type && !isnull(xeno_stats)) - xeno_stats.track_personal_abilities_used(caste_type, ability, amount) - -/datum/entity/player_stats/xeno/count_personal_steps_walked(caste, amount = 1) - var/datum/entity/player_stats/caste/S = setup_caste_stats(caste) - S.steps_walked += amount - if(GLOB.round_statistics) - var/datum/entity/player_stats/caste/R = GLOB.round_statistics.setup_caste_stats(caste) - R.steps_walked += amount - -/mob/living/carbon/xenomorph/track_steps_walked(amount = 1) - if(statistic_exempt || !client || !mind) - return - var/datum/entity/player_stats/xeno/xeno_stats = mind.setup_xeno_stats() - if(isnull(xeno_stats)) - return - xeno_stats.steps_walked += amount - if(caste_type) - xeno_stats.count_personal_steps_walked(caste_type, amount) - -/datum/entity/player_stats/xeno/proc/count_personal_slashes(caste, amount = 1) - var/datum/entity/player_stats/caste/S = setup_caste_stats(caste) - S.total_hits += amount - if(GLOB.round_statistics) - var/datum/entity/player_stats/caste/R = GLOB.round_statistics.setup_caste_stats(caste) - R.total_hits += amount - -/mob/living/carbon/xenomorph/proc/track_slashes(caste, amount = 1) - if(statistic_exempt || !client || !mind) - return - var/datum/entity/player_stats/xeno/xeno_stats = mind.setup_xeno_stats() - if(isnull(xeno_stats)) - return - xeno_stats.total_hits += amount - if(caste_type) - xeno_stats.count_personal_slashes(caste_type, amount) - if(GLOB.round_statistics) - GLOB.round_statistics.total_slashes += amount diff --git a/code/datums/statistics/random_facts/damage_fact.dm b/code/datums/statistics/random_facts/damage_fact.dm index 2fa8a5d06491..c1be9f6d713f 100644 --- a/code/datums/statistics/random_facts/damage_fact.dm +++ b/code/datums/statistics/random_facts/damage_fact.dm @@ -5,5 +5,5 @@ /datum/random_fact/damage/life_grab_stat(mob/fact_mob) return fact_mob.life_damage_taken_total -/datum/random_fact/damage/death_grab_stat(datum/entity/statistic/death/fact_death) +/datum/random_fact/damage/death_grab_stat(datum/entity/statistic_death/fact_death) return fact_death.total_damage_taken diff --git a/code/datums/statistics/random_facts/ib_fact.dm b/code/datums/statistics/random_facts/ib_fact.dm index dca8c303b744..8d93bc755ef0 100644 --- a/code/datums/statistics/random_facts/ib_fact.dm +++ b/code/datums/statistics/random_facts/ib_fact.dm @@ -5,5 +5,5 @@ /datum/random_fact/ib/life_grab_stat(mob/fact_mob) return fact_mob.life_ib_total -/datum/random_fact/ib/death_grab_stat(datum/entity/statistic/death/fact_death) +/datum/random_fact/ib/death_grab_stat(datum/entity/statistic_death/fact_death) return fact_death.total_ib_fixed diff --git a/code/datums/statistics/random_facts/kills_fact.dm b/code/datums/statistics/random_facts/kills_fact.dm index 7ef1c2b238de..e6752c48b55a 100644 --- a/code/datums/statistics/random_facts/kills_fact.dm +++ b/code/datums/statistics/random_facts/kills_fact.dm @@ -5,5 +5,5 @@ /datum/random_fact/kills/life_grab_stat(mob/fact_mob) return fact_mob.life_kills_total -/datum/random_fact/kills/death_grab_stat(datum/entity/statistic/death/fact_death) +/datum/random_fact/kills/death_grab_stat(datum/entity/statistic_death/fact_death) return fact_death.total_kills diff --git a/code/datums/statistics/random_facts/random_fact.dm b/code/datums/statistics/random_facts/random_fact.dm index d327bd36f4f6..ae265a2155f0 100644 --- a/code/datums/statistics/random_facts/random_fact.dm +++ b/code/datums/statistics/random_facts/random_fact.dm @@ -21,14 +21,15 @@ /datum/random_fact/proc/calculate_announcement_message() var/death_stat_gotten = 0 var/living_stat_gotten = 0 - var/datum/entity/statistic/death/death_to_report = null + var/datum/entity/statistic_death/death_to_report = null var/mob/mob_to_report = null if(GLOB.round_statistics && length(GLOB.round_statistics.death_stats_list)) - for(var/datum/entity/statistic/death/death in GLOB.round_statistics.death_stats_list) - if(!check_human && !death.is_xeno) + for(var/datum/entity/statistic_death/death in GLOB.round_statistics.death_stats_list) + var/xeno_checked = death.faction_name in FACTION_LIST_XENOMORPH + if(!check_human && !xeno_checked) continue - if(!check_xeno && death.is_xeno) + if(!check_xeno && xeno_checked) continue if(death_stat_gotten < death_grab_stat(death)) death_to_report = death @@ -82,5 +83,5 @@ /datum/random_fact/proc/life_grab_stat(mob/fact_mob) return 0 -/datum/random_fact/proc/death_grab_stat(datum/entity/statistic/death/fact_death) +/datum/random_fact/proc/death_grab_stat(datum/entity/statistic_death/fact_death) return 0 diff --git a/code/datums/statistics/random_facts/revives_fact.dm b/code/datums/statistics/random_facts/revives_fact.dm index 60b6daa896d2..0430ef3598d0 100644 --- a/code/datums/statistics/random_facts/revives_fact.dm +++ b/code/datums/statistics/random_facts/revives_fact.dm @@ -5,5 +5,5 @@ /datum/random_fact/revives/life_grab_stat(mob/fact_mob) return fact_mob.life_revives_total -/datum/random_fact/revives/death_grab_stat(datum/entity/statistic/death/fact_death) +/datum/random_fact/revives/death_grab_stat(datum/entity/statistic_death/fact_death) return fact_death.total_revives_done diff --git a/code/datums/tutorial/ss13/_ss13.dm b/code/datums/tutorial/ss13/_ss13.dm index 53cf5c918ee9..91a6b7c612b8 100644 --- a/code/datums/tutorial/ss13/_ss13.dm +++ b/code/datums/tutorial/ss13/_ss13.dm @@ -27,7 +27,6 @@ if(tutorial_mob.mind) tutorial_mob.mind_initialize() tutorial_mob.mind.transfer_to(new_character, TRUE) - tutorial_mob.mind.setup_human_stats() INVOKE_ASYNC(new_character, TYPE_PROC_REF(/mob/living/carbon/human, regenerate_icons)) INVOKE_ASYNC(new_character, TYPE_PROC_REF(/mob/living/carbon/human, update_body), 1, 0) diff --git a/code/game/gamemodes/cm_initialize.dm b/code/game/gamemodes/cm_initialize.dm index cc127912f9c1..a320a2cfc85d 100644 --- a/code/game/gamemodes/cm_initialize.dm +++ b/code/game/gamemodes/cm_initialize.dm @@ -167,7 +167,6 @@ Additional game mode variables. if(player.client.prefs.get_job_priority(JOB_PREDATOR) > 0) //Are their prefs turned on? if(!player.mind) //They have to have a key if they have a client. player.mind_initialize() //Will work on ghosts too, but won't add them to active minds. - player.mind.setup_human_stats() player.faction = FACTION_YAUTJA player.faction_group = FACTION_LIST_YAUTJA players += player.mind @@ -440,7 +439,6 @@ Additional game mode variables. // Helper proc to set some constants /proc/setup_new_xeno(datum/mind/new_xeno) new_xeno.roundstart_picked = TRUE - new_xeno.setup_xeno_stats() /datum/game_mode/proc/check_xeno_late_join(mob/xeno_candidate) if(jobban_isbanned(xeno_candidate, JOB_XENOMORPH)) // User is jobbanned @@ -811,7 +809,6 @@ Additional game mode variables. new_xeno.SetSleeping(0) // ghosting sleeps, but they got a new mind! wake up! (/mob/living/verb/ghost()) new_xeno.mind_initialize() - new_xeno.mind.player_entity = setup_player_entity(xeno_candidate_mind.ckey) new_xeno.statistic_tracked = FALSE // Let the round recorder know that the key has changed @@ -1125,7 +1122,10 @@ Additional game mode variables. // for the toolbox /datum/game_mode/proc/end_round_message() - return "Extended round has ended." + if(round_finished) + return "Round has ended. [round_finished]." + else + return "Round has ended due to technical reasons." /datum/game_mode/proc/get_escape_menu() return "On the [SSmapping.configs[SHIP_MAP].map_name], orbiting..." diff --git a/code/game/gamemodes/cm_process.dm b/code/game/gamemodes/cm_process.dm index 1056e866744f..99a378e4de4b 100644 --- a/code/game/gamemodes/cm_process.dm +++ b/code/game/gamemodes/cm_process.dm @@ -1,5 +1,3 @@ - - /* Like with cm_initialize.dm, these procs exist to quickly populate classic CM game modes. Specifically for processing, announcing completion, and so on. Simply plug in these procs diff --git a/code/game/gamemodes/colonialmarines/colonialmarines.dm b/code/game/gamemodes/colonialmarines/colonialmarines.dm index 044d67fde7dc..aba2f4b895e5 100644 --- a/code/game/gamemodes/colonialmarines/colonialmarines.dm +++ b/code/game/gamemodes/colonialmarines/colonialmarines.dm @@ -12,8 +12,8 @@ #define GROUNDSIDE_XENO_MULTIPLIER 1.0 /datum/game_mode/colonialmarines - name = "Distress Signal" - config_tag = "Distress Signal" + name = MODE_NAME_DISTRESS_SIGNAL + config_tag = MODE_NAME_DISTRESS_SIGNAL required_players = 1 //Need at least one player, but really we need 2. xeno_required_num = 1 //Need at least one xeno. monkey_amount = 5 @@ -579,96 +579,61 @@ ////////////////////////////////////////////////////////////////////// /datum/game_mode/colonialmarines/declare_completion() - announce_ending() - var/musical_track + . = ..() + + declare_completion_announce_fallen_soldiers() + declare_completion_announce_xenomorphs() + declare_completion_announce_predators() + declare_completion_announce_medal_awards() + declare_fun_facts() + + + add_current_round_status_to_end_results("Round End") + handle_round_results_statistics_output() + +/datum/game_mode/colonialmarines/get_winners_states() + var/majority = 0.5 var/end_icon = "draw" + var/musical_track switch(round_finished) if(MODE_INFESTATION_X_MAJOR) musical_track = pick('sound/theme/sad_loss1.ogg','sound/theme/sad_loss2.ogg') end_icon = "xeno_major" - if(GLOB.round_statistics && GLOB.round_statistics.current_map) - GLOB.round_statistics.current_map.total_xeno_victories++ - GLOB.round_statistics.current_map.total_xeno_majors++ if(MODE_INFESTATION_M_MAJOR) musical_track = pick('sound/theme/winning_triumph1.ogg','sound/theme/winning_triumph2.ogg') end_icon = "marine_major" - if(GLOB.round_statistics && GLOB.round_statistics.current_map) - GLOB.round_statistics.current_map.total_marine_victories++ - GLOB.round_statistics.current_map.total_marine_majors++ if(MODE_INFESTATION_X_MINOR) var/list/living_player_list = count_humans_and_xenos(get_affected_zlevels()) if(living_player_list[1] && !living_player_list[2]) // If Xeno Minor but Xenos are dead and Humans are alive, see which faction is the last standing var/headcount = count_per_faction() var/living = headcount["total_headcount"] - if ((headcount["WY_headcount"] / living) > MAJORITY) + if ((headcount["WY_headcount"] / living) > majority) musical_track = pick('sound/theme/lastmanstanding_wy.ogg') log_game("3rd party victory: Weyland-Yutani") message_admins("3rd party victory: Weyland-Yutani") - else if ((headcount["UPP_headcount"] / living) > MAJORITY) + else if ((headcount["UPP_headcount"] / living) > majority) musical_track = pick('sound/theme/lastmanstanding_upp.ogg') log_game("3rd party victory: Union of Progressive Peoples") message_admins("3rd party victory: Union of Progressive Peoples") - else if ((headcount["CLF_headcount"] / living) > MAJORITY) + else if ((headcount["CLF_headcount"] / living) > majority) musical_track = pick('sound/theme/lastmanstanding_clf.ogg') log_game("3rd party victory: Colonial Liberation Front") message_admins("3rd party victory: Colonial Liberation Front") - else if ((headcount["marine_headcount"] / living) > MAJORITY) + else if ((headcount["marine_headcount"] / living) > majority) musical_track = pick('sound/theme/neutral_melancholy2.ogg') //This is the theme song for Colonial Marines the game, fitting else musical_track = pick('sound/theme/neutral_melancholy1.ogg') end_icon = "xeno_minor" - if(GLOB.round_statistics && GLOB.round_statistics.current_map) - GLOB.round_statistics.current_map.total_xeno_victories++ if(MODE_INFESTATION_M_MINOR) musical_track = pick('sound/theme/neutral_hopeful1.ogg','sound/theme/neutral_hopeful2.ogg') end_icon = "marine_minor" - if(GLOB.round_statistics && GLOB.round_statistics.current_map) - GLOB.round_statistics.current_map.total_marine_victories++ if(MODE_INFESTATION_DRAW_DEATH) end_icon = "draw" musical_track = 'sound/theme/neutral_hopeful2.ogg' - if(GLOB.round_statistics && GLOB.round_statistics.current_map) - GLOB.round_statistics.current_map.total_draws++ var/sound/S = sound(musical_track, channel = SOUND_CHANNEL_LOBBY) S.status = SOUND_STREAM sound_to(world, S) - if(GLOB.round_statistics) - GLOB.round_statistics.game_mode = name - GLOB.round_statistics.round_length = world.time - GLOB.round_statistics.round_result = round_finished - GLOB.round_statistics.end_round_player_population = length(GLOB.clients) - - GLOB.round_statistics.log_round_statistics() - - calculate_end_statistics() - show_end_statistics(end_icon) - - declare_completion_announce_fallen_soldiers() - declare_completion_announce_xenomorphs() - declare_completion_announce_predators() - declare_completion_announce_medal_awards() - declare_fun_facts() - - - add_current_round_status_to_end_results("Round End") - handle_round_results_statistics_output() - - return 1 - -// for the toolbox -/datum/game_mode/colonialmarines/end_round_message() - switch(round_finished) - if(MODE_INFESTATION_X_MAJOR) - return "Round has ended. Xeno Major Victory." - if(MODE_INFESTATION_M_MAJOR) - return "Round has ended. Marine Major Victory." - if(MODE_INFESTATION_X_MINOR) - return "Round has ended. Xeno Minor Victory." - if(MODE_INFESTATION_M_MINOR) - return "Round has ended. Marine Minor Victory." - if(MODE_INFESTATION_DRAW_DEATH) - return "Round has ended. Draw." - return "Round has ended in a strange way." + return list(end_icon) /datum/game_mode/colonialmarines/proc/add_current_round_status_to_end_results(special_round_status as text) var/players = GLOB.clients @@ -723,7 +688,7 @@ var/datum/discord_embed/embed = new() embed.title = "[SSperf_logging.round?.id]" - embed.description = "[round_stats.round_name]\n[round_stats.map_name]\n[end_round_message()]" + embed.description = "[GLOB.round_statistics.round_name]\n[GLOB.round_statistics.map_name]\n[end_round_message()]" var/list/webhook_info = list() webhook_info["embeds"] = list(embed.convert_to_list()) diff --git a/code/game/gamemodes/colonialmarines/huntergames.dm b/code/game/gamemodes/colonialmarines/huntergames.dm index 12a5fc9615ff..51ede27e1b50 100644 --- a/code/game/gamemodes/colonialmarines/huntergames.dm +++ b/code/game/gamemodes/colonialmarines/huntergames.dm @@ -86,8 +86,8 @@ //Digging through this is a pain. I'm leaving it mostly alone until a full rework takes place. /datum/game_mode/huntergames - name = "Hunter Games" - config_tag = "Hunter Games" + name = MODE_NAME_HUNTER_GAMES + config_tag = MODE_NAME_HUNTER_GAMES required_players = 1 flags_round_type = MODE_NO_LATEJOIN latejoin_larva_drop = 0 //You never know @@ -391,8 +391,8 @@ //Announces the end of the game with all relevant information stated// ////////////////////////////////////////////////////////////////////// /datum/game_mode/huntergames/declare_completion() - if(GLOB.round_statistics) - GLOB.round_statistics.track_round_end() + . = ..() + var/mob/living/carbon/winner = null for(var/mob/living/carbon/human/Q in GLOB.alive_mob_list) @@ -413,16 +413,6 @@ to_world("There was a winner, but they died before they could receive the prize!! Bummer.") world << 'sound/misc/sadtrombone.ogg' - if(GLOB.round_statistics) - GLOB.round_statistics.game_mode = name - GLOB.round_statistics.round_length = world.time - GLOB.round_statistics.end_round_player_population = count_humans() - - GLOB.round_statistics.log_round_statistics() - - - return 1 - /datum/game_mode/proc/auto_declare_completion_huntergames() return diff --git a/code/game/gamemodes/colonialmarines/whiskey_outpost.dm b/code/game/gamemodes/colonialmarines/whiskey_outpost.dm index aa9e56069b63..3fd77d207011 100644 --- a/code/game/gamemodes/colonialmarines/whiskey_outpost.dm +++ b/code/game/gamemodes/colonialmarines/whiskey_outpost.dm @@ -2,13 +2,13 @@ //Global proc for checking if the game is whiskey outpost so I dont need to type if(gamemode == whiskey outpost) 50000 times /proc/Check_WO() - if(SSticker.mode == GAMEMODE_WHISKEY_OUTPOST || GLOB.master_mode == GAMEMODE_WHISKEY_OUTPOST) + if(SSticker.mode == MODE_NAME_WISKEY_OUTPOST || GLOB.master_mode == MODE_NAME_WISKEY_OUTPOST) return 1 return 0 /datum/game_mode/whiskey_outpost - name = GAMEMODE_WHISKEY_OUTPOST - config_tag = GAMEMODE_WHISKEY_OUTPOST + name = MODE_NAME_WISKEY_OUTPOST + config_tag = MODE_NAME_WISKEY_OUTPOST required_players = 140 xeno_bypass_timer = 1 flags_round_type = MODE_NEW_SPAWN @@ -37,7 +37,6 @@ /datum/job/marine/standard/whiskey = JOB_SQUAD_MARINE, ) - latejoin_larva_drop = 0 //You never know //var/mob/living/carbon/human/Commander //If there is no Commander, marines wont get any supplies @@ -249,68 +248,51 @@ //Checks if the round is over// /////////////////////////////// /datum/game_mode/whiskey_outpost/check_finished() - if(finished != 0) - return 1 - - return 0 + if(round_finished) + return TRUE + return FALSE ////////////////////////////////////////////////////////////////////// //Announces the end of the game with all relevant information stated// ////////////////////////////////////////////////////////////////////// -/datum/game_mode/whiskey_outpost/declare_completion() - if(GLOB.round_statistics) - GLOB.round_statistics.track_round_end() - if(finished == 1) - log_game("Round end result - xenos won") - to_world(SPAN_ROUND_HEADER("The Xenos have successfully defended their hive from colonization.")) - to_world(SPAN_ROUNDBODY("Well done, you've secured LV-624 for the hive!")) - to_world(SPAN_ROUNDBODY("It will be another five years before the USCM returns to the Neroid Sector, with the arrival of the 2nd 'Falling Falcons' Battalion and the USS Almayer.")) - to_world(SPAN_ROUNDBODY("The xenomorph hive on LV-624 remains unthreatened until then...")) - world << sound('sound/misc/Game_Over_Man.ogg') - if(GLOB.round_statistics) - GLOB.round_statistics.round_result = MODE_INFESTATION_X_MAJOR - if(GLOB.round_statistics.current_map) - GLOB.round_statistics.current_map.total_xeno_victories++ - GLOB.round_statistics.current_map.total_xeno_majors++ - - else if(finished == 2) - log_game("Round end result - marines won") - to_world(SPAN_ROUND_HEADER("Against the onslaught, the marines have survived.")) - to_world(SPAN_ROUNDBODY("The signal rings out to the USS Alistoun, and Dust Raiders stationed elsewhere in the Neroid Sector begin to converge on LV-624.")) - to_world(SPAN_ROUNDBODY("Eventually, the Dust Raiders secure LV-624 and the entire Neroid Sector in 2182, pacifiying it and establishing peace in the sector for decades to come.")) - to_world(SPAN_ROUNDBODY("The USS Almayer and the 2nd 'Falling Falcons' Battalion are never sent to the sector and are spared their fate in 2186.")) - world << sound('sound/misc/hell_march.ogg') - if(GLOB.round_statistics) - GLOB.round_statistics.round_result = MODE_INFESTATION_M_MAJOR - if(GLOB.round_statistics.current_map) - GLOB.round_statistics.current_map.total_marine_victories++ - GLOB.round_statistics.current_map.total_marine_majors++ - - else - log_game("Round end result - no winners") - to_world(SPAN_ROUND_HEADER("NOBODY WON!")) - to_world(SPAN_ROUNDBODY("How? Don't ask me...")) - world << 'sound/misc/sadtrombone.ogg' - if(GLOB.round_statistics) - GLOB.round_statistics.round_result = MODE_INFESTATION_DRAW_DEATH - - if(GLOB.round_statistics) - GLOB.round_statistics.game_mode = name - GLOB.round_statistics.round_length = world.time - GLOB.round_statistics.end_round_player_population = length(GLOB.clients) - - GLOB.round_statistics.log_round_statistics() - - round_finished = 1 - - calculate_end_statistics() - - - return 1 +/datum/game_mode/whiskey_outpost/announce_ending() + log_game("Round end result: [round_finished]") + to_chat_spaced(world, margin_top = 2, type = MESSAGE_TYPE_SYSTEM, html = SPAN_ROUNDHEADER("|Round Complete|")) + switch(round_finished) + if(MODE_WISKEY_OUTPOST_M_MAJOR) + to_world(SPAN_ROUND_HEADER("Against the onslaught, the marines have survived.")) + to_world(SPAN_ROUNDBODY("The signal rings out to the USS Alistoun, and Dust Raiders stationed elsewhere in the Neroid Sector begin to converge on LV-624.")) + to_world(SPAN_ROUNDBODY("Eventually, the Dust Raiders secure LV-624 and the entire Neroid Sector in 2182, pacifiying it and establishing peace in the sector for decades to come.")) + to_world(SPAN_ROUNDBODY("The USS Almayer and the 2nd 'Falling Falcons' Battalion are never sent to the sector and are spared their fate in 2186.")) + if(MODE_WISKEY_OUTPOST_X_MAJOR) + to_world(SPAN_ROUND_HEADER("The Xenos have successfully defended their hive from colonization.")) + to_world(SPAN_ROUNDBODY("Well done, you've secured LV-624 for the hive!")) + to_world(SPAN_ROUNDBODY("It will be another five years before the USCM returns to the Neroid Sector, with the arrival of the 2nd 'Falling Falcons' Battalion and the USS Almayer.")) + to_world(SPAN_ROUNDBODY("The xenomorph hive on LV-624 remains unthreatened until then...")) + +/datum/game_mode/whiskey_outpost/get_winners_states() + var/end_icon = "draw" + var/musical_track + switch(round_finished) + if(MODE_WISKEY_OUTPOST_M_MAJOR) + musical_track = 'sound/misc/hell_march.ogg' + end_icon = "marine_major" + if(MODE_WISKEY_OUTPOST_X_MAJOR) + musical_track = 'sound/misc/Game_Over_Man.ogg' + end_icon = "xeno_major" + else + musical_track = 'sound/misc/sadtrombone.ogg' + if(GLOB.round_statistics) + GLOB.round_statistics.round_result = MODE_INFESTATION_DRAW_DEATH -/datum/game_mode/proc/auto_declare_completion_whiskey_outpost() - return + var/sound/S = sound(musical_track, channel = SOUND_CHANNEL_LOBBY) + S.status = SOUND_STREAM + sound_to(world, S) + return list(end_icon) +/////////////////////////////// +//Other WO things to simulate// +/////////////////////////////// /datum/game_mode/whiskey_outpost/proc/place_whiskey_outpost_drop(OT = "sup") //Art revamping spawns 13JAN17 var/turf/T = pick(supply_spawns) var/randpick diff --git a/code/game/gamemodes/colonialmarines/xenovsxeno.dm b/code/game/gamemodes/colonialmarines/xenovsxeno.dm index 4f9fdac4a4cc..880621824448 100644 --- a/code/game/gamemodes/colonialmarines/xenovsxeno.dm +++ b/code/game/gamemodes/colonialmarines/xenovsxeno.dm @@ -1,8 +1,8 @@ #define is_hive_living(hive) (!hive.hardcore || hive.living_xeno_queen) /datum/game_mode/xenovs - name = GAMEMODE_HIVE_WARS - config_tag = GAMEMODE_HIVE_WARS + name = MODE_NAME_HIVE_WARS + config_tag = MODE_NAME_HIVE_WARS required_players = 4 //Need at least 4 players xeno_required_num = 4 //Need at least four xenos. monkey_amount = 0.2 // Amount of monkeys per player @@ -218,7 +218,6 @@ if(istype(X) && is_hive_living(hive)) hivenumbers[hive.name].Add(X) - return hivenumbers /////////////////////////// @@ -247,48 +246,34 @@ else if (living_hives == 1) round_finished = "The [last_living_hive] has won." - /////////////////////////////// //Checks if the round is over// /////////////////////////////// /datum/game_mode/xenovs/check_finished() if(round_finished) return TRUE + return FALSE ////////////////////////////////////////////////////////////////////// //Announces the end of the game with all relevant information stated// ////////////////////////////////////////////////////////////////////// /datum/game_mode/xenovs/declare_completion() - announce_ending() + . = ..() + + declare_completion_announce_xenomorphs() + declare_fun_facts() + +/datum/game_mode/xenovs/get_winners_states() + var/end_icon = "xeno_major" var/musical_track musical_track = pick('sound/theme/neutral_melancholy1.ogg', 'sound/theme/neutral_melancholy2.ogg') var/sound/S = sound(musical_track, channel = SOUND_CHANNEL_LOBBY) S.status = SOUND_STREAM sound_to(world, S) - if(GLOB.round_statistics) - GLOB.round_statistics.game_mode = name - GLOB.round_statistics.round_length = world.time - GLOB.round_statistics.end_round_player_population = length(GLOB.clients) - - GLOB.round_statistics.log_round_statistics() - - declare_completion_announce_xenomorphs() - calculate_end_statistics() - declare_fun_facts() - - - return TRUE + return list(end_icon) /datum/game_mode/xenovs/announce_ending() - if(GLOB.round_statistics) - GLOB.round_statistics.track_round_end() log_game("Round end result: [round_finished]") to_chat_spaced(world, margin_top = 2, type = MESSAGE_TYPE_SYSTEM, html = SPAN_ROUNDHEADER("|Round Complete|")) to_chat_spaced(world, type = MESSAGE_TYPE_SYSTEM, html = SPAN_ROUNDBODY("Thus ends the story of the battling hives on [SSmapping.configs[GROUND_MAP].map_name]. [round_finished]\nThe game-mode was: [GLOB.master_mode]!\n[CONFIG_GET(string/endofroundblurb)]")) - -// for the toolbox -/datum/game_mode/xenovs/end_round_message() - if(round_finished) - return "Hive Wars Round has ended. [round_finished]" - return "Hive Wars Round has ended. No one has won" diff --git a/code/game/gamemodes/extended/extended.dm b/code/game/gamemodes/extended/extended.dm index 652d8af65a12..07f77226a311 100644 --- a/code/game/gamemodes/extended/extended.dm +++ b/code/game/gamemodes/extended/extended.dm @@ -1,6 +1,6 @@ /datum/game_mode/extended - name = "Extended" - config_tag = "Extended" + name = MODE_NAME_EXTENDED + config_tag = MODE_NAME_EXTENDED required_players = 0 latejoin_larva_drop = 0 votable = FALSE @@ -33,16 +33,11 @@ return /datum/game_mode/extended/declare_completion() - announce_ending() + . = ..() + var/musical_track = pick('sound/theme/neutral_hopeful1.ogg','sound/theme/neutral_hopeful2.ogg') world << musical_track - if(GLOB.round_statistics) - GLOB.round_statistics.game_mode = name - GLOB.round_statistics.round_length = world.time - GLOB.round_statistics.end_round_player_population = length(GLOB.clients) - GLOB.round_statistics.log_round_statistics() - calculate_end_statistics() declare_completion_announce_predators() declare_completion_announce_medal_awards() diff --git a/code/game/gamemodes/extended/extended_clash.dm b/code/game/gamemodes/extended/extended_clash.dm index 1cf2c448d410..7aea0ffc0a5e 100644 --- a/code/game/gamemodes/extended/extended_clash.dm +++ b/code/game/gamemodes/extended/extended_clash.dm @@ -1,6 +1,6 @@ /datum/game_mode/extended/faction_clash - name = "Faction Clash" - config_tag = "Faction Clash" + name = MODE_NAME_FACTION_CLASH + config_tag = MODE_NAME_FACTION_CLASH flags_round_type = MODE_THUNDERSTORM|MODE_FACTION_CLASH starting_round_modifiers = list(/datum/gamemode_modifier/blood_optimization, /datum/gamemode_modifier/defib_past_armor, /datum/gamemode_modifier/disable_combat_cas, /datum/gamemode_modifier/disable_ib, /datum/gamemode_modifier/disable_attacking_corpses, /datum/gamemode_modifier/disable_long_range_sentry, /datum/gamemode_modifier/disable_stripdrag_enemy, /datum/gamemode_modifier/indestructible_splints, /datum/gamemode_modifier/mortar_laser_warning, /datum/gamemode_modifier/no_body_c4) diff --git a/code/game/gamemodes/extended/extended_nospawn.dm b/code/game/gamemodes/extended/extended_nospawn.dm index 757721b94383..c1c8e050c51e 100644 --- a/code/game/gamemodes/extended/extended_nospawn.dm +++ b/code/game/gamemodes/extended/extended_nospawn.dm @@ -1,6 +1,6 @@ /datum/game_mode/extended/nospawn - name = "Extended - No Spawn" - config_tag = "Extended - No Spawn" + name = MODE_NAME_EXTENDED_NO_SPAWN + config_tag = MODE_NAME_EXTENDED_NO_SPAWN flags_round_type = MODE_NO_LATEJOIN|MODE_NO_SPAWN votable = FALSE diff --git a/code/game/gamemodes/extended/infection.dm b/code/game/gamemodes/extended/infection.dm index caef8717898f..bf7e99153790 100644 --- a/code/game/gamemodes/extended/infection.dm +++ b/code/game/gamemodes/extended/infection.dm @@ -1,7 +1,7 @@ //THIS IS A BLANK LABEL ONLY SO PEOPLE CAN SEE WHEN WE RUNNIN DIS BITCH. Should probably write a real one one day. Maybe. /datum/game_mode/infection - name = "Infection" - config_tag = "Infection" + name = MODE_NAME_INFECTION + config_tag = MODE_NAME_INFECTION required_players = 0 //otherwise... no zambies latejoin_larva_drop = 0 flags_round_type = MODE_INFECTION //Apparently without this, the game mode checker ignores this as a potential legit game mode. @@ -114,16 +114,11 @@ round_checkwin = 0 /datum/game_mode/infection/declare_completion() - announce_ending() + . = ..() + var/musical_track = pick('sound/theme/sad_loss1.ogg','sound/theme/sad_loss2.ogg') world << musical_track - if(GLOB.round_statistics) - GLOB.round_statistics.game_mode = name - GLOB.round_statistics.round_length = world.time - GLOB.round_statistics.end_round_player_population = length(GLOB.clients) - GLOB.round_statistics.log_round_statistics() - declare_completion_announce_xenomorphs() declare_completion_announce_predators() declare_completion_announce_medal_awards() diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 35ea20cb497e..84028e2727d1 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -11,8 +11,6 @@ * */ -GLOBAL_DATUM(round_statistics, /datum/entity/statistic/round) -GLOBAL_LIST_INIT_TYPED(player_entities, /datum/entity/player_entity, list()) GLOBAL_VAR_INIT(cas_tracking_id_increment, 0) //this var used to assign unique tracking_ids to tacbinos and signal flares /datum/game_mode var/name = "invalid" @@ -32,8 +30,6 @@ GLOBAL_VAR_INIT(cas_tracking_id_increment, 0) //this var used to assign unique t var/static_comms_amount = 0 var/obj/structure/machinery/computer/shuttle/dropship/flight/active_lz = null - var/datum/entity/statistic/round/round_stats = null - var/list/roles_to_roll var/corpses_to_spawn = 0 @@ -45,6 +41,7 @@ GLOBAL_VAR_INIT(cas_tracking_id_increment, 0) //this var used to assign unique t /datum/game_mode/New() ..() + initialize_gamemode_modifiers() if(taskbar_icon) GLOB.available_taskbar_icons |= taskbar_icon @@ -78,9 +75,8 @@ GLOBAL_VAR_INIT(cas_tracking_id_increment, 0) //this var used to assign unique t spawn_static_comms() if(corpses_to_spawn) generate_corpses() - initialize_gamemode_modifiers() SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MODE_PRESETUP) - return 1 + return TRUE ///Triggered partway through the first drop, based on DROPSHIP_DROP_MSG_DELAY. Marines are underway but haven't yet landed. /datum/game_mode/proc/ds_first_drop(obj/docking_port/mobile/marine_dropship) @@ -137,15 +133,11 @@ GLOBAL_VAR_INIT(cas_tracking_id_increment, 0) //this var used to assign unique t return /datum/game_mode/proc/announce_ending() - if(GLOB.round_statistics) - GLOB.round_statistics.track_round_end() log_game("Round end result: [round_finished]") to_chat_spaced(world, margin_top = 2, type = MESSAGE_TYPE_SYSTEM, html = SPAN_ROUNDHEADER("|Round Complete|")) to_chat_spaced(world, type = MESSAGE_TYPE_SYSTEM, html = SPAN_ROUNDBODY("Thus ends the story of the brave men and women of the [MAIN_SHIP_NAME] and their struggle on [SSmapping.configs[GROUND_MAP].map_name].\nThe game-mode was: [GLOB.master_mode]!\n[CONFIG_GET(string/endofroundblurb)]")) /datum/game_mode/proc/declare_completion() - if(GLOB.round_statistics) - GLOB.round_statistics.track_round_end() var/clients = 0 var/surviving_humans = 0 var/surviving_total = 0 @@ -172,8 +164,28 @@ GLOBAL_VAR_INIT(cas_tracking_id_increment, 0) //this var used to assign unique t if(surviving_total > 0) log_game("Round end - total: [surviving_total]") + announce_ending() - return 0 + var/list/winners_info = get_winners_states() + + if(GLOB.round_statistics) + var/datum/entity/statistic_round/round = GLOB.round_statistics + round.game_mode = name + round.round_length = world.time + round.round_result = round_finished + if(!length(round.current_map.victories)) + round.current_map.victories = list() + round.current_map.victories[round_finished]++ + round.end_round_player_population = length(GLOB.clients) + + round.log_round_statistics() + round.track_round_end() + + calculate_end_statistics() + show_end_statistics(winners_info[1]) + +/datum/game_mode/proc/get_winners_states() + return list("draw") /datum/game_mode/proc/calculate_end_statistics() for(var/i in GLOB.alive_mob_list) @@ -189,13 +201,13 @@ GLOBAL_VAR_INIT(cas_tracking_id_increment, 0) //this var used to assign unique t record_playtime(M.client.player_data, M.job, type) /datum/game_mode/proc/show_end_statistics(icon_state) - GLOB.round_statistics.update_panel_data() + GLOB.round_statistics.process() for(var/mob/M in GLOB.player_list) if(M.client) give_action(M, /datum/action/show_round_statistics, null, icon_state) /datum/game_mode/proc/check_win() //universal trigger to be called at mob death, nuke explosion, etc. To be called from everywhere. - return 0 + return FALSE /datum/game_mode/proc/get_players_for_role(role, override_jobbans = 0) var/list/players = list() diff --git a/code/game/jobs/job/antag/xeno/xenomorph.dm b/code/game/jobs/job/antag/xeno/xenomorph.dm index 1765d01e3c85..483adeff35e2 100644 --- a/code/game/jobs/job/antag/xeno/xenomorph.dm +++ b/code/game/jobs/job/antag/xeno/xenomorph.dm @@ -26,8 +26,6 @@ transform_to_xeno(H, XENO_HIVE_NORMAL) /datum/job/antag/xenos/proc/transform_to_xeno(mob/living/carbon/human/human_to_transform, hive_index) - var/datum/mind/new_xeno = human_to_transform.mind - new_xeno.setup_xeno_stats() var/datum/hive_status/hive = GLOB.hive_datum[hive_index] human_to_transform.first_xeno = TRUE diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index a06120b50f12..cbbc7c854ead 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -124,7 +124,7 @@ GLOBAL_LIST_INIT(airlock_wire_descriptions, list( if(damage >= damage_cap) if(M && istype(M)) - M.count_niche_stat(STATISTICS_NICHE_DESTRUCTION_DOORS, 1) + M.count_statistic_stat(STATISTICS_DESTRUCTION_DOORS) SEND_SIGNAL(M, COMSIG_MOB_DESTROY_AIRLOCK, src) to_chat(loc, SPAN_DANGER("[src] blows apart!")) deconstruct(FALSE) diff --git a/code/game/machinery/doors/runed_sandstone.dm b/code/game/machinery/doors/runed_sandstone.dm index c3c6fb5f2f40..33744cc65b21 100644 --- a/code/game/machinery/doors/runed_sandstone.dm +++ b/code/game/machinery/doors/runed_sandstone.dm @@ -211,7 +211,7 @@ if(damage >= damage_cap) if(M && istype(M)) - M.count_niche_stat(STATISTICS_NICHE_DESTRUCTION_DOORS, 1) + M.count_statistic_stat(STATISTICS_DESTRUCTION_DOORS) SEND_SIGNAL(M, COMSIG_MOB_DESTROY_AIRLOCK, src) to_chat(loc, SPAN_DANGER("[src] blows apart!")) deconstruct(FALSE) diff --git a/code/game/machinery/fusion_engine.dm b/code/game/machinery/fusion_engine.dm index 9398d33914a5..1a98bc03c7a1 100644 --- a/code/game/machinery/fusion_engine.dm +++ b/code/game/machinery/fusion_engine.dm @@ -332,6 +332,7 @@ return playsound(loc, 'sound/items/Ratchet.ogg', 25, 1) buildstate = BUILDSTATE_FUNCTIONAL + user.count_statistic_stat(STATISTICS_REPAIR_GENERATOR) update_icon() return diff --git a/code/game/objects/explosion_recursive.dm b/code/game/objects/explosion_recursive.dm index 708b3d25e43e..0a8f7f76345b 100644 --- a/code/game/objects/explosion_recursive.dm +++ b/code/game/objects/explosion_recursive.dm @@ -271,21 +271,21 @@ explosion resistance exactly as much as their health if(M.stat == DEAD) ff_living = FALSE msg_admin_ff(ff_msg, ff_living) - if(ishuman(firingMob)) - var/mob/living/carbon/human/H = firingMob - H.track_friendly_fire(explosion_source) + firingMob.track_friendly_damage(initial(name), M, severity) + firingMob.count_statistic_stat(STATISTICS_EXPLODED_MOBS) else M.attack_log += "\[[time_stamp()]\] [firingMob]/[firingMob.ckey] blew up [M]/[M.ckey] with \a [explosion_source] in [get_area(firingMob)]." firingMob:attack_log += "\[[time_stamp()]\] [firingMob]/[firingMob.ckey] blew up [M]/[M.ckey] with \a [explosion_source] in [get_area(firingMob)]." msg_admin_attack("[firingMob] ([firingMob.ckey]) blew up [M] ([M.ckey]) with \a [explosion_source] in [get_area(firingMob)] ([location_of_mob.z],[location_of_mob.y],[location_of_mob.z])", location_of_mob.x, location_of_mob.y, location_of_mob.z) + firingMob.track_damage(initial(name), M, severity) + firingMob.count_statistic_stat(STATISTICS_EXPLODED_MOBS) else if(explosion_source_mob) var/mob/firingMob = explosion_source_mob var/turf/location_of_mob = get_turf(firingMob) - if(ishuman(firingMob)) - var/mob/living/carbon/human/H = firingMob - H.track_shot_hit(initial(name), M) M.attack_log += "\[[time_stamp()]\] [firingMob] blew up [M]/[M.ckey] with a [explosion_source] in [get_area(firingMob)]." msg_admin_attack("[firingMob] ([firingMob.ckey]) blew up [M] ([M.ckey]) with \a [explosion_source] in [get_area(firingMob)] ([location_of_mob.z],[location_of_mob.y],[location_of_mob.z])", location_of_mob.x, location_of_mob.y, location_of_mob.z) + firingMob.track_damage(initial(name), M, severity) + firingMob.count_statistic_stat(STATISTICS_EXPLODED_MOBS) else if(explosion_source) M.attack_log += "\[[time_stamp()]\] [M]/[M.ckey] was blown up with a [explosion_source] in [get_area(M)]." else diff --git a/code/game/objects/items/devices/defibrillator.dm b/code/game/objects/items/devices/defibrillator.dm index 5aaa57b9abf8..040110164f6e 100644 --- a/code/game/objects/items/devices/defibrillator.dm +++ b/code/game/objects/items/devices/defibrillator.dm @@ -265,6 +265,7 @@ target.apply_damage(-damage_heal_threshold, TOX) target.apply_damage(-damage_heal_threshold, CLONE) target.apply_damage(-target.getOxyLoss(), OXY) + user.track_heal_damage(initial(name), target, damage_heal_threshold * 3) target.updatehealth() //Needed for the check to register properly if(!(target.species?.flags & NO_CHEM_METABOLIZATION)) diff --git a/code/game/objects/items/explosives/grenades/grenade.dm b/code/game/objects/items/explosives/grenades/grenade.dm index f157d7f8d931..f877ae287400 100644 --- a/code/game/objects/items/explosives/grenades/grenade.dm +++ b/code/game/objects/items/explosives/grenades/grenade.dm @@ -128,7 +128,7 @@ /obj/item/explosive/grenade/launch_towards(datum/launch_metadata/LM) if(active && ismob(LM.thrower)) var/mob/M = LM.thrower - M.count_niche_stat(STATISTICS_NICHE_GRENADES) + M.count_statistic_stat(STATISTICS_GRENADES) . = ..() diff --git a/code/game/objects/items/fulton.dm b/code/game/objects/items/fulton.dm index 5d11e86216e4..d8cfae266069 100644 --- a/code/game/objects/items/fulton.dm +++ b/code/game/objects/items/fulton.dm @@ -128,7 +128,7 @@ GLOBAL_LIST_EMPTY(deployed_fultons) transfer_fingerprints_to(F) src.add_fingerprint(user) F.add_fingerprint(user) - user.count_niche_stat(STATISTICS_NICHE_FULTON) + user.count_statistic_stat(STATISTICS_FULTON) use(1) F.faction = user.faction F.deploy_fulton() diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index 8ae49b347fe6..db83cda2df58 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -59,7 +59,7 @@ if(human_mob.has_limb_for_slot(WEAR_HANDCUFFS)) user.drop_inv_item_on_ground(src) human_mob.equip_to_slot_if_possible(src, WEAR_HANDCUFFS, 1, 0, 1, 1) - user.count_niche_stat(STATISTICS_NICHE_HANDCUFF) + user.count_statistic_stat(STATISTICS_HANDCUFF) else if(ismonkey(target)) user.visible_message(SPAN_NOTICE("[user] tries to put [src] on [target].")) diff --git a/code/game/objects/items/legcuffs.dm b/code/game/objects/items/legcuffs.dm index b5ea094c642e..b87b57ae06d8 100644 --- a/code/game/objects/items/legcuffs.dm +++ b/code/game/objects/items/legcuffs.dm @@ -37,7 +37,7 @@ if(human_target.has_limb_for_slot(WEAR_LEGCUFFS)) user.drop_inv_item_on_ground(src) human_target.equip_to_slot_if_possible(src, WEAR_LEGCUFFS, 1, 0, 1, 1) - user.count_niche_stat(STATISTICS_NICHE_HANDCUFF) + user.count_statistic_stat(STATISTICS_HANDCUFF) else if (ismonkey(target)) user.visible_message(SPAN_NOTICE("[user] tries to put [src] on [target].")) diff --git a/code/game/objects/items/reagent_containers/pill.dm b/code/game/objects/items/reagent_containers/pill.dm index 7f951ddc9ad3..bb484d53a77c 100644 --- a/code/game/objects/items/reagent_containers/pill.dm +++ b/code/game/objects/items/reagent_containers/pill.dm @@ -112,7 +112,7 @@ SPAN_HELPFUL("You fed [M] a pill."), SPAN_HELPFUL("[user] fed you a pill."), SPAN_NOTICE("[user] fed [M] a pill.")) - user.count_niche_stat(STATISTICS_NICHE_PILLS) + user.count_statistic_stat(STATISTICS_PILLS) var/rgt_list_text = get_reagent_list_text() diff --git a/code/game/objects/items/stacks/cable_coil.dm b/code/game/objects/items/stacks/cable_coil.dm index cb7140e34a75..5af44a12d689 100644 --- a/code/game/objects/items/stacks/cable_coil.dm +++ b/code/game/objects/items/stacks/cable_coil.dm @@ -331,6 +331,7 @@ return S.heal_damage(0, 15, TRUE) + user.track_heal_damage(initial(name), H, 15) H.pain.recalculate_pain() user.visible_message(SPAN_DANGER("\The [user] repairs some burn damage on \the [M]'s [S.display_name] with \the [src].")) return diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index fedb7b4c59cd..db3e40d49814 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -140,6 +140,7 @@ SPAN_HELPFUL("[user] salves the burns on your [affecting.display_name]."), SPAN_NOTICE("[user] salves the burns on [possessive_their] [affecting.display_name].")) affecting.heal_damage(burn = heal_burn) + user.track_heal_damage(initial(name), affecting, heal_burn) use(1) playsound(user, 'sound/handling/ointment_spreading.ogg', 25, 1, 2) if(WOUNDS_ALREADY_TREATED) @@ -191,6 +192,7 @@ if(SEND_SIGNAL(affecting, COMSIG_LIMB_ADD_SUTURES, TRUE, FALSE, heal_amt * 0.5)) heal_amt *= 0.5 affecting.heal_damage(brute = heal_amt) + user.track_heal_damage(initial(name), affecting, heal_amt) use(1) if(WOUNDS_ALREADY_TREATED) to_chat(user, SPAN_WARNING("The wounds on [possessive] [affecting.display_name] have already been treated.")) diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm index 608fe18bafb3..d07548eebbf4 100644 --- a/code/game/objects/items/stacks/nanopaste.dm +++ b/code/game/objects/items/stacks/nanopaste.dm @@ -26,6 +26,7 @@ if (S && (S.status & (LIMB_ROBOT|LIMB_SYNTHSKIN))) if(S.get_damage()) S.heal_damage(15, 15, robo_repair = 1) + user.track_heal_damage(initial(name), H, 30) H.pain.recalculate_pain() H.updatehealth() use(1) diff --git a/code/game/objects/items/storage/smartpack.dm b/code/game/objects/items/storage/smartpack.dm index d822d36c8809..0312dc90514f 100644 --- a/code/game/objects/items/storage/smartpack.dm +++ b/code/game/objects/items/storage/smartpack.dm @@ -91,7 +91,6 @@ playsound(src, 'sound/handling/light_on_1.ogg', 50, TRUE) update_icon(user) - /obj/item/storage/backpack/marine/smartpack/green item_state = "g_smartpack" icon_state = "g_smartpack" diff --git a/code/game/objects/items/tools/maintenance_tools.dm b/code/game/objects/items/tools/maintenance_tools.dm index fa3a9e932198..986a181558fb 100644 --- a/code/game/objects/items/tools/maintenance_tools.dm +++ b/code/game/objects/items/tools/maintenance_tools.dm @@ -265,6 +265,7 @@ return limb.heal_damage(15, 0, TRUE) + user.track_heal_damage(initial(name), human, 15) human.pain.recalculate_pain() human.UpdateDamageIcon() user.visible_message(SPAN_WARNING("\The [user] patches some dents on \the [human]'s [limb.display_name] with \the [src]."), diff --git a/code/game/objects/items/weapons/blades.dm b/code/game/objects/items/weapons/blades.dm index bb91e5c4fccf..a40081be87d4 100644 --- a/code/game/objects/items/weapons/blades.dm +++ b/code/game/objects/items/weapons/blades.dm @@ -202,10 +202,10 @@ embedded_human.embedded_items -= S organ = null for(var/i in 1 to S.count-1) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_SHRAPNEL) + user.count_statistic_stat(STATISTICS_SURGERY_SHRAPNEL) var/shrapnel = new S.type(S.loc) QDEL_IN(shrapnel, 300) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_SHRAPNEL) + user.count_statistic_stat(STATISTICS_SURGERY_SHRAPNEL) QDEL_IN(S, 300) if(length(removed_limbs)) diff --git a/code/game/objects/structures/barricade/barricade.dm b/code/game/objects/structures/barricade/barricade.dm index 072243899bd0..20cc85a40269 100644 --- a/code/game/objects/structures/barricade/barricade.dm +++ b/code/game/objects/structures/barricade/barricade.dm @@ -50,7 +50,7 @@ if(health != maxhealth) //Update cades mapped with a custom health update_health(0, TRUE) if(user) - user.count_niche_stat(STATISTICS_NICHE_CADES) + user.count_statistic_stat(STATISTICS_CADES) addtimer(CALLBACK(src, PROC_REF(update_icon)), 0) starting_maxhealth = maxhealth @@ -383,7 +383,7 @@ user.visible_message(SPAN_NOTICE("[user] repairs some damage on [src]."), SPAN_NOTICE("You repair [src].")) - user.count_niche_stat(STATISTICS_NICHE_REPAIR_CADES) + user.count_statistic_stat(STATISTICS_REPAIR_CADES) update_health(-200) playsound(src.loc, 'sound/items/Welder2.ogg', 25, TRUE) diff --git a/code/game/objects/structures/barricade/deployable.dm b/code/game/objects/structures/barricade/deployable.dm index 7963fa3c3566..ec21630540df 100644 --- a/code/game/objects/structures/barricade/deployable.dm +++ b/code/game/objects/structures/barricade/deployable.dm @@ -232,7 +232,7 @@ user.visible_message(SPAN_NOTICE("[user] repairs some damage on [src]."), SPAN_NOTICE("You repair [src].")) - user.count_niche_stat(STATISTICS_NICHE_REPAIR_CADES) + user.count_statistic_stat(STATISTICS_REPAIR_CADES) for(var/counter in 1 to length(stack_health)) stack_health[counter] += 200 diff --git a/code/game/objects/structures/barricade/non_folding.dm b/code/game/objects/structures/barricade/non_folding.dm index 79b6b9f63451..1d00a04beade 100644 --- a/code/game/objects/structures/barricade/non_folding.dm +++ b/code/game/objects/structures/barricade/non_folding.dm @@ -129,7 +129,7 @@ to_chat(user, SPAN_NOTICE("You applied a composite upgrade.")) metal.use(2) - user.count_niche_stat(STATISTICS_NICHE_UPGRADE_CADES) + user.count_statistic_stat(STATISTICS_UPGRADE_CADES) update_icon() return else @@ -169,7 +169,7 @@ to_chat(user, SPAN_NOTICE("You applied a composite upgrade.")) metal.use(2) - user.count_niche_stat(STATISTICS_NICHE_UPGRADE_CADES) + user.count_statistic_stat(STATISTICS_UPGRADE_CADES) update_icon() return diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index b1645fbc83d3..6d0748a987e2 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -105,7 +105,7 @@ return if(health <= 0) if(user && istype(user)) - user.count_niche_stat(STATISTICS_NICHE_DESTRUCTION_WINDOWS, 1) + user.count_statistic_stat(STATISTICS_DESTRUCTION_WINDOWS) SEND_SIGNAL(user, COMSIG_MOB_DESTROY_WINDOW, src) user.visible_message(SPAN_DANGER("[user] smashes through [src][AM ? " with [AM]":""]!")) if(is_mainship_level(z)) @@ -121,13 +121,22 @@ //Tasers and the like should not damage windows. var/ammo_flags = Proj.ammo.flags_ammo_behavior | Proj.projectile_override_flags if(Proj.ammo.damage_type == HALLOSS || Proj.damage <= 0 || ammo_flags == AMMO_ENERGY) - return 0 + return FALSE if(!not_damageable) //Impossible to destroy health -= Proj.damage + ..() healthcheck(user = Proj.firer) - return 1 + + if(health > 0) + return TRUE + + if(istype(Proj.firer, /mob)) + var/mob/user = Proj.firer + user.count_statistic_stat(STATISTICS_DESTRUCTION_WINDOWS) + + return TRUE /obj/structure/window/ex_act(severity, explosion_direction, datum/cause_data/cause_data) if(not_damageable) //Impossible to destroy @@ -146,7 +155,7 @@ create_shrapnel(location, rand(1,5), explosion_direction, shrapnel_type = /datum/ammo/bullet/shrapnel/light/glass, cause_data = cause_data) if(M) - M.count_niche_stat(STATISTICS_NICHE_DESTRUCTION_WINDOWS, 1) + M.count_statistic_stat(STATISTICS_DESTRUCTION_WINDOWS) SEND_SIGNAL(M, COMSIG_MOB_WINDOW_EXPLODED, src) handle_debris(severity, explosion_direction) @@ -542,7 +551,7 @@ return if(M) - M.count_niche_stat(STATISTICS_NICHE_DESTRUCTION_WINDOWS, 1) + M.count_statistic_stat(STATISTICS_DESTRUCTION_WINDOWS) SEND_SIGNAL(M, COMSIG_MOB_EXPLODE_W_FRAME, src) if(health >= -3000) diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index 789bbd12d56c..8bac658471e3 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -589,7 +589,7 @@ GLOBAL_DATUM_INIT(supply_controller, /datum/controller/supply, new()) COOLDOWN_START(src, next_fire, drop_cooldown) if(ismob(usr)) var/mob/M = usr - M.count_niche_stat(STATISTICS_NICHE_CRATES) + M.count_statistic_stat(STATISTICS_CRATES) playsound(crate.loc,'sound/effects/bamf.ogg', 50, 1) //Ehh var/obj/structure/droppod/supply/pod = new(null, crate) diff --git a/code/game/turfs/space.dm b/code/game/turfs/space.dm index 85d406e9f8ed..5c50e544e495 100644 --- a/code/game/turfs/space.dm +++ b/code/game/turfs/space.dm @@ -81,7 +81,7 @@ inertial_drift(A) - if(SSticker.mode) + if(SSticker.mode && length(SSmapping.levels_by_trait(ZTRAIT_GROUND))) // Okay, so let's make it so that people can travel z levels but not nuke disks! diff --git a/code/game/turfs/walls/walls.dm b/code/game/turfs/walls/walls.dm index ca6484aae8e1..874ae99b68af 100644 --- a/code/game/turfs/walls/walls.dm +++ b/code/game/turfs/walls/walls.dm @@ -204,7 +204,7 @@ if(damage >= damage_cap) if(M && istype(M)) - M.count_niche_stat(STATISTICS_NICHE_DESTRUCTION_WALLS, 1) + M.count_statistic_stat(STATISTICS_DESTRUCTION_WALLS) SEND_SIGNAL(M, COMSIG_MOB_DESTROY_WALL, src) // Xenos used to be able to crawl through the wall, should suggest some structural damage to the girder if (acided_hole) diff --git a/code/game/verbs/records.dm b/code/game/verbs/records.dm index 5303e79df6a1..533663c010be 100644 --- a/code/game/verbs/records.dm +++ b/code/game/verbs/records.dm @@ -187,7 +187,7 @@ GLOBAL_DATUM_INIT(medals_view_tgui, /datum/medals_view_tgui, new) . = ..() .["medals"] = list() - for(var/datum/view_record/medal_view/medal as anything in get_medals(user)) + for(var/datum/view_record/statistic_medal/medal as anything in get_medals(user)) var/xeno_medal = FALSE if(medal.medal_type in GLOB.xeno_medals) xeno_medal = TRUE @@ -206,7 +206,7 @@ GLOBAL_DATUM_INIT(medals_view_tgui, /datum/medals_view_tgui, new) .["medals"] += list(current_medal) /datum/medals_view_tgui/proc/get_medals(mob/user) - return DB_VIEW(/datum/view_record/medal_view, DB_COMP("player_id", DB_EQUALS, user.client.player_data.id)) + return DB_VIEW(/datum/view_record/statistic_medal, DB_COMP("player_id", DB_EQUALS, user.client.player_data.id)) /datum/medals_view_tgui/ui_state(mob/user) @@ -227,7 +227,7 @@ GLOBAL_DATUM_INIT(medals_view_given_tgui, /datum/medals_view_tgui/given_medals, /datum/medals_view_tgui/given_medals/get_medals(mob/user) - return DB_VIEW(/datum/view_record/medal_view, DB_COMP("giver_player_id", DB_EQUALS, user.client.player_data.id)) + return DB_VIEW(/datum/view_record/statistic_medal, DB_COMP("giver_player_id", DB_EQUALS, user.client.player_data.id)) /datum/medals_view_tgui/given_medals/tgui_interact(mob/user, datum/tgui/ui) diff --git a/code/game/world.dm b/code/game/world.dm index 45e06f4c0734..c687fdeb96b4 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -93,7 +93,7 @@ GLOBAL_LIST_INIT(reboot_sfx, file2list("config/reboot_sfx.txt")) // If the server's configured for local testing, get everything set up ASAP. // Shamelessly stolen from the test manager's host_tests() proc if(testing_locally) - GLOB.master_mode = "Extended" + GLOB.master_mode = MODE_NAME_EXTENDED // Wait for the game ticker to initialize while(!SSticker.initialized) diff --git a/code/modules/admin/player_panel/actions/general.dm b/code/modules/admin/player_panel/actions/general.dm index e4ebc9fb85dd..07b648cf0510 100644 --- a/code/modules/admin/player_panel/actions/general.dm +++ b/code/modules/admin/player_panel/actions/general.dm @@ -209,11 +209,11 @@ action_tag = "access_variables" name = "Access Variables" - /datum/player_action/access_variables/act(client/user, mob/target, list/params) user.debug_variables(target) return TRUE + /datum/player_action/access_playtimes action_tag = "access_playtimes" name = "Access Playtimes" @@ -224,6 +224,16 @@ return TRUE +/datum/player_action/access_statistics + action_tag = "access_statistics" + name = "Access Statistics" + +/datum/player_action/access_statistics/act(client/user, mob/target, list/params) + target?.client?.player_data?.player_entity.tgui_interact(user.mob) + + return TRUE + + /datum/player_action/access_admin_datum action_tag = "access_admin_datum" name = "Access Admin Datum" diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 380efa3cfdf3..0b067bce7368 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -303,9 +303,7 @@ M.ghostize() if(M.mind) - if(M.mind.player_entity) - M.track_death_calculations() - M.mind.player_entity = setup_player_entity(src.ckey) + M.track_death_calculations() M.statistic_tracked = FALSE usr.mind.transfer_to(M, TRUE) diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 3c9d7a9db1be..26b85735800b 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -69,8 +69,6 @@ var/xeno_postfix = "" var/xeno_name_ban = FALSE - var/datum/entity/player_entity/player_entity = null - //Asset cache // List of all asset filenames sent to this client by the asset cache, along with their assoicated md5s var/list/sent_assets = list() diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index dde6695448dc..fcee94b7920f 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -303,8 +303,6 @@ GLOBAL_LIST_INIT(whitelisted_client_procs, list( next_external_rsc = WRAP(next_external_rsc+1, 1, length(external_rsc_urls)+1) preload_rsc = external_rsc_urls[next_external_rsc] - player_entity = setup_player_entity(ckey) - if(check_localhost_status()) var/datum/admins/admin = new("!localhost!", RL_HOST, ckey) admin.associate(src) @@ -544,19 +542,10 @@ GLOBAL_LIST_INIT(whitelisted_client_procs, list( return if(GLOB.player_entities["[ckey]"]) return GLOB.player_entities["[ckey]"] - var/datum/entity/player_entity/P = new() - P.ckey = ckey - P.name = ckey - GLOB.player_entities["[ckey]"] = P - // P.setup_save(ckey) - return P - -/proc/save_player_entities() - for(var/key_ref in GLOB.player_entities) - // var/datum/entity/player_entity/P = player_entities["[key_ref]"] - // P.save_statistics() - log_debug("STATISTICS: Statistics saving complete.") - message_admins("STATISTICS: Statistics saving complete.") + var/datum/player_entity/p_entity = new() + p_entity.ckey = ckey + GLOB.player_entities["[ckey]"] = p_entity + return p_entity /client/proc/clear_chat_spam_mute(warn_level = 1, message = FALSE, increase_warn = FALSE) if(talked > warn_level) @@ -824,12 +813,6 @@ GLOBAL_LIST_INIT(whitelisted_client_procs, list( total_xeno_playtime += get_job_playtime(src, JOB_XENOMORPH) - if(player_entity) - var/past_xeno_playtime = player_entity.get_playtime(STATISTIC_XENO) - if(past_xeno_playtime) - total_xeno_playtime += past_xeno_playtime - - cached_xeno_playtime = total_xeno_playtime return total_xeno_playtime diff --git a/code/modules/cm_marines/overwatch.dm b/code/modules/cm_marines/overwatch.dm index 7a8958e673de..64896ec5b299 100644 --- a/code/modules/cm_marines/overwatch.dm +++ b/code/modules/cm_marines/overwatch.dm @@ -926,7 +926,7 @@ busy = FALSE if(istype(T)) current_orbital_cannon.fire_ob_cannon(T, user, current_squad) - user.count_niche_stat(STATISTICS_NICHE_OB) + user.count_statistic_stat(STATISTICS_OB) /obj/structure/machinery/computer/overwatch/proc/handle_supplydrop() SHOULD_NOT_SLEEP(TRUE) @@ -974,7 +974,7 @@ COOLDOWN_START(current_squad, next_supplydrop, 500 SECONDS) if(ismob(usr)) var/mob/M = usr - M.count_niche_stat(STATISTICS_NICHE_CRATES) + M.count_statistic_stat(STATISTICS_CRATES) playsound(crate.loc,'sound/effects/bamf.ogg', 50, 1) //Ehh var/obj/structure/droppod/supply/pod = new(null, crate) diff --git a/code/modules/cm_tech/droppod/gear_access_point.dm b/code/modules/cm_tech/droppod/gear_access_point.dm index 608fd33e18f4..bc6470e50a41 100644 --- a/code/modules/cm_tech/droppod/gear_access_point.dm +++ b/code/modules/cm_tech/droppod/gear_access_point.dm @@ -43,9 +43,9 @@ return /obj/structure/techpod_vendor/proc/get_access_permission(mob/living/carbon/human/user) - if(SSticker.mode == GAMEMODE_WHISKEY_OUTPOST || GLOB.master_mode == GAMEMODE_WHISKEY_OUTPOST) //all WO has lifted access restrictions + if(SSticker.mode == MODE_NAME_WISKEY_OUTPOST || GLOB.master_mode == MODE_NAME_WISKEY_OUTPOST) //all WO has lifted access restrictions return TRUE - else if(SSticker.mode == "Distress Signal" || GLOB.master_mode == "Distress Signal") + else if(SSticker.mode.name == MODE_NAME_DISTRESS_SIGNAL || GLOB.master_mode == MODE_NAME_DISTRESS_SIGNAL) if(access_settings_override) //everyone allowed to grab stuff return TRUE else if(user.get_target_lock(faction_requirement)) //only it's faction group allowed diff --git a/code/modules/cm_tech/implements/ammo_kits.dm b/code/modules/cm_tech/implements/ammo_kits.dm index b77db20eeb00..85c3a6503ae9 100644 --- a/code/modules/cm_tech/implements/ammo_kits.dm +++ b/code/modules/cm_tech/implements/ammo_kits.dm @@ -41,6 +41,8 @@ uses-- playsound(get_turf(user), "sound/machines/fax.ogg", 5) + user.count_statistic_stat(STATISTICS_AMMO_CONVERTED) + if(uses <= 0) user.drop_held_item(src) qdel(src) diff --git a/code/modules/cm_tech/implements/engi_czsp.dm b/code/modules/cm_tech/implements/engi_czsp.dm index f1e9721f9197..cde167ab2bb0 100644 --- a/code/modules/cm_tech/implements/engi_czsp.dm +++ b/code/modules/cm_tech/implements/engi_czsp.dm @@ -52,4 +52,5 @@ D.forceMove(H.loc) H.drop_held_item(src) + user.count_statistic_stat(STATISTICS_UPGRADE_TURRETS) qdel(src) diff --git a/code/modules/cm_tech/implements/implants.dm b/code/modules/cm_tech/implements/implants.dm index 95b534ac0f63..10743fac53cf 100644 --- a/code/modules/cm_tech/implements/implants.dm +++ b/code/modules/cm_tech/implements/implants.dm @@ -92,12 +92,26 @@ /obj/item/device/implanter/attack_self(mob/user) ..() + + if(!uses || !implant_type) + return ..() + + if(LAZYISIN(user.implants, implant_type)) + to_chat(user, SPAN_WARNING("You already have this implant!")) + return + + if(length(user.implants) >= user.max_implants) + to_chat(user, SPAN_WARNING("You can't take any more implants!")) + return + implant(user, TRUE) /obj/item/device/implanter/proc/implant(mob/M, self_inject) if(uses <= 0) return + M.count_statistic_stat(STATISTICS_IMPLANTS_IMPLANTED) + if(LAZYISIN(M.implants, implant_type)) QDEL_NULL(M.implants[implant_type]) @@ -196,7 +210,9 @@ INVOKE_ASYNC(src, PROC_REF(revive), M) /obj/item/device/internal_implant/rejuv/proc/revive(mob/living/M) + M.track_revive() M.heal_all_damage() + M.count_statistic_stat(STATISTICS_REVIVED_BY_IMPLANT) for(var/i in stimulant_to_inject) var/reagent_id = i diff --git a/code/modules/desert_dam/motion_sensor/sensortower.dm b/code/modules/desert_dam/motion_sensor/sensortower.dm index a6127770908c..c951aebcf510 100644 --- a/code/modules/desert_dam/motion_sensor/sensortower.dm +++ b/code/modules/desert_dam/motion_sensor/sensortower.dm @@ -191,6 +191,7 @@ return FALSE playsound(loc, 'sound/items/Ratchet.ogg', 25, 1) buildstate = SENSORTOWER_BUILDSTATE_WORKING + user.count_statistic_stat(STATISTICS_REPAIR_SENSORTOWER) user.visible_message(SPAN_NOTICE("[user] repairs \the [src]'s tubing and plating."), SPAN_NOTICE("You repair \the [src]'s tubing and plating.")) update_icon() diff --git a/code/modules/events/inflation.dm b/code/modules/events/inflation.dm index b410d9795838..2ebdfc17d084 100644 --- a/code/modules/events/inflation.dm +++ b/code/modules/events/inflation.dm @@ -6,7 +6,7 @@ min_players = 1 max_occurrences = 1 // we can increase the number once there's more random events around - 3 is a good number alert_observers = FALSE - gamemode_blacklist = list(GAMEMODE_WHISKEY_OUTPOST, GAMEMODE_HIVE_WARS) + gamemode_blacklist = list(MODE_NAME_WISKEY_OUTPOST, MODE_NAME_HIVE_WARS) /datum/round_event/economy_inflation announce_when = 1 diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 89dcfac16426..271faf953e69 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -443,6 +443,7 @@ Works together with spawning an observer, noted above. /mob/proc/ghostize(can_reenter_corpse = TRUE, aghosted = FALSE) if(isaghost(src) || !key) return + if(aghosted) src.aghosted = TRUE @@ -470,13 +471,10 @@ Works together with spawning an observer, noted above. if(!can_reenter_corpse) away_timer = 300 //They'll never come back, so we can max out the timer right away. - if(GLOB.round_statistics) - GLOB.round_statistics.update_panel_data() track_death_calculations() //This needs to be done before mind is nullified if(ghost.mind) ghost.mind.original = ghost - else if(ghost.mind && ghost.mind.player_entity) //Use else here because track_death_calculations() already calls this. - ghost.mind.player_entity.update_panel_data(GLOB.round_statistics) + else if(ghost.client) ghost.mind.original = src mind = null @@ -525,8 +523,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/living/proc/do_ghost() if(stat == DEAD) - if(mind && mind.player_entity) - mind.player_entity.update_panel_data(GLOB.round_statistics) ghostize(TRUE) else var/list/options = list("Ghost", "Stay in body") @@ -1213,14 +1209,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp ref = WEAKREF(H) GLOB.data_core.manifest_modify(name, ref, null, null, "*Deceased*") - -/mob/dead/observer/verb/view_kill_feed() +/mob/dead/observer/verb/view_stats() set category = "Ghost.View" - set name = "View Kill Feed" - set desc = "View global kill statistics tied to the game." + set name = "View Statistic" + set desc = "View global and player statistics tied to the game." - if(GLOB.round_statistics) - GLOB.round_statistics.show_kill_feed(src) + if(client?.player_data?.player_entity) + client.player_data.player_entity.try_recalculate() + client.player_data.player_entity.tgui_interact(src) /mob/dead/observer/get_status_tab_items() . = ..() diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index fa7c7ec3176e..67bc4ec3d445 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -8,6 +8,8 @@ act = lowertext(act) var/list/key_emotes = GLOB.emote_list[act] + if(act == "scream") + track_scream() if(!length(key_emotes)) if(intentional && !force_silence) diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm index 0930d02f3601..b91aa0f59446 100644 --- a/code/modules/mob/living/brain/brain.dm +++ b/code/modules/mob/living/brain/brain.dm @@ -56,6 +56,4 @@ /mob/living/brain/synth/ghost() set desc = "Relinquish your sentience and visit the land of the past." - if(mind && mind.player_entity) - mind.player_entity.update_panel_data(GLOB.round_statistics) ghostize(TRUE) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 44f59d5cdfc6..2fa70db7a3d0 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -62,7 +62,12 @@ for(var/mob/M as anything in viewers(user, null)) if(M.client) M.show_message(text(SPAN_DANGER("[user] attacks [src]'s stomach wall with the [I.name]!")), SHOW_MESSAGE_AUDIBLE) - user.track_hit(initial(I.name)) + if(user.faction == faction) + user.track_friendly_hit(initial(I.name)) + user.track_friendly_damage(initial(I.name), src, d) + else + user.track_hit(initial(I.name)) + user.track_damage(initial(I.name), src, d) playsound(user.loc, 'sound/effects/attackblob.ogg', 25, 1) if(prob(max(4*(100*getBruteLoss()/maxHealth - 75),0))) //4% at 24% health, 80% at 5% health @@ -237,7 +242,7 @@ apply_effect(6, STUN)//This should work for now, more is really silly and makes you lay there forever apply_effect(6, WEAKEN) - count_niche_stat(STATISTICS_NICHE_SHOCK) + count_statistic_stat(STATISTICS_SHOCK) else src.visible_message( diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 86a903e0ce18..c3a78707329c 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1743,7 +1743,6 @@ if(new_player.mind) new_player.mind_initialize() new_player.mind.transfer_to(target, TRUE) - new_player.mind.setup_human_stats() target.sec_hud_set_ID() target.hud_set_squad() diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 8cd2901be9bc..a80149630926 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -144,7 +144,7 @@ for(var/turf/T in view()) turfs += T var/turf/target = pick(turfs) - count_niche_stat(STATISTICS_NICHE_DISCHARGE) + count_statistic_stat(STATISTICS_DISCHARGE) attack_log += "\[[time_stamp()]\] [key_name(src)] accidentally fired [held_weapon.name] in [get_area(src)] triggered by [key_name(attacking_mob)]." attacking_mob.attack_log += "\[[time_stamp()]\] [key_name(src)] accidentally fired [held_weapon.name] in [get_area(src)] triggered by [key_name(attacking_mob)]." diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 22fa985e06fa..335d970b2331 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -212,12 +212,15 @@ Contains most of the procs that are called when a mob is attacked by something var/damage = armor_damage_reduction(GLOB.marine_melee, I.force, armor, (weapon_sharp?30:0) + (weapon_edge?10:0)) // no penetration frm punches apply_damage(damage, I.damtype, affecting, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I) + if(user.faction == faction) + user.track_friendly_hit(initial(I.name)) + user.track_friendly_damage(initial(I.name), src, damage) + else + user.track_hit(initial(I.name)) + user.track_damage(initial(I.name), src, damage) if(damage > 5) last_damage_data = create_cause_data(initial(I.name), user) - user.track_hit(initial(I.name)) - if(user.faction == faction) - user.track_friendly_fire(initial(I.name)) var/bloody = FALSE if((I.damtype == BRUTE || I.damtype == HALLOSS) && prob(I.force*2 + 25)) @@ -326,11 +329,14 @@ Contains most of the procs that are called when a mob is attacked by something if (launch_meta_valid && ismob(LM.thrower)) var/mob/M = LM.thrower var/client/assailant = M.client + if(M.faction == faction) + M.track_friendly_hit(initial(O.name)) + M.track_friendly_damage(initial(O.name), src, damage) + else + M.track_hit(initial(O.name)) + M.track_damage(initial(O.name), src, damage) if (damage > 5) last_damage_mob = M - M.track_hit(initial(O.name)) - if (M.faction == faction) - M.track_friendly_fire(initial(O.name)) if (assailant) src.attack_log += text("\[[time_stamp()]\] Has been hit with \a [O], thrown by [key_name(M)]") M.attack_log += text("\[[time_stamp()]\] Hit [key_name(src)] with a thrown [O]") diff --git a/code/modules/mob/living/carbon/xenomorph/Evolution.dm b/code/modules/mob/living/carbon/xenomorph/Evolution.dm index 4f288af48fcf..410587309eeb 100644 --- a/code/modules/mob/living/carbon/xenomorph/Evolution.dm +++ b/code/modules/mob/living/carbon/xenomorph/Evolution.dm @@ -207,12 +207,12 @@ GLOBAL_LIST_EMPTY(deevolved_ckeys) // We prevent de-evolved people from being tracked for the rest of the round relating to T1s in order to prevent people // Intentionally de/re-evolving to mess with the stats gathered. We don't track t2/3 because it's a legit strategy to open // With a t1 into drone before de-evoing later to go t1 into another caste once survs are dead/capped - if(new_xeno.ckey && !((new_xeno.caste.caste_type in XENO_T1_CASTES) && (new_xeno.ckey in GLOB.deevolved_ckeys) && !(new_xeno.datum_flags & DF_VAR_EDITED))) + if(new_xeno.ckey && !((new_xeno.caste.caste_type in XENO_T1_CASTES) && (new_xeno.ckey in GLOB.deevolved_ckeys) && !(new_xeno.datum_flags & DF_VAR_EDITED)) && GLOB.round_statistics) var/caste_cleaned_key = lowertext(replacetext(castepick, " ", "_")) - if(!SSticker.mode?.round_stats.castes_evolved[caste_cleaned_key]) - SSticker.mode?.round_stats.castes_evolved[caste_cleaned_key] = 1 + if(!GLOB.round_statistics.castes_evolved[caste_cleaned_key]) + GLOB.round_statistics.castes_evolved[caste_cleaned_key] = 1 else - SSticker.mode?.round_stats.castes_evolved[caste_cleaned_key] += 1 + GLOB.round_statistics.castes_evolved[caste_cleaned_key] += 1 SEND_SIGNAL(src, COMSIG_XENO_EVOLVE_TO_NEW_CASTE, new_xeno) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm index 7d507d46d8fa..83d775798495 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm @@ -720,6 +720,7 @@ X.use_plasma(400) X.place_construction(T, structure_template) + X.count_statistic_stat(STATISTIC_XENO_STRUCTURES_BUILD) return ..() diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm index a31de2316925..18855009de5a 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/queen/queen_powers.dm @@ -196,48 +196,50 @@ return ..() /datum/action/xeno_action/activable/queen_heal/use_ability(atom/A, verbose) - var/mob/living/carbon/xenomorph/queen/X = owner - if(!X.check_state()) + var/mob/living/carbon/xenomorph/queen/user_xeno = owner + if(!user_xeno.check_state()) return if(!action_cooldown_check()) return - var/turf/T = get_turf(A) - if(!T) - to_chat(X, SPAN_WARNING("You must select a valid turf to heal around.")) + var/turf/target_turf = get_turf(A) + if(!target_turf) + to_chat(user_xeno, SPAN_WARNING("You must select a valid turf to heal around.")) return - if(X.loc.z != T.loc.z) - to_chat(X, SPAN_XENOWARNING("You are too far away to do this here.")) + if(user_xeno.loc.z != target_turf.loc.z) + to_chat(user_xeno, SPAN_XENOWARNING("You are too far away to do this here.")) return if(!check_and_use_plasma_owner()) return - for(var/mob/living/carbon/xenomorph/Xa in range(4, T)) - if(!X.can_not_harm(Xa)) + for(var/mob/living/carbon/xenomorph/target_xeno in range(4, target_turf)) + if(!user_xeno.can_not_harm(target_xeno)) continue - if(SEND_SIGNAL(Xa, COMSIG_XENO_PRE_HEAL) & COMPONENT_CANCEL_XENO_HEAL) + if(SEND_SIGNAL(target_xeno, COMSIG_XENO_PRE_HEAL) & COMPONENT_CANCEL_XENO_HEAL) if(verbose) - to_chat(X, SPAN_XENOMINORWARNING("You cannot heal [Xa]!")) + to_chat(user_xeno, SPAN_XENOMINORWARNING("You cannot heal [target_xeno]!")) continue - if(Xa == X) + if(target_xeno == user_xeno) continue - if(Xa.stat == DEAD || QDELETED(Xa)) + if(target_xeno.stat == DEAD || QDELETED(target_xeno)) continue - if(!Xa.caste.can_be_queen_healed) + if(!target_xeno.caste.can_be_queen_healed) continue - new /datum/effects/heal_over_time(Xa, Xa.maxHealth * 0.3, 2 SECONDS, 2) - Xa.flick_heal_overlay(3 SECONDS, "#D9F500") //it's already hard enough to gauge health without hp overlays! + var/amount_heal = target_xeno.maxHealth * 0.3 + user_xeno.track_heal_damage(null, target_xeno, amount_heal) + new /datum/effects/heal_over_time(target_xeno, amount_heal, 2 SECONDS, 2) + target_xeno.flick_heal_overlay(3 SECONDS, "#D9F500") //it's already hard enough to gauge health without hp overlays! apply_cooldown() - to_chat(X, SPAN_XENONOTICE("You channel your plasma to heal your sisters' wounds around this area.")) + to_chat(user_xeno, SPAN_XENONOTICE("You channel your plasma to heal your sisters' wounds around this area.")) return ..() /datum/action/xeno_action/onclick/manage_hive/proc/give_evo_points() diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm b/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm index 2c758177a24d..176a29b28502 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/xeno_action.dm @@ -61,9 +61,9 @@ /datum/action/xeno_action/proc/track_xeno_ability_stats() if(!owner) return + var/mob/living/carbon/xenomorph/xeno = owner - if (name && GLOB.round_statistics) - GLOB.round_statistics.track_ability_usage(name) + if(name) xeno.track_ability_usage(name, xeno.caste_type) /datum/action/xeno_action/can_use_action() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm b/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm index 8de39dc98548..da8ee430f808 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Facehugger.dm @@ -165,10 +165,11 @@ if(!did_hug) qdel(hugger) return - if(client) - client.player_data?.adjust_stat(PLAYER_STAT_FACEHUGS, STAT_CATEGORY_XENO, 1) + + track_ability_usage(STATISTICS_FACEHUGGE, caste_type, 1) hug_successful = TRUE timeofdeath = world.time + qdel(src) return did_hug @@ -183,7 +184,9 @@ age = XENO_NORMAL - total_facehugs = get_client_stat(client, PLAYER_STAT_FACEHUGS) + var/datum/entity/statistic/statistic = client?.player_data?.player_entity?.get_statistic(faction, STATISTIC_TYPE_CASTE_ABILITIES, caste_type, STATISTICS_FACEHUGGE) + if(statistic) + total_facehugs = statistic.value switch(total_facehugs) if(FACEHUG_TIER_1 to FACEHUG_TIER_2) age = XENO_MATURE diff --git a/code/modules/mob/living/carbon/xenomorph/damage_procs.dm b/code/modules/mob/living/carbon/xenomorph/damage_procs.dm index 11d65d1bb0ff..d6dd52325531 100644 --- a/code/modules/mob/living/carbon/xenomorph/damage_procs.dm +++ b/code/modules/mob/living/carbon/xenomorph/damage_procs.dm @@ -280,6 +280,10 @@ var/dmg = list("damage" = acid_blood_damage) if(SEND_SIGNAL(src, COMSIG_XENO_DEAL_ACID_DAMAGE, victim, dmg) & COMPONENT_BLOCK_DAMAGE) continue + if(faction == victim.faction) + track_friendly_damage("Acid", victim, acid_blood_damage) + else + track_damage("Acid", victim, acid_blood_damage) i++ victim.visible_message(SPAN_DANGER("\The [victim] is scalded with hissing green blood!"), SPAN_DANGER("You are splattered with sizzling blood! IT BURNS!")) diff --git a/code/modules/mob/living/carbon/xenomorph/hive_status.dm b/code/modules/mob/living/carbon/xenomorph/hive_status.dm index 324ca3402a80..54d65522f3e2 100644 --- a/code/modules/mob/living/carbon/xenomorph/hive_status.dm +++ b/code/modules/mob/living/carbon/xenomorph/hive_status.dm @@ -2,7 +2,7 @@ var/name = "Normal Hive" // Used for the faction of the xenomorph. Not recommended to modify. - var/internal_faction + var/internal_faction = FACTION_XENOMORPH /// Short Hive ID as string used in stats reporting var/reporting_id = "normal" @@ -1009,6 +1009,7 @@ name = "Corrupted Hive" reporting_id = "corrupted" hivenumber = XENO_HIVE_CORRUPTED + internal_faction = FACTION_XENOMORPH_CORRPUTED prefix = "Corrupted " color = "#80ff80" ui_color ="#4d994d" @@ -1036,6 +1037,7 @@ name = "Alpha Hive" reporting_id = "alpha" hivenumber = XENO_HIVE_ALPHA + internal_faction = FACTION_XENOMORPH_ALPHA prefix = "Alpha " color = "#ff4040" ui_color = "#992626" @@ -1047,6 +1049,7 @@ name = "Bravo Hive" reporting_id = "bravo" hivenumber = XENO_HIVE_BRAVO + internal_faction = FACTION_XENOMORPH_BRAVO prefix = "Bravo " color = "#ffff80" ui_color = "#99994d" @@ -1058,6 +1061,7 @@ name = "Charlie Hive" reporting_id = "charlie" hivenumber = XENO_HIVE_CHARLIE + internal_faction = FACTION_XENOMORPH_CHARLIE prefix = "Charlie " color = "#bb40ff" ui_color = "#702699" @@ -1069,6 +1073,7 @@ name = "Delta Hive" reporting_id = "delta" hivenumber = XENO_HIVE_DELTA + internal_faction = FACTION_XENOMORPH_DELTA prefix = "Delta " color = "#8080ff" ui_color = "#4d4d99" @@ -1080,6 +1085,7 @@ name = "Feral Hive" reporting_id = "feral" hivenumber = XENO_HIVE_FERAL + internal_faction = FACTION_XENOMORPH_FERAL prefix = "Feral " color = "#828296" ui_color = "#828296" @@ -1096,6 +1102,7 @@ name = "Forsaken Hive" reporting_id = "forsaken" hivenumber = XENO_HIVE_FORSAKEN + internal_faction = FACTION_XENOMORPH_FORSAKEN prefix = "Forsaken " color = "#cc8ec4" ui_color = "#cc8ec4" diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm index 2f383d6e3c3a..96b8314ece2f 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/drone/healer.dm @@ -128,6 +128,7 @@ face_atom(target_xeno) adjustBruteLoss(amount * damage_taken_mod) use_plasma(amount * 2) + track_heal_damage(null, target_xeno, amount * damage_taken_mod) updatehealth() new /datum/effects/heal_over_time(target_xeno, heal_amount = amount) target_xeno.xeno_jitter(1 SECONDS) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index d892c96b90a5..6737bbccc278 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -69,10 +69,12 @@ var/mob/M if(launch_meta_valid && ismob(LM.thrower)) M = LM.thrower - if(damage_done > 5) + if(M.faction == faction) + M.track_friendly_hit(initial(O.name)) + M.track_friendly_damage(initial(O.name), src, damage_done) + else M.track_hit(initial(O.name)) - if (M.faction == faction) - M.track_friendly_fire(initial(O.name)) + M.track_damage(initial(O.name), src, damage_done) var/client/assailant = M.client if(assailant) src.attack_log += text("\[[time_stamp()]\] Has been hit with \a [O], thrown by [key_name(M)]") diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 272bc289b2ec..b20d8ee513b7 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -105,7 +105,7 @@ if(last_damage_data) var/mob/user = last_damage_data.resolve_mob() if(user) - user.count_niche_stat(STATISTICS_NICHE_CAT) + user.count_statistic_stat(STATISTICS_CAT) /mob/living/simple_animal/cat/proc/handle_movement_target() turns_since_scan++ diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index 9f4f00a375ef..9e1074739aae 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -109,7 +109,7 @@ if(last_damage_data) var/mob/user = last_damage_data.resolve_mob() if(user) - user.count_niche_stat(STATISTICS_NICHE_CORGI) + user.count_statistic_stat(STATISTICS_CORGI) /obj/item/reagent_container/food/snacks/meat/corgi name = "Corgi meat" diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 23c24be44d01..46325a6efd03 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -147,7 +147,7 @@ if(last_damage_data) var/mob/user = last_damage_data.resolve_mob() if(user) - user.count_niche_stat(STATISTICS_NICHE_COW) + user.count_statistic_stat(STATISTICS_COW) /mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M as mob) if(!stat && M.a_intent == INTENT_DISARM && icon_state != icon_dead) @@ -257,7 +257,7 @@ GLOBAL_VAR_INIT(chicken_count, 0) if(last_damage_data) var/mob/user = last_damage_data.resolve_mob() if(user) - user.count_niche_stat(STATISTICS_NICHE_CHICKEN) + user.count_statistic_stat(STATISTICS_CHICKEN) /mob/living/simple_animal/chicken/attackby(obj/item/O as obj, mob/user as mob) if(istype(O, /obj/item/reagent_container/food/snacks/grown/wheat)) //feedin' dem chickens diff --git a/code/modules/mob/mob_verbs.dm b/code/modules/mob/mob_verbs.dm index 180882a00528..ea5a37506e4e 100644 --- a/code/modules/mob/mob_verbs.dm +++ b/code/modules/mob/mob_verbs.dm @@ -31,14 +31,14 @@ to_chat(usr, SPAN_DANGER("This mob type cannot throw items.")) return -/mob/verb/view_stats() +/mob/verb/view_playtimes() set category = "OOC.Records" set name = "View Playtimes" set desc = "View your playtimes." if(!SSentity_manager.ready) to_chat(src, "DB is still starting up, please wait") return - if(client && client.player_entity) + if(client?.player_data) client.player_data.tgui_interact(src) /mob/verb/toggle_high_toss() diff --git a/code/modules/mob/new_player/login.dm b/code/modules/mob/new_player/login.dm index 048bdeb361df..e502175d688c 100644 --- a/code/modules/mob/new_player/login.dm +++ b/code/modules/mob/new_player/login.dm @@ -117,6 +117,16 @@ client.player_data.tgui_interact(src) return TRUE + if("statistic") + if(!SSentity_manager.ready) + to_chat(src, SPAN_WARNING("DB is still starting up, please wait")) + return FALSE + + if(client?.player_data?.player_entity) + client.player_data.player_entity.try_recalculate() + client.player_data.player_entity.tgui_interact(src) + return TRUE + if("manifest") ViewManifest() return TRUE diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 1add99af6a5f..ee34e7884ff7 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -161,16 +161,17 @@ hive.stored_larva++ hive.hive_ui.update_burrowed_larva() - if(character.mind && character.mind.player_entity) - var/datum/entity/player_entity/player = character.mind.player_entity - if(player.get_playtime(STATISTIC_HUMAN) == 0 && player.get_playtime(STATISTIC_XENO) == 0) + if(character.mind && character.client.player_data) + var/list/xeno_playtimes = LAZYACCESS(character.client.player_data.playtime_data, "stored_xeno_playtime") + var/list/marine_playtimes = LAZYACCESS(character.client.player_data.playtime_data, "stored_human_playtime") + if(!xeno_playtimes && !marine_playtimes) msg_admin_niche("NEW JOIN: [key_name(character, 1, 1, 0)]. IP: [character.lastKnownIP], CID: [character.computer_id]") if(character.client) - var/client/client = character.client - if(client.player_data && client.player_data.playtime_loaded && length(client.player_data.playtimes) == 0) + var/client/C = character.client + if(C.player_data && C.player_data.playtime_loaded && length(C.player_data.playtimes) == 0) msg_admin_niche("NEW PLAYER: [key_name(character, 1, 1, 0)]. IP: [character.lastKnownIP], CID: [character.computer_id]") - if(client.player_data && client.player_data.playtime_loaded && ((round(client.get_total_human_playtime() DECISECONDS_TO_HOURS, 0.1)) <= CONFIG_GET(number/notify_new_player_age))) - msg_sea("NEW PLAYER: [key_name(character, 0, 1, 0)] only has [(round(client.get_total_human_playtime() DECISECONDS_TO_HOURS, 0.1))] hours as a human. Current role: [get_actual_job_name(character)] - Current location: [get_area(character)]") + if(C.player_data && C.player_data.playtime_loaded && ((round(C.get_total_human_playtime() DECISECONDS_TO_HOURS, 0.1)) <= 5)) + msg_sea("NEW PLAYER: [key_name(character, 0, 1, 0)] only has [(round(C.get_total_human_playtime() DECISECONDS_TO_HOURS, 0.1))] hours as a human. Current role: [character.job] - Current location: [get_area(character)]") character.client.init_verbs() qdel(src) diff --git a/code/modules/objectives/data_retrieval.dm b/code/modules/objectives/data_retrieval.dm index 96d82e0a8c36..5a017ad388ff 100644 --- a/code/modules/objectives/data_retrieval.dm +++ b/code/modules/objectives/data_retrieval.dm @@ -251,7 +251,7 @@ uploading = 1 objective.activate() to_chat(user, SPAN_NOTICE("You start uploading the data.")) - user.count_niche_stat(STATISTICS_NICHE_UPLOAD) + user.count_statistic_stat(STATISTICS_UPLOAD) /obj/structure/machinery/computer/objective/proc/check_if_usable(mob/living/user) if(!powered()) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 2334806fc9f7..ce6c360ae53d 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -781,7 +781,7 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list( if(do_after(user, 50 * user.get_skill_duration_multiplier(SKILL_ENGINEER), INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) user.visible_message(SPAN_NOTICE("[user] replaces [src]'s damaged frontal panel with a new one."), SPAN_NOTICE("You replace [src]'s damaged frontal panel with a new one.")) - user.count_niche_stat(STATISTICS_NICHE_REPAIR_APC) + user.count_statistic_stat(STATISTICS_REPAIR_APC) qdel(W) beenhit = 0 stat &= ~BROKEN diff --git a/code/modules/projectiles/guns/flamer/flamer.dm b/code/modules/projectiles/guns/flamer/flamer.dm index 42e42d6d0165..d8c93ad7b9e5 100644 --- a/code/modules/projectiles/guns/flamer/flamer.dm +++ b/code/modules/projectiles/guns/flamer/flamer.dm @@ -674,10 +674,12 @@ else to_chat(ignited_morb, SPAN_HIGHDANGER(msg)) - if(weapon_cause_data) - var/mob/SM = weapon_cause_data.resolve_mob() - if(istype(SM)) - SM.track_shot_hit(weapon_cause_data.cause_name) + var/mob/shoot_mob = weapon_cause_data?.resolve_mob() + if(shoot_mob) + if(shoot_mob.faction == ignited_morb.faction) + shoot_mob.track_friendly_damage(weapon_cause_data.cause_name, ignited_morb, firedamage) + else + shoot_mob.track_damage(weapon_cause_data.cause_name, ignited_morb, firedamage) RegisterSignal(SSdcs, COMSIG_GLOB_WEATHER_CHANGE, PROC_REF(update_in_weather_status)) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 293122fff181..3d47488a20a6 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -1058,6 +1058,14 @@ if(!stat && pain.feels_pain) emote("scream") to_chat(src, SPAN_HIGHDANGER("You scream in pain as the impact sends shrapnel into the wound!")) + + var/mob/shoot_mob = P.weapon_cause_data?.resolve_mob() + if(shoot_mob) + if(shoot_mob.faction == faction) + shoot_mob.track_friendly_damage(P.weapon_cause_data.cause_name, src, damage) + else + shoot_mob.track_damage(P.weapon_cause_data.cause_name, src, damage) + SEND_SIGNAL(P, COMSIG_POST_BULLET_ACT_HUMAN, src, damage, damage_result) //Deal with xeno bullets. @@ -1126,7 +1134,14 @@ return if(damage) + var/mob/shoot_mob = P.weapon_cause_data?.resolve_mob() //only apply the blood splatter if we do damage + if(shoot_mob) + if(shoot_mob.faction == faction) + shoot_mob.track_friendly_damage(P.weapon_cause_data.cause_name, src, damage) + else + shoot_mob.track_damage(P.weapon_cause_data.cause_name, src, damage) + handle_blood_splatter(get_dir(P.starting, loc)) apply_damage(damage_result,P.ammo.damage_type, P.def_zone) //Deal the damage. diff --git a/code/modules/reagents/chemistry_machinery/reagent_analyzer.dm b/code/modules/reagents/chemistry_machinery/reagent_analyzer.dm index 038e0098ec66..59ed3a3c4119 100644 --- a/code/modules/reagents/chemistry_machinery/reagent_analyzer.dm +++ b/code/modules/reagents/chemistry_machinery/reagent_analyzer.dm @@ -97,7 +97,7 @@ GLOB.chemical_data.save_new_properties(S.properties) if(S.chemclass >= CHEM_CLASS_SPECIAL && !GLOB.chemical_data.chemical_identified_list[S.id]) if(last_used) - last_used.count_niche_stat(STATISTICS_NICHE_CHEMS) + last_used.count_statistic_stat(STATISTICS_CHEMS) var/datum/chem_property/P = S.get_property(PROPERTY_DNA_DISINTEGRATING) if(P) if(GLOB.chemical_data.clearance_level >= S.gen_tier) diff --git a/code/modules/round_recording/round_recorder.dm b/code/modules/round_recording/round_recorder.dm index 8748b995aa6c..b973835a8328 100644 --- a/code/modules/round_recording/round_recorder.dm +++ b/code/modules/round_recording/round_recorder.dm @@ -32,7 +32,7 @@ map = SSmapping.configs[GROUND_MAP].map_name gamemode = GLOB.master_mode - round_name = GLOB.round_statistics.name + round_name = GLOB.round_statistics.round_name // Record the end time of the game and export the game history /datum/round_recorder/proc/end_game() diff --git a/code/modules/shuttle/shuttles/crashable/escape_shuttle.dm b/code/modules/shuttle/shuttles/crashable/escape_shuttle.dm index 6558d1aca381..6ad26fbfbfa0 100644 --- a/code/modules/shuttle/shuttles/crashable/escape_shuttle.dm +++ b/code/modules/shuttle/shuttles/crashable/escape_shuttle.dm @@ -102,6 +102,17 @@ air.explo_proof = TRUE air.unacidable = TRUE + for(var/mob/living/carbon/human/survived_human as anything in GLOB.alive_human_list) //check for lifeboats survivors + var/area/area = get_area(survived_human) + if(!survived_human) + continue + if(survived_human.stat != DEAD && (area in shuttle_areas)) + var/turf/turf = get_turf(survived_human) + if(!turf || is_mainship_level(turf.z)) + continue + to_chat(survived_human, "

[SPAN_CENTERBOLD("You have successfully left the [MAIN_SHIP_NAME]. You may now ghost and observe the rest of the round.")]
") + survived_human.count_statistic_stat(STATISTICS_ESCAPE) + /obj/docking_port/mobile/crashable/escape_shuttle/crash_check() . = ..() diff --git a/code/modules/shuttle/shuttles/crashable/lifeboats.dm b/code/modules/shuttle/shuttles/crashable/lifeboats.dm index 617ab0869afb..d31eb287722f 100644 --- a/code/modules/shuttle/shuttles/crashable/lifeboats.dm +++ b/code/modules/shuttle/shuttles/crashable/lifeboats.dm @@ -25,6 +25,7 @@ continue survivors++ to_chat(survived_human, "

[SPAN_CENTERBOLD("You have successfully left the [MAIN_SHIP_NAME]. You may now ghost and observe the rest of the round.")]
") + survived_human.count_statistic_stat(STATISTICS_ESCAPE) /// Port Aft Lifeboat (bottom-right, doors on its left side) /obj/docking_port/mobile/crashable/lifeboat/port diff --git a/code/modules/shuttles/shuttle_console.dm b/code/modules/shuttles/shuttle_console.dm index 447f4a1bf386..feb990325d5e 100644 --- a/code/modules/shuttles/shuttle_console.dm +++ b/code/modules/shuttles/shuttle_console.dm @@ -301,7 +301,7 @@ GLOBAL_LIST_EMPTY(shuttle_controls) message_all_yautja("The serpent Queen has commanded the landing shuttle to depart.") playsound(src, 'sound/misc/queen_alarm.ogg') - Q.count_niche_stat(STATISTICS_NICHE_FLIGHT) + Q.count_statistic_stat(STATISTICS_FLIGHT) if(Q.hive) addtimer(CALLBACK(Q.hive, TYPE_PROC_REF(/datum/hive_status, abandon_on_hijack)), DROPSHIP_WARMUP_TIME + 5 SECONDS, TIMER_UNIQUE) //+ 5 seconds catch standing in doorways @@ -328,7 +328,7 @@ GLOBAL_LIST_EMPTY(shuttle_controls) if(is_ground_level(z)) shuttle.transit_gun_mission = 0 //remote launch always do transport flight. shuttle.launch(src) if(onboard && !shuttle.iselevator) - M.count_niche_stat(STATISTICS_NICHE_FLIGHT) + M.count_statistic_stat(STATISTICS_FLIGHT) msg_admin_niche("[M] ([M.key]) launched \a [shuttle.iselevator? "elevator" : "shuttle"] using [src].") ui_interact(usr) diff --git a/code/modules/surgery/amputation.dm b/code/modules/surgery/amputation.dm index c9c1c92d4877..d71229f91d91 100644 --- a/code/modules/surgery/amputation.dm +++ b/code/modules/surgery/amputation.dm @@ -166,7 +166,7 @@ SPAN_WARNING("[user] cuts your [surgery.affected_limb.display_name] off!"), SPAN_NOTICE("[user] cuts [target]'s [surgery.affected_limb.display_name] off.")) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_AMPUTATE) + user.count_statistic_stat(STATISTICS_SURGERY_AMPUTATE) surgery.affected_limb.droplimb(amputation = TRUE, surgery_in_progress = TRUE) target.incision_depths[target_zone] = SURGERY_DEPTH_SURFACE log_interact(user, target, "[key_name(user)] successfully severed [key_name(target)]'s [surgery.affected_limb.display_name] with \the [tool].") @@ -191,7 +191,7 @@ SPAN_WARNING("[user] hacks [target]'s [surgery.affected_limb.display_name] off!")) user.animation_attack_on(target) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_AMPUTATE) + user.count_statistic_stat(STATISTICS_SURGERY_AMPUTATE) surgery.affected_limb.droplimb() //This will sever the limb messily and reset incision depth. The stump cleanup surgery will have to be done to properly amputate, but doing this saved two seconds. Worth it? target.apply_damage(20, BRUTE, surgery.affected_limb.parent) log_interact(user, target, "[key_name(user)] hacked [key_name(target)]'s [surgery.affected_limb.display_name] off with \the [tool], ending [surgery].") diff --git a/code/modules/surgery/bones.dm b/code/modules/surgery/bones.dm index 6cd35a775829..0074b9163d1d 100644 --- a/code/modules/surgery/bones.dm +++ b/code/modules/surgery/bones.dm @@ -200,7 +200,7 @@ SPAN_NOTICE("[user] sets the bones in your [surgery.affected_limb.display_name]."), SPAN_NOTICE("[user] sets the bones in [target]'s [surgery.affected_limb.display_name].")) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_BONES) + user.count_statistic_stat(STATISTICS_SURGERY_BONES) if(surgery.affected_limb.status & LIMB_SPLINTED_INDESTRUCTIBLE) new /obj/item/stack/medical/splint/nano(get_turf(target), 1) surgery.affected_limb.status &= ~(LIMB_SPLINTED|LIMB_SPLINTED_INDESTRUCTIBLE|LIMB_BROKEN) diff --git a/code/modules/surgery/brainrepair.dm b/code/modules/surgery/brainrepair.dm index 2b4e51292203..428aa624de38 100644 --- a/code/modules/surgery/brainrepair.dm +++ b/code/modules/surgery/brainrepair.dm @@ -51,7 +51,7 @@ SPAN_NOTICE("[user] finishes extracting fragments of bone from your brain."), SPAN_NOTICE("[user] finishes extracting fragments of bone from [target]'s brain.")) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_BRAIN) + user.count_statistic_stat(STATISTICS_SURGERY_BRAIN) var/datum/internal_organ/brain/B = target.internal_organs_by_name["brain"] if(B) diff --git a/code/modules/surgery/chestburster.dm b/code/modules/surgery/chestburster.dm index 731ea2017b94..aef193cf0d9b 100644 --- a/code/modules/surgery/chestburster.dm +++ b/code/modules/surgery/chestburster.dm @@ -166,7 +166,7 @@ else user.apply_damage(15, BURN, "r_hand") - user.count_niche_stat(STATISTICS_NICHE_SURGERY_LARVA) + user.count_statistic_stat(STATISTICS_SURGERY_LARVA) var/mob/living/carbon/xenomorph/larva/L = locate() in target //the larva was fully grown, ready to burst. if(L) L.forceMove(target.loc) diff --git a/code/modules/surgery/eye.dm b/code/modules/surgery/eye.dm index b9efb0371ee3..7e95a18166ea 100644 --- a/code/modules/surgery/eye.dm +++ b/code/modules/surgery/eye.dm @@ -167,7 +167,7 @@ target.disabilities &= ~NEARSIGHTED target.sdisabilities &= ~DISABILITY_BLIND surgery.target_eyes.heal_damage(surgery.target_eyes.damage) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_EYE) + user.count_statistic_stat(STATISTICS_SURGERY_EYE) target.pain.recalculate_pain() /datum/surgery_step/cauterize/eyes/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/eye_repair/surgery) diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm index 8f2e6156831a..622765826516 100644 --- a/code/modules/surgery/implant.dm +++ b/code/modules/surgery/implant.dm @@ -295,10 +295,10 @@ surgery.affected_limb.implants -= S target.embedded_items -= S for(var/i in 1 to S.count-1) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_SHRAPNEL) + user.count_statistic_stat(STATISTICS_SURGERY_SHRAPNEL) var/shrap = new S.type(S.loc) QDEL_IN(shrap, 30 SECONDS) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_SHRAPNEL) + user.count_statistic_stat(STATISTICS_SURGERY_SHRAPNEL) QDEL_IN(S, 30 SECONDS) else var/obj/item/obj = surgery.affected_limb.implants[1] @@ -318,7 +318,7 @@ if(is_sharp(obj)) target.embedded_items -= obj - user.count_niche_stat(STATISTICS_NICHE_SURGERY_SHRAPNEL) + user.count_statistic_stat(STATISTICS_SURGERY_SHRAPNEL) log_interact(user, target, "[key_name(user)] removed [obj] from [key_name(target)]'s [surgery.affected_limb.display_name] with \the [tool], ending [surgery].") else diff --git a/code/modules/surgery/internal_bleeding.dm b/code/modules/surgery/internal_bleeding.dm index c67d670ea521..bcf49b874cc6 100644 --- a/code/modules/surgery/internal_bleeding.dm +++ b/code/modules/surgery/internal_bleeding.dm @@ -38,7 +38,7 @@ log_interact(user, target, "[key_name(user)] began repairing internal bleeding in [key_name(target)]'s [surgery.affected_limb.display_name], beginning [surgery].") /datum/surgery_step/fix_vein/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, tool_type, datum/surgery/surgery) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_IB) + user.count_statistic_stat(STATISTICS_SURGERY_IB) user.life_ib_total++ user.affected_message(target, diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index c1708702524a..c4d10c065300 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -82,7 +82,7 @@ and organ transplant code which may come in handy in future but haven't been edi SPAN_NOTICE("[user] finishes treating your damaged [I.name]."), SPAN_NOTICE("[user] finishes treating [target]'s damaged [I.name].")) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_ORGAN_REPAIR) + user.count_statistic_stat(STATISTICS_SURGERY_ORGAN_REPAIR) I.rejuvenate() target.pain.recalculate_pain() break diff --git a/code/modules/surgery/robotic_organs_internal.dm b/code/modules/surgery/robotic_organs_internal.dm index f268b959d7ec..8b2399e89473 100644 --- a/code/modules/surgery/robotic_organs_internal.dm +++ b/code/modules/surgery/robotic_organs_internal.dm @@ -77,7 +77,7 @@ and organ transplant code which may come in handy in future but haven't been edi SPAN_NOTICE("[user] finishes treating your damaged [I.name]."), SPAN_NOTICE("[user] finishes treating [target]'s damaged [I.name].")) - user.count_niche_stat(STATISTICS_NICHE_SURGERY_ORGAN_REPAIR) + user.count_statistic_stat(STATISTICS_SURGERY_ORGAN_REPAIR) I.rejuvenate() break diff --git a/code/modules/vehicles/apc/apc_command.dm b/code/modules/vehicles/apc/apc_command.dm index 8d056daec2ea..493692241c83 100644 --- a/code/modules/vehicles/apc/apc_command.dm +++ b/code/modules/vehicles/apc/apc_command.dm @@ -182,9 +182,9 @@ //stole my own code from techpod_vendor /obj/vehicle/multitile/apc/command/proc/get_access_permission(mob/living/carbon/human/user) - if(SSticker.mode == GAMEMODE_WHISKEY_OUTPOST || GLOB.master_mode == GAMEMODE_WHISKEY_OUTPOST) + if(SSticker.mode == MODE_NAME_WISKEY_OUTPOST || GLOB.master_mode == MODE_NAME_WISKEY_OUTPOST) return TRUE - else if(SSticker.mode == "Distress Signal" || GLOB.master_mode == "Distress Signal") + else if(SSticker.mode.name == MODE_NAME_DISTRESS_SIGNAL || GLOB.master_mode == MODE_NAME_DISTRESS_SIGNAL) if(techpod_access_settings_override) return TRUE else if(user.get_target_lock(techpod_faction_requirement)) diff --git a/colonialmarines.dme b/colonialmarines.dme index 955fea187b2a..cfe620d7acde 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -102,7 +102,7 @@ #include "code\__DEFINES\sounds.dm" #include "code\__DEFINES\speech_channels.dm" #include "code\__DEFINES\stamina.dm" -#include "code\__DEFINES\stats.dm" +#include "code\__DEFINES\statistic.dm" #include "code\__DEFINES\status_effects.dm" #include "code\__DEFINES\strippable.dm" #include "code\__DEFINES\STUI.dm" @@ -666,21 +666,15 @@ #include "code\datums\stamina\_stamina.dm" #include "code\datums\stamina\none.dm" #include "code\datums\statistics\cause_data.dm" -#include "code\datums\statistics\entities\caste_stats.dm" #include "code\datums\statistics\entities\death_stats.dm" -#include "code\datums\statistics\entities\human_stats.dm" -#include "code\datums\statistics\entities\job_stats.dm" #include "code\datums\statistics\entities\map_stats.dm" #include "code\datums\statistics\entities\medal_stats.dm" #include "code\datums\statistics\entities\panel_stats.dm" #include "code\datums\statistics\entities\player_entity.dm" -#include "code\datums\statistics\entities\player_save.dm" #include "code\datums\statistics\entities\player_stats.dm" #include "code\datums\statistics\entities\round_caste_picks.dm" #include "code\datums\statistics\entities\round_stats.dm" -#include "code\datums\statistics\entities\weapon_stats.dm" #include "code\datums\statistics\entities\xeno_death.dm" -#include "code\datums\statistics\entities\xeno_stats.dm" #include "code\datums\statistics\random_facts\christmas_fact.dm" #include "code\datums\statistics\random_facts\damage_fact.dm" #include "code\datums\statistics\random_facts\ib_fact.dm" diff --git a/nano/templates/cm_stat_panel.tmpl b/nano/templates/cm_stat_panel.tmpl deleted file mode 100644 index 26de08f17054..000000000000 --- a/nano/templates/cm_stat_panel.tmpl +++ /dev/null @@ -1,966 +0,0 @@ - -
- {{if data.round}} - {{:helper.link('Global', 'home', {'menu' : 0, 'subMenu' : 0, 'dataMenu': 0}, data.menu == 0 ? 'selected' : null)}} - {{/if}} -
-
- {{if data.menu == 0}} - {{:helper.link('General', null, {'subMenu' : 0, 'dataMenu': 0}, data.subMenu == 0 ? 'selected' : null)}} - {{:helper.link('Participants', null, {'subMenu' : 1, 'dataMenu': 0}, data.subMenu == 1 ? 'selected' : null)}} - {{:helper.link('Deaths', null, {'subMenu' : 2, 'dataMenu': 0}, data.subMenu == 2 ? 'selected' : null)}} - {{:helper.link('Jobs', null, {'subMenu' : 3, 'dataMenu': 0}, data.subMenu == 3 ? 'selected' : null)}} - {{:helper.link('Castes', null, {'subMenu' : 4, 'dataMenu': 0}, data.subMenu == 4 ? 'selected' : null)}} - {{:helper.link('Weapons', null, {'subMenu' : 5, 'dataMenu': 0}, data.subMenu == 5 ? 'selected' : null)}} - {{else data.menu == 1}} - {{if data.human}} - {{:helper.link('Human', null, {'subMenu' : 0, 'dataMenu' : 0}, data.subMenu == 0 ? 'selected' : null)}} - {{/if}} - {{if data.xeno}} - {{:helper.link('Xeno', null, {'subMenu' : 1, 'dataMenu' : 0}, data.subMenu == 1 ? 'selected' : null)}} - {{/if}} - {{/if}} -
-{{if data.menu == 1 && data.subMenu != 2}} -
- {{:helper.link('General', null, {'dataMenu' : 0}, data.dataMenu == 0 ? 'selected' : null)}} - {{:helper.link('Deaths', null, {'dataMenu' : 2}, data.dataMenu == 2 ? 'selected' : null)}} - {{if data.subMenu == 0}} - {{:helper.link('Weapons', null, {'dataMenu' : 3}, data.dataMenu == 3 ? 'selected' : null)}} - {{:helper.link('Roles', null, {'dataMenu' : 4}, data.dataMenu == 4 ? 'selected' : null)}} - {{:helper.link('Medals', null, {'dataMenu' : 5}, data.dataMenu == 5 ? 'selected' : null)}} - {{else data.subMenu == 1}} - {{:helper.link('Castes', null, {'dataMenu' : 3}, data.dataMenu == 3 ? 'selected' : null)}} - {{:helper.link('Jellies', null, {'dataMenu' : 5}, data.dataMenu == 5 ? 'selected' : null)}} - {{/if}} -
-{{/if}} -
- Updated {{:data.current_time}} -
-
- {{if data.menu == 0}} - {{if data.round}} - {{if data.subMenu == 0}} -
- {{:data.round.name}} -
-
- Map: -
-
- {{:data.round.map_name}} -
-
- Gamemode: -
-
- {{:data.round.game_mode}} -
- {{if data.round.round_result}} -
- Result: -
-
- {{:data.round.round_result}} -
- {{/if}} -
- Round Start: -
-
- {{:data.round.real_time_start}} -
- {{if data.round.real_time_end}} -
- Round End: -
-
- {{:data.round.real_time_end}} -
- {{/if}} - {{if data.round.round_length}} -
- Round Length: -
-
- {{:data.round.round_length}} -
- {{/if}} - {{if data.round.round_hijack_time}} -
- Hijack Time: -
-
- {{:data.round.round_hijack_time}} -
- {{/if}} - {{if data.round.end_round_player_population}} -
- Final Population: -
-
- {{:data.round.end_round_player_population}} -
- {{/if}} -
- DEFCON Level: -
-
- {{:data.round.defcon_level}} -
- {{if data.round.total_objective_points}} -
- Objective Points: -
-
- {{:data.round.objective_points}} -
-
- Total Objective Points: -
-
- {{:data.round.total_objective_points}} -
- {{/if}} -
- Total Shots Fired: -
-
- {{:data.round.total_projectiles_fired}} -
-
- Total Shots Hit: -
-
- {{:data.round.total_projectiles_hit}} -
-
- Total Shots Hit (Human): -
-
- {{:data.round.total_projectiles_hit_human}} -
-
- Total Shots Hit (Xeno): -
-
- {{:data.round.total_projectiles_hit_xeno}} -
-
- Total FF Instances: -
-
- {{:data.round.total_friendly_fire_instances}} -
-
- Total Friendly Fire Kills: -
-
- Total Slashes: -
-
- {{:data.round.total_slashes}} -
-
- Total Facehuggers Applied: -
-
- {{:data.round.total_huggers_applied}} -
-
- Total Larva Bursts: -
-
- {{:data.round.total_larva_burst}} -
- {{else data.subMenu == 1}} -
- Total Participants: -
-
- {{props data.round.participants}} -
- {{:value.name}}: -
-
- {{:value.value}} -
- {{/props}} -
-
- Total Deaths: -
-
- {{props data.round.total_deaths}} -
- {{:value.name}}: -
-
- {{:value.value}} -
- {{/props}} -
- {{if data.round.round_hijack_time}} -
- Hijack Participants: -
-
- {{props data.round.hijack_participants}} -
- {{:value.name}}: -
-
- {{:value.value}} -
- {{/props}} -
- {{/if}} - {{if data.round.real_time_end}} -
- Final Participants: -
-
-
- {{props data.round.final_participants}} -
- {{:value.name}}: -
-
- {{:value.value}} -
- {{/props}} -
-
- {{/if}} - {{else data.subMenu == 2}} - {{props data.round.death_stats_list :death_value:death_index}} -
-
- {{:death_value.mob_name}} -
- {{if death_value.job_name}} -
- Role: -
-
- {{:death_value.job_name}} -
- {{/if}} -
- Area: -
-
- {{:death_value.area_name}} -
-
- Cause: -
-
- {{:death_value.cause_name}} -
-
- Time of Death: -
-
- {{:death_value.time_of_death}} -
-
- Lifespan: -
-
- {{:death_value.total_time_alive}} -
-
- Damage Taken: -
-
- {{:death_value.total_damage_taken}} -
-
- Location: -
-
- ({{:death_value.x}}, {{:death_value.y}}, {{:death_value.z}}) -
-
- {{/props}} - {{else data.subMenu == 3}} - {{props data.round.job_stats_list :job_value:job_index}} -
-
- {{:job_value.name}} -
- {{if job_value.total_shots}} -
- Total Shots: -
-
- {{:job_value.total_shots}} -
- {{/if}} - {{if job_value.total_shots_hit}} -
- Total Shots Hit: -
-
- {{:job_value.total_shots_hit}} -
- {{/if}} - {{if job_value.total_friendly_fire}} -
- Total FF Instances: -
-
- {{:job_value.total_friendly_fire}} -
- {{/if}} - {{if job_value.total_revives}} -
- Total Times Revived: -
-
- {{:job_value.total_revives}} -
- {{/if}} - {{if job_value.total_lives_saved}} -
- Total Lives Saved: -
-
- {{:job_value.total_lives_saved}} -
- {{/if}} - {{if job_value.total_screams}} -
- Total Screams: -
-
- {{:job_value.total_screams}} -
- {{/if}} - {{props job_value.niche_stats :niche_value:niche_index}} -
- {{:niche_value.name}}: -
-
- {{:niche_value.value}} -
- {{/props}} - {{if job_value.nemesis}} -
- Nemesis: -
-
-
- {{:job_value.nemesis.name}} -
-
- {{/if}} -
- {{/props}} - {{else data.subMenu == 4}} - {{props data.round.caste_stats_list :caste_value:caste_index}} -
-
- {{:caste_value.name}} -
- {{props caste_value.niche_stats :niche_value:niche_index}} -
- {{:niche_value.name}}: -
-
- {{:niche_value.value}} -
- {{/props}} -
-
- Abilities Used: -
- {{props caste_value.abilities_used :ability_value:ability_index}} -
- {{:ability_value.name}}: -
-
- {{:ability_value.value}} -
- {{/props}} - {{if caste_value.nemesis}} -
- Nemesis: -
-
-
- {{:caste_value.nemesis.name}} -
-
- {{/if}} -
- {{/props}} - {{else data.subMenu == 5}} - {{props data.round.weapon_stats_list}} -
-
-
- {{:value.name}} -
- {{if value.total_hits}} -
- Total Hits: -
-
- {{:value.total_hits}} -
- {{/if}} - {{if value.total_shots}} -
- Total Shots: -
-
- {{:value.total_shots}} -
- {{/if}} - {{if value.total_shots_hit}} -
- Total Shots Hit: -
-
- {{:value.total_shots_hit}} -
- {{/if}} - {{if value.total_friendly_fire}} -
- Total FF Instances: -
-
- {{:value.total_friendly_fire}} -
- {{/if}} - {{props value.niche_stats :niche_value:niche_index}} -
- {{:niche_value.name}}: -
-
- {{:niche_value.value}} -
- {{/props}} -
-
- {{/props}} - {{/if}} - {{/if}} - {{else data.menu == 1}} - {{if data.subMenu == 0}} - {{if data.human}} - {{if data.dataMenu == 0}} -
- Total Playtime: -
-
- {{:data.human.total_playtime}} -
-
- Total Rounds Played: -
-
- {{:data.human.total_rounds_played}} -
-
- Total Shots: -
-
- {{:data.human.total_shots}} -
-
- Total Shots Hit: -
-
- {{:data.human.total_shots_hit}} -
- {{if data.human.total_lives_saved}} -
- Total FF Instances: -
-
- {{:data.human.total_friendly_fire}} -
- {{/if}} - {{if data.human.total_revives}} -
- Total Times Revived: -
-
- {{:data.human.total_revives}} -
- {{/if}} - {{if data.human.total_lives_saved}} -
- Total Lives Saved: -
-
- {{:data.human.total_lives_saved}} -
- {{/if}} - {{if data.human.total_lives_saved}} -
- Total Screams: -
-
- {{:data.human.total_screams}} -
- {{/if}} - {{props data.human.niche_stats :niche_value:niche_index}} -
- {{:niche_value.name}}: -
-
- {{:niche_value.value}} -
- {{/props}} - {{if data.human.top_weapon}} -
- Top Weapon: -
-
-
- {{:data.human.top_weapon.name}} -
- {{if data.human.top_weapon.total_shots}} -
- Total Shots: -
-
- {{:data.human.top_weapon.total_shots}} -
- {{/if}} - {{if data.human.top_weapon.total_shots_hit}} -
- Total Shots Hit: -
-
- {{:data.human.top_weapon.total_shots_hit}} -
- {{/if}} - {{if data.human.top_weapon.total_hits}} -
- Total Hits: -
-
- {{:data.human.top_weapon.total_hits}} -
- {{/if}} - {{if data.human.top_weapon.total_friendly_fire}} -
- Total FF Instances: -
-
- {{:data.human.top_weapon.total_friendly_fire}} -
- {{/if}} -
- {{/if}} - {{if data.human.nemesis}} -
- Nemesis: -
-
-
- {{:data.human.nemesis.name}} -
-
- {{/if}} - {{else data.dataMenu == 2}} - {{props data.human.death_list :death_value:death_index}} -
-
- {{:death_value.mob_name}} -
- {{if death_value.job_name}} -
- Role: -
-
- {{:death_value.job_name}} -
- {{/if}} -
- Area: -
-
- {{:death_value.area_name}} -
-
- Cause: -
-
- {{:death_value.cause_name}} -
-
- Time of Death: -
-
- {{:death_value.time_of_death}} -
-
- Lifespan: -
-
- {{:death_value.total_time_alive}} -
-
- Damage Taken: -
-
- {{:death_value.total_damage_taken}} -
-
- Location: -
-
- ({{:death_value.x}}, {{:death_value.y}}, {{:death_value.z}}) -
-
- {{/props}} - {{else data.dataMenu == 3}} - {{props data.human.weapon_stats_list}} -
-
-
- {{:value.name}} -
- {{if value.total_hits}} -
- Total Hits: -
-
- {{:value.total_hits}} -
- {{/if}} - {{if value.total_shots}} -
- Total Shots: -
-
- {{:value.total_shots}} -
- {{/if}} - {{if value.total_shots_hit}} -
- Total Shots Hit: -
-
- {{:value.total_shots_hit}} -
- {{/if}} - {{if value.total_friendly_fire}} -
- Total FF Instances: -
-
- {{:value.total_friendly_fire}} -
- {{/if}} - {{props value.niche_stats :niche_value:niche_index}} -
- {{:niche_value.name}}: -
-
- {{:niche_value.value}} -
- {{/props}} -
-
- {{/props}} - {{else data.dataMenu == 4}} - {{props data.human.job_stats_list :job_value:job_index}} -
-
- {{:job_value.name}} -
-
- Total Playtime: -
-
- {{:job_value.total_playtime}} -
-
- Total Rounds Played: -
-
- {{:job_value.total_rounds_played}} -
- {{if job_value.total_shots}} -
- Total Shots: -
-
- {{:job_value.total_shots}} -
- {{/if}} - {{if job_value.total_shots_hit}} -
- Total Shots Hit: -
-
- {{:job_value.total_shots_hit}} -
- {{/if}} - {{if job_value.total_friendly_fire}} -
- Total FF Instances: -
-
- {{:job_value.total_friendly_fire}} -
- {{/if}} - {{if job_value.total_revives}} -
- Total Times Revived: -
-
- {{:job_value.total_revives}} -
- {{/if}} - {{if job_value.total_lives_saved}} -
- Total Lives Saved: -
-
- {{:job_value.total_lives_saved}} -
- {{/if}} - {{if job_value.total_screams}} -
- Total Screams: -
-
- {{:job_value.total_screams}} -
- {{/if}} - {{props job_value.niche_stats :niche_value:niche_index}} -
- {{:niche_value.name}}: -
-
- {{:niche_value.value}} -
- {{/props}} -
- {{if job_value.nemesis}} -
- Nemesis: -
-
-
- {{:job_value.nemesis.name}} -
-
- {{/if}} -
- {{/props}} - {{else data.dataMenu == 5}} - {{props data.human.medal_list :medal_value:medal_index}} -
-
- {{:medal_value.medal_type}} -
-
- {{:medal_value.recipient}} -
-
- {{:medal_value.recipient_job}} -
-
-
- {{:medal_value.citation}} -
-
- {{/props}} - {{/if}} - {{/if}} - {{else data.subMenu == 1}} - {{if data.xeno}} - {{if data.dataMenu == 0}} -
- Total Playtime: -
-
- {{:data.xeno.total_playtime}} -
-
- Total Rounds Played: -
-
- {{:data.xeno.total_rounds_played}} -
-
- Total Slashes: -
-
- {{:data.xeno.total_hits}} -
- {{props data.xeno.niche_stats :niche_value:niche_index}} -
- {{:niche_value.name}}: -
-
- {{:niche_value.value}} -
- {{/props}} - {{if data.xeno.top_caste}} -
- Top Caste: -
-
-
- {{:data.xeno.top_caste.name}} -
-
- Total Playtime: -
-
- {{:data.xeno.top_caste.total_playtime}} -
-
- Total Rounds Played: -
-
- {{:data.xeno.top_caste.total_rounds_played}} -
-
- {{/if}} - {{if data.xeno.nemesis}} -
- Nemesis: -
-
-
- {{:data.xeno.nemesis.name}} -
-
- {{/if}} - {{else data.dataMenu == 2}} - {{props data.xeno.death_list :death_value:death_index}} -
-
- {{:death_value.mob_name}} -
- {{if death_value.job_name}} -
- Caste: -
-
- {{:death_value.job_name}} -
- {{/if}} -
- Area: -
-
- {{:death_value.area_name}} -
-
- Cause: -
-
- {{:death_value.cause_name}} -
-
- Time of Death: -
-
- {{:death_value.time_of_death}} -
-
- Lifespan: -
-
- {{:death_value.total_time_alive}} -
-
- Damage Taken: -
-
- {{:death_value.total_damage_taken}} -
-
- Location: -
-
- ({{:death_value.x}}, {{:death_value.y}}, {{:death_value.z}}) -
-
- {{/props}} - {{else data.dataMenu == 3}} - {{props data.xeno.caste_stats_list :caste_value:caste_index}} -
-
- {{:caste_value.name}} -
-
- Total Playtime: -
-
- {{:caste_value.total_playtime}} -
-
- Total Rounds Played: -
-
- {{:caste_value.total_rounds_played}} -
- {{props caste_value.niche_stats :niche_value:niche_index}} -
- {{:niche_value.name}}: -
-
- {{:niche_value.value}} -
- {{/props}} -
-
- Abilities Used: -
- {{props caste_value.abilities_used :ability_value:ability_index}} -
- {{:ability_value.name}}: -
-
- {{:ability_value.value}} -
- {{/props}} - {{if caste_value.nemesis}} -
- Nemesis: -
-
-
- {{:caste_value.nemesis.name}} -
-
- {{/if}} -
- {{/props}} - {{else data.dataMenu == 5}} - {{props data.xeno.medal_list :medal_value:medal_index}} -
-
- {{:medal_value.medal_type}} -
-
- {{:medal_value.recipient}} -
-
-
- {{:medal_value.citation}} -
-
- {{/props}} - {{/if}} - {{/if}} - {{/if}} - {{/if}} -
diff --git a/tgui/packages/tgui/interfaces/KillPanel.jsx b/tgui/packages/tgui/interfaces/KillPanel.jsx deleted file mode 100644 index 535c7eda4b78..000000000000 --- a/tgui/packages/tgui/interfaces/KillPanel.jsx +++ /dev/null @@ -1,62 +0,0 @@ -import { Fragment } from 'react'; - -import { useBackend } from '../backend'; -import { Box, Collapsible, NoticeBox, Section } from '../components'; -import { Window } from '../layouts'; - -export const KillPanel = (props) => { - const { act, data } = useBackend(); - const { death_data } = data; - - const real_data = death_data['death_stats_list']; - - return ( - - -
- {death_data ? ( - - ) : ( - No recorded kills! - )} -
-
-
- ); -}; - -const KillView = (props) => { - const { act, data } = useBackend(); - const { death_data } = data; - - const real_data = death_data['death_stats_list']; - - return real_data.map((entry, index) => ( - - Mob: {entry.mob_name} - {entry.job_name ? ( - <> - - Job: {entry.job_name} - - ) : null} - - Area: {entry.area_name} - - Cause: {entry.cause_name} - - Time: {entry.time_of_death} - - Lifespan: {entry.total_time_alive} - - Damage taken: {entry.total_damage_taken} - - - Coords: {entry.x}, {entry.y}, {entry.z} - - - )); -}; diff --git a/tgui/packages/tgui/interfaces/LobbyMenu.tsx b/tgui/packages/tgui/interfaces/LobbyMenu.tsx index c21ce9076533..f037ab678c5c 100644 --- a/tgui/packages/tgui/interfaces/LobbyMenu.tsx +++ b/tgui/packages/tgui/interfaces/LobbyMenu.tsx @@ -384,6 +384,9 @@ const LobbyButtons = (props: { act('playtimes')} icon="list-ul"> View Playtimes + act('statistic')} icon="list-ul"> + View Statistic + diff --git a/tgui/packages/tgui/interfaces/PlayerPanel.jsx b/tgui/packages/tgui/interfaces/PlayerPanel.jsx index 099c0950a3bc..a4a7d45cef08 100644 --- a/tgui/packages/tgui/interfaces/PlayerPanel.jsx +++ b/tgui/packages/tgui/interfaces/PlayerPanel.jsx @@ -131,6 +131,15 @@ export const PlayerPanel = (props) => { View Playtimes + + + diff --git a/tgui/packages/tgui/interfaces/Statistic.jsx b/tgui/packages/tgui/interfaces/Statistic.jsx new file mode 100644 index 000000000000..019053a995b2 --- /dev/null +++ b/tgui/packages/tgui/interfaces/Statistic.jsx @@ -0,0 +1,301 @@ +import { useState } from 'react'; + +import { useBackend } from '../backend'; +import { + Box, + Collapsible, + Flex, + NoticeBox, + Section, + Tabs, +} from '../components'; +import { Window } from '../layouts'; + +export const Statistic = () => { + const { data } = useBackend(); + const [selectedTab, setSelectedTab] = useState('Round'); + + const { data_tabs, round, medals } = data; + + return ( + + + + + + {data_tabs.map((tab) => ( + setSelectedTab(tab)} + > + {tab} + + ))} + + + + + + + + + ); +}; + +const GetTab = ({ selectedTab, round, medals }) => { + const { data } = useBackend(); + const { factions } = data; + + switch (selectedTab) { + case 'Round': + return round ? ( + + ) : ( + + Round statistic preparing! + + ); + case 'Medals': + return ; + default: + return factions[selectedTab] ? ( + + ) : null; + } +}; + +const RoundTab = ({ round }) => ( + <> +
+ + + + {round.round_result ? ( + + ) : null} + {round.real_time_start ? ( + + ) : null} + {round.real_time_end ? ( + + ) : null} + {round.round_length ? ( + + ) : null} + {round.round_hijack_time ? ( + + ) : null} + + + + + + + + + + + {round.end_round_player_population ? ( + + ) : null} + {round.participants_list.map((entry, index) => ( + + {entry.value.map((sub_entry, sub_index) => ( + + ))} + + ))} +
+ {round.death_list.length ? ( + + ) : ( + + No recorded kills! + + )} + +); + +const MedalTab = ({ medals }) => + medals.map((entry, index) => ( +
+ + + + +
+ )); + +const StatTab = ({ faction }) => { + const { + total_statistics, + top_statistics, + nemesis, + total_deaths, + death_list, + statistics_list, + } = faction; + + return ( + <> + {total_statistics.length ? ( +
+ {total_statistics.map((entry, stat_idx) => ( + + ))} +
+ ) : ( + + No recorded statistic! + + )} + + {top_statistics.length + ? top_statistics.map((entry, index) => ( +
+ {entry.statistics.length + ? entry.statistics.map((stat, statIndex) => ( + + )) + : null} +
+ )) + : null} + + {nemesis.name ? ( +
+ +
+ ) : ( + + No recorded nemesis! + + )} + + {death_list.length ? ( + + ) : ( + + No recorded deaths! + + )} + + {statistics_list.length + ? statistics_list.map((entry, index) => + entry.value.length + ? entry.value.map((sub_entry, sub_index) => ( +
+ {sub_entry.statistics.length ? ( + <> + Statistics + {sub_entry.statistics.map((stat, stat_idx) => ( + + ))} + + ) : null} + {sub_entry.top_statistics.length ? ( + <> + Top Statistics + {sub_entry.top_statistics.map((stat, stat_idx) => ( + + ))} + + ) : null} +
+ )) + : null, + ) + : null} + + ); +}; + +const DeathsView = ({ death_log_data, total_deaths }) => ( +
+ + {death_log_data.map((entry, index) => ( +
+ + {entry.job_name && } + + + + + + +
+ ))} +
+
+); + +const StatItem = ({ label, value }) => ( + + {label}: {value} + +); diff --git a/tgui/packages/tgui/styles/interfaces/Statistic.scss b/tgui/packages/tgui/styles/interfaces/Statistic.scss new file mode 100644 index 000000000000..a197f1e63ba3 --- /dev/null +++ b/tgui/packages/tgui/styles/interfaces/Statistic.scss @@ -0,0 +1,50 @@ +@use '../colors.scss'; +$separator-color: colors.$primary !default; + +.StatisticMenu { + margin: auto; + display: flex; + flex-direction: column; + overflow-y: auto; + height: 100%; + + .TilesInititalizator { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, auto)); + gap: 10px; + overflow: hidden; + flex-grow: 1; + + .TilesSmallItem { + padding: 15px; + aspect-ratio: 1 / 1; + } + + .TilesMediumItem { + padding: 10px; + aspect-ratio: 1 / 1; + } + + .TilesBigItem { + padding: 10px; + grid-column: span 2; + aspect-ratio: 2 / 1; + width: 100%; + box-sizing: border-box; + } + } + + .TilesTitleItem { + font-size: 1em; + font-weight: bold; + } + + .TilesStatItem { + margin-bottom: 6px; + + .TilesStatLabel { + color: $separator-color; + font-weight: bold; + } + } +} diff --git a/tgui/packages/tgui/styles/main.scss b/tgui/packages/tgui/styles/main.scss index 39a260ce223c..913d8ad9ebb2 100644 --- a/tgui/packages/tgui/styles/main.scss +++ b/tgui/packages/tgui/styles/main.scss @@ -81,7 +81,10 @@ @include meta.load-css('./interfaces/SidePanel.scss'); @include meta.load-css('./interfaces/SmartFridge.scss'); @include meta.load-css('./interfaces/SquadInfo.scss'); +@include meta.load-css('./interfaces/Statistic.scss'); +@include meta.load-css('./interfaces/StripMenu.scss'); @include meta.load-css('./interfaces/TachyonArray.scss'); +@include meta.load-css('./interfaces/TacticalMap.scss'); @include meta.load-css('./interfaces/Techweb.scss'); @include meta.load-css('./interfaces/TechNode.scss'); @include meta.load-css('./interfaces/Vending.scss');