Files
Bubberstation/code/datums/achievements/_achievement_data.dm
ff006aa4a5 verb macro system (pr 1/3) (#96720)
## About The Pull Request

just macro-izes all the usages of verbs in the codebase as a
pre-requisite to my follow up pr that serializes all the verbs arguments
so we can tgui-ify the command bar, so we can then put it on the
onscreen map.

this also basically does the same as #94487 so can easily be integrated
into the verb queueing stuff... but does not actually do any verb
queueing by itself. basically im just trying to be
https://github.com/tgstation/tgstation/labels/Atomic
## Why It's Good For The Game
it doesn't really do anything by itself but it does let us do more stuff

## Changelog
🆑
code: the backend to all verbs in the game has been played with, please
report any issues to github
/🆑

---------

Co-authored-by: harryob <55142896+harryob@users.noreply.github.com>
2026-07-04 02:45:07 -04:00

135 lines
4.5 KiB
Plaintext

///Datum that handles
/datum/achievement_data
///Ckey of this achievement data's owner
var/owner_ckey
///Up to date list of all achievements and their info.
var/data = list()
///Original status of achievement.
var/original_cached_data = list()
///Have we done our set-up yet?
var/initialized = FALSE
/datum/achievement_data/New(ckey)
owner_ckey = ckey
if(SSachievements.initialized && !initialized)
InitializeData()
/datum/achievement_data/proc/InitializeData()
initialized = TRUE
load_all_achievements() //So we know which achievements we have unlocked so far.
///Gets list of changed rows in MassInsert format
/datum/achievement_data/proc/get_changed_data()
. = list()
for(var/T in data)
var/datum/award/A = SSachievements.awards[T]
if(data[T] != original_cached_data[T])//If our data from before is not the same as now, save it to db.
var/deets = A.get_changed_rows(src)
if(deets)
. += list(deets)
/datum/achievement_data/proc/load_all_achievements()
set waitfor = FALSE
var/list/kv = list()
var/datum/db_query/Query = SSdbcore.NewQuery(
"SELECT achievement_key,value FROM [format_table_name("achievements")] WHERE ckey = :ckey",
list("ckey" = owner_ckey)
)
if(!Query.Execute())
qdel(Query)
return
while(Query.NextRow())
var/key = Query.item[1]
var/value = text2num(Query.item[2])
kv[key] = value
qdel(Query)
for(var/award_type in subtypesof(/datum/award))
var/datum/award/award = SSachievements.awards[award_type]
if(!award || !award.name) //Skip abstract achievements types
continue
award.on_achievement_data_init(src, kv[award.database_id])
///Updates local cache with db data for the given achievement type if it wasn't loaded yet.
/datum/achievement_data/proc/get_data(achievement_type)
var/datum/award/award = SSachievements.awards[achievement_type]
if(!award.name)
return FALSE
if(!data[achievement_type])
award.load(src)
///Unlocks an achievement of a specific type. achievement type is a typepath to the award, user is the mob getting the award, and value is an optional value to be used for defining a score to add to the leaderboard
/datum/achievement_data/proc/unlock(achievement_type, mob/user, value = 1, ...)
set waitfor = FALSE
if(!SSachievements.achievements_enabled)
return
var/datum/award/award = SSachievements.awards[achievement_type]
get_data(achievement_type) //Get the current status first if necessary
var/list/unlock_args = list(user, src, value)
if(length(args) > 3)
unlock_args += args.Copy(4)
award.unlock(arglist(unlock_args))
update_static_data(user)
///Getter for the status/score of an achievement
/datum/achievement_data/proc/get_achievement_status(achievement_type)
return data[achievement_type]
/datum/achievement_data/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet_batched/achievements),
)
/datum/achievement_data/ui_state(mob/user)
return GLOB.always_state
/datum/achievement_data/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Achievements")
ui.open()
/datum/achievement_data/ui_static_data(mob/user)
. = ..()
.["categories"] = GLOB.achievement_categories
.["achievements"] = list()
.["highscores"] = list()
.["progresses"] = list()
.["user_key"] = owner_ckey
var/datum/asset/spritesheet_batched/assets = get_asset_datum(/datum/asset/spritesheet_batched/achievements)
for(var/achievement_type in SSachievements.awards)
var/datum/award/award = SSachievements.awards[achievement_type]
if(!award.name) //No name? we a subtype.
continue
if(isnull(data[achievement_type])) //We're still loading
continue
var/list/award_data = list(
"name" = award.name,
"desc" = award.desc,
"category" = award.category,
"icon_class" = assets.icon_class_name("achievement-[award.icon_state]"),
"value" = data[achievement_type],
)
award_data += award.get_ui_data(award_data, src)
.["achievements"] += list(award_data)
for(var/score_type in SSachievements.scores)
var/datum/award/score/score = SSachievements.scores[score_type]
if(!score.name)
continue
if(istype(score, /datum/award/score/progress))
var/datum/award/score/progress/prog = score
var/list/prog_data = prog.get_progress(src)
if(length(prog_data))
.["progresses"] += list(prog_data)
if(!score.track_high_scores || !length(score.high_scores))
continue
.["highscores"] += list(list("name" = score.name, "scores" = score.high_scores))
GAME_VERB_DESC(/client, checkachievements, "Check achievements", "See all of your achievements!", "OOC")
persistent_client.achievements.ui_interact(usr)