Merge branch 'master' into void-but-for-real
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
///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(owner_ckey,data[T])
|
||||
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/T in subtypesof(/datum/award))
|
||||
var/datum/award/A = SSachievements.awards[T]
|
||||
if(!A || !A.name) //Skip abstract achievements types
|
||||
continue
|
||||
if(!data[T])
|
||||
data[T] = A.parse_value(kv[A.database_id])
|
||||
original_cached_data[T] = data[T]
|
||||
|
||||
///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/A = SSachievements.awards[achievement_type]
|
||||
if(!A.name)
|
||||
return FALSE
|
||||
if(!data[achievement_type])
|
||||
data[achievement_type] = A.load(owner_ckey)
|
||||
original_cached_data[achievement_type] = data[achievement_type]
|
||||
|
||||
///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/A = SSachievements.awards[achievement_type]
|
||||
get_data(achievement_type) //Get the current status first if necessary
|
||||
if(istype(A, /datum/award/achievement))
|
||||
if(data[achievement_type]) //You already unlocked it so don't bother running the unlock proc
|
||||
return
|
||||
data[achievement_type] = TRUE
|
||||
A.on_unlock(user) //Only on default achievement, as scores keep going up.
|
||||
else if(istype(A, /datum/award/score))
|
||||
data[achievement_type] += value
|
||||
|
||||
///Getter for the status/score of an achievement
|
||||
/datum/achievement_data/proc/get_achievement_status(achievement_type)
|
||||
return data[achievement_type]
|
||||
|
||||
///Resets an achievement to default values.
|
||||
/datum/achievement_data/proc/reset(achievement_type)
|
||||
if(!SSachievements.achievements_enabled)
|
||||
return
|
||||
var/datum/award/A = SSachievements.awards[achievement_type]
|
||||
get_data(achievement_type)
|
||||
if(istype(A, /datum/award/achievement))
|
||||
data[achievement_type] = FALSE
|
||||
else if(istype(A, /datum/award/score))
|
||||
data[achievement_type] = 0
|
||||
|
||||
/datum/achievement_data/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/spritesheet/simple/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_data(mob/user)
|
||||
var/ret_data = list() // screw standards (qustinnus you must rename src.data ok)
|
||||
ret_data["categories"] = list("Bosses", "Misc", "Mafia", "Scores")
|
||||
ret_data["achievements"] = list()
|
||||
ret_data["user_key"] = user.ckey
|
||||
|
||||
var/datum/asset/spritesheet/simple/assets = get_asset_datum(/datum/asset/spritesheet/simple/achievements)
|
||||
//This should be split into static data later
|
||||
for(var/achievement_type in SSachievements.awards)
|
||||
if(!SSachievements.awards[achievement_type].name) //No name? we a subtype.
|
||||
continue
|
||||
if(isnull(data[achievement_type])) //We're still loading
|
||||
continue
|
||||
var/list/this = list(
|
||||
"name" = SSachievements.awards[achievement_type].name,
|
||||
"desc" = SSachievements.awards[achievement_type].desc,
|
||||
"category" = SSachievements.awards[achievement_type].category,
|
||||
"icon_class" = assets.icon_class_name(SSachievements.awards[achievement_type].icon),
|
||||
"value" = data[achievement_type],
|
||||
"score" = ispath(achievement_type,/datum/award/score)
|
||||
)
|
||||
ret_data["achievements"] += list(this)
|
||||
|
||||
return ret_data
|
||||
|
||||
/datum/achievement_data/ui_static_data(mob/user)
|
||||
. = ..()
|
||||
.["highscore"] = list()
|
||||
for(var/score in SSachievements.scores)
|
||||
var/datum/award/score/S = SSachievements.scores[score]
|
||||
if(!S.name || !S.track_high_scores || !S.high_scores.len)
|
||||
continue
|
||||
.["highscore"] += list(list("name" = S.name,"scores" = S.high_scores))
|
||||
|
||||
/client/verb/checkachievements()
|
||||
set category = "OOC"
|
||||
set name = "Check achievements"
|
||||
set desc = "See all of your achievements!"
|
||||
|
||||
player_details.achievements.ui_interact(usr)
|
||||
@@ -0,0 +1,117 @@
|
||||
/datum/award
|
||||
///Name of the achievement, If null it won't show up in the achievement browser. (Handy for inheritance trees)
|
||||
var/name
|
||||
var/desc = "You did it."
|
||||
///Found in UI_Icons/Achievements
|
||||
var/icon = "default"
|
||||
var/category = "Normal"
|
||||
|
||||
///What ID do we use in db, limited to 32 characters
|
||||
var/database_id
|
||||
//Bump this up if you're changing outdated table identifier and/or achievement type
|
||||
var/achievement_version = 2
|
||||
|
||||
//Value returned on db connection failure, in case we want to differ 0 and nonexistent later on
|
||||
var/default_value = FALSE
|
||||
|
||||
///This proc loads the achievement data from the hub.
|
||||
/datum/award/proc/load(key)
|
||||
if(!SSdbcore.Connect())
|
||||
return default_value
|
||||
if(!key || !database_id || !name)
|
||||
return default_value
|
||||
var/raw_value = get_raw_value(key)
|
||||
return parse_value(raw_value)
|
||||
|
||||
///This saves the changed data to the hub.
|
||||
/datum/award/proc/get_changed_rows(key, value)
|
||||
if(!database_id || !key || !name)
|
||||
return
|
||||
return list(
|
||||
"ckey" = key,
|
||||
"achievement_key" = database_id,
|
||||
"value" = value,
|
||||
)
|
||||
|
||||
/datum/award/proc/get_metadata_row()
|
||||
return list(
|
||||
"achievement_key" = database_id,
|
||||
"achievement_version" = achievement_version,
|
||||
"achievement_type" = "award",
|
||||
"achievement_name" = name,
|
||||
"achievement_description" = desc,
|
||||
)
|
||||
|
||||
///Get raw numerical achievement value from the database
|
||||
/datum/award/proc/get_raw_value(key)
|
||||
var/datum/db_query/Q = SSdbcore.NewQuery(
|
||||
"SELECT value FROM [format_table_name("achievements")] WHERE ckey = :ckey AND achievement_key = :achievement_key",
|
||||
list("ckey" = key, "achievement_key" = database_id)
|
||||
)
|
||||
if(!Q.Execute(async = TRUE))
|
||||
qdel(Q)
|
||||
return 0
|
||||
var/result = 0
|
||||
if(Q.NextRow())
|
||||
result = text2num(Q.item[1])
|
||||
qdel(Q)
|
||||
return result
|
||||
|
||||
//Should return sanitized value for achievement cache
|
||||
/datum/award/proc/parse_value(raw_value)
|
||||
return default_value
|
||||
|
||||
///Can be overriden for achievement specific events
|
||||
/datum/award/proc/on_unlock(mob/user)
|
||||
return
|
||||
|
||||
///Achievements are one-off awards for usually doing cool things.
|
||||
/datum/award/achievement
|
||||
desc = "Achievement for epic people"
|
||||
|
||||
/datum/award/achievement/get_metadata_row()
|
||||
. = ..()
|
||||
.["achievement_type"] = "achievement"
|
||||
|
||||
/datum/award/achievement/parse_value(raw_value)
|
||||
return raw_value > 0
|
||||
|
||||
/datum/award/achievement/on_unlock(mob/user)
|
||||
. = ..()
|
||||
to_chat(user, "<span class='greenannounce'><B>Achievement unlocked: [name]!</B></span>")
|
||||
|
||||
///Scores are for leaderboarded things, such as killcount of a specific boss
|
||||
/datum/award/score
|
||||
desc = "you did it sooo many times."
|
||||
category = "Scores"
|
||||
default_value = 0
|
||||
|
||||
var/track_high_scores = TRUE
|
||||
var/list/high_scores = list()
|
||||
|
||||
/datum/award/score/New()
|
||||
. = ..()
|
||||
if(track_high_scores)
|
||||
LoadHighScores()
|
||||
|
||||
/datum/award/score/get_metadata_row()
|
||||
. = ..()
|
||||
.["achievement_type"] = "score"
|
||||
|
||||
/datum/award/score/proc/LoadHighScores()
|
||||
var/datum/db_query/Q = SSdbcore.NewQuery(
|
||||
"SELECT ckey,value FROM [format_table_name("achievements")] WHERE achievement_key = :achievement_key ORDER BY value DESC LIMIT 50",
|
||||
list("achievement_key" = database_id)
|
||||
)
|
||||
if(!Q.Execute(async = TRUE))
|
||||
qdel(Q)
|
||||
return
|
||||
else
|
||||
while(Q.NextRow())
|
||||
var/key = Q.item[1]
|
||||
var/score = text2num(Q.item[2])
|
||||
high_scores[key] = score
|
||||
qdel(Q)
|
||||
|
||||
/datum/award/score/parse_value(raw_value)
|
||||
return isnum(raw_value) ? raw_value : 0
|
||||
@@ -0,0 +1,130 @@
|
||||
/datum/award/achievement/boss
|
||||
category = "Bosses"
|
||||
icon = "baseboss"
|
||||
|
||||
/datum/award/achievement/boss/tendril_exterminator
|
||||
name = "Tendril Exterminator"
|
||||
desc = "Watch your step"
|
||||
database_id = BOSS_MEDAL_TENDRIL
|
||||
icon = "tendril"
|
||||
|
||||
/datum/award/achievement/boss/boss_killer
|
||||
name = "Boss Killer"
|
||||
desc = "You've come a long ways from asking how to switch hands."
|
||||
database_id = "Boss Killer"
|
||||
// icon = "firstboss"
|
||||
|
||||
/datum/award/achievement/boss/blood_miner_kill
|
||||
name = "Blood-Drunk Miner Killer"
|
||||
desc = "I guess he couldn't handle his drink that well."
|
||||
database_id = BOSS_MEDAL_MINER
|
||||
icon = "miner"
|
||||
|
||||
/datum/award/achievement/boss/demonic_miner_kill
|
||||
name = "Demonic-Frost Miner Killer"
|
||||
desc = "Definitely harder than the Blood-Drunk Miner."
|
||||
database_id = BOSS_MEDAL_FROSTMINER
|
||||
|
||||
/datum/award/achievement/boss/bubblegum_kill
|
||||
name = "Bubblegum Killer"
|
||||
desc = "I guess he wasn't made of candy after all"
|
||||
database_id = BOSS_MEDAL_BUBBLEGUM
|
||||
icon = "bbgum"
|
||||
|
||||
/datum/award/achievement/boss/colossus_kill
|
||||
name = "Colossus Killer"
|
||||
desc = "The bigger they are... the better the loot"
|
||||
database_id = BOSS_MEDAL_COLOSSUS
|
||||
icon = "colossus"
|
||||
|
||||
/datum/award/achievement/boss/drake_kill
|
||||
name = "Drake Killer"
|
||||
desc = "Now I can wear Rune Platebodies!"
|
||||
database_id = BOSS_MEDAL_DRAKE
|
||||
icon = "drake"
|
||||
|
||||
/datum/award/achievement/boss/hierophant_kill
|
||||
name = "Hierophant Killer"
|
||||
desc = "Hierophant, but not triumphant."
|
||||
database_id = BOSS_MEDAL_HIEROPHANT
|
||||
icon = "hierophant"
|
||||
|
||||
/datum/award/achievement/boss/legion_kill
|
||||
name = "Legion Killer"
|
||||
desc = "We were many..now we are none."
|
||||
database_id = BOSS_MEDAL_LEGION
|
||||
icon = "legion"
|
||||
|
||||
/datum/award/achievement/boss/swarmer_beacon_kill
|
||||
name = "Swarm Beacon Killer"
|
||||
desc = "GET THEM OFF OF ME!"
|
||||
database_id = BOSS_MEDAL_SWARMERS
|
||||
icon = "swarmer"
|
||||
|
||||
/datum/award/achievement/boss/wendigo_kill
|
||||
name = "Wendigo Killer"
|
||||
desc = "You've now ruined years of mythical storytelling."
|
||||
database_id = BOSS_MEDAL_WENDIGO
|
||||
|
||||
/datum/award/achievement/boss/blood_miner_crusher
|
||||
name = "Blood-Drunk Miner Crusher"
|
||||
desc = "I guess he couldn't handle his drink that well."
|
||||
database_id = BOSS_MEDAL_MINER_CRUSHER
|
||||
icon = "miner"
|
||||
|
||||
/datum/award/achievement/boss/demonic_miner_crusher
|
||||
name = "Demonic-Frost Miner Crusher"
|
||||
desc = "Definitely harder than the Blood-Drunk Miner."
|
||||
database_id = BOSS_MEDAL_FROSTMINER_CRUSHER
|
||||
|
||||
/datum/award/achievement/boss/bubblegum_crusher
|
||||
name = "Bubblegum Crusher"
|
||||
desc = "I guess he wasn't made of candy after all"
|
||||
database_id = BOSS_MEDAL_BUBBLEGUM_CRUSHER
|
||||
icon = "bbgum"
|
||||
|
||||
/datum/award/achievement/boss/colossus_crusher
|
||||
name = "Colossus Crusher"
|
||||
desc = "The bigger they are... the better the loot"
|
||||
database_id = BOSS_MEDAL_COLOSSUS_CRUSHER
|
||||
icon = "colossus"
|
||||
|
||||
/datum/award/achievement/boss/drake_crusher
|
||||
name = "Drake Crusher"
|
||||
desc = "Now I can wear Rune Platebodies!"
|
||||
database_id = BOSS_MEDAL_DRAKE_CRUSHER
|
||||
icon = "drake"
|
||||
|
||||
/datum/award/achievement/boss/hierophant_crusher
|
||||
name = "Hierophant Crusher"
|
||||
desc = "Hierophant, but not triumphant."
|
||||
database_id = BOSS_MEDAL_HIEROPHANT_CRUSHER
|
||||
icon = "hierophant"
|
||||
|
||||
/datum/award/achievement/boss/legion_crusher
|
||||
name = "Legion Crusher"
|
||||
desc = "We were many... now we are none."
|
||||
database_id = BOSS_MEDAL_LEGION_CRUSHER
|
||||
|
||||
/datum/award/achievement/boss/swarmer_beacon_crusher
|
||||
name = "Swarm Beacon Crusher"
|
||||
desc = "GET THEM OFF OF ME!"
|
||||
database_id = BOSS_MEDAL_SWARMERS_CRUSHER
|
||||
|
||||
/datum/award/achievement/boss/wendigo_crusher
|
||||
name = "Wendigo Crusher"
|
||||
desc = "You've now ruined years of mythical storytelling."
|
||||
database_id = BOSS_MEDAL_WENDIGO_CRUSHER
|
||||
|
||||
//should be removed soon
|
||||
// /datum/award/achievement/boss/king_goat_kill
|
||||
// name = "King Goat Killer"
|
||||
// desc = "The king is dead, long live the king!"
|
||||
// database_id = BOSS_MEDAL_KINGGOAT
|
||||
// icon = "goatboss"
|
||||
|
||||
// /datum/award/achievement/boss/king_goat_crusher
|
||||
// name = "King Goat Crusher"
|
||||
// desc = "The king is dead, long live the king!"
|
||||
// database_id = BOSS_MEDAL_KINGGOAT_CRUSHER
|
||||
// icon = "goatboss"
|
||||
@@ -0,0 +1,54 @@
|
||||
/datum/award/score/tendril_score
|
||||
name = "Tendril Score"
|
||||
desc = "Watch your step"
|
||||
database_id = TENDRIL_CLEAR_SCORE
|
||||
|
||||
/datum/award/score/boss_score
|
||||
name = "Bosses Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = BOSS_SCORE
|
||||
|
||||
/datum/award/score/blood_miner_score
|
||||
name = "Blood-Drunk Miners Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = MINER_SCORE
|
||||
|
||||
/datum/award/score/demonic_miner_score
|
||||
name = "Demonic-Frost Miners Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = FROST_MINER_SCORE
|
||||
|
||||
/datum/award/score/bubblegum_score
|
||||
name = "Bubblegums Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = BUBBLEGUM_SCORE
|
||||
|
||||
/datum/award/score/colussus_score
|
||||
name = "Colossus Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = COLOSSUS_SCORE
|
||||
|
||||
/datum/award/score/drake_score
|
||||
name = "Drakes Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = DRAKE_SCORE
|
||||
|
||||
/datum/award/score/hierophant_score
|
||||
name = "Hierophants Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = HIEROPHANT_SCORE
|
||||
|
||||
/datum/award/score/legion_score
|
||||
name = "Legions Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = LEGION_SCORE
|
||||
|
||||
/datum/award/score/swarmer_beacon_score
|
||||
name = "Swarmer Beacons Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = SWARMER_BEACON_SCORE
|
||||
|
||||
/datum/award/score/wendigo_score
|
||||
name = "Wendigos Killed"
|
||||
desc = "You've killed HOW many?"
|
||||
database_id = WENDIGO_SCORE
|
||||
@@ -0,0 +1,115 @@
|
||||
/datum/award/achievement/mafia
|
||||
category = "Mafia"
|
||||
icon = "basemafia"
|
||||
|
||||
///ALL THE ACHIEVEMENTS FOR WINNING A ROUND AS A ROLE///
|
||||
|
||||
/datum/award/achievement/mafia/assistant
|
||||
name = "Assistant Victory"
|
||||
desc = "If you got killed instead of someone more important, you just flexed the true strength of your \"\"\"\"role\"\"\"\"."
|
||||
database_id = MAFIA_MEDAL_ASSISTANT
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/detective
|
||||
name = "Detective Victory"
|
||||
desc = "If you did this with a Medical Doctor in the game, i'm not really that impressed."
|
||||
database_id = MAFIA_MEDAL_DETECTIVE
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/psychologist
|
||||
name = "Psychologist Victory"
|
||||
desc = "You learned how to not reveal someone random night one! Or... maybe you're just a lucky bastard."
|
||||
database_id = MAFIA_MEDAL_PSYCHOLOGIST
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/chaplain
|
||||
name = "Chaplain Victory"
|
||||
desc = "Useless... until the one night the thoughtfeeder confidently claims themselves as detective. Mafia's true bullshit detector."
|
||||
database_id = MAFIA_MEDAL_CHAPLAIN
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/md
|
||||
name = "Medical Doctor Victory"
|
||||
desc = "Congratulations on learning how to not talk!"
|
||||
database_id = MAFIA_MEDAL_MD
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/officer
|
||||
name = "Security Officer Victory"
|
||||
desc = "Don't worry, you can win this if you're dead! You... did use your ability to become dead, right?"
|
||||
database_id = MAFIA_MEDAL_OFFICER
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/lawyer
|
||||
name = "Lawyer Victory"
|
||||
desc = "Oh don't mind me, i'm just the worst rol- Oops, I just instantly ended the game."
|
||||
database_id = MAFIA_MEDAL_LAWYER
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/hop
|
||||
name = "Head of Personnel Victory"
|
||||
desc = "King of Assistants, waster of a single mafia's night, thrower of games."
|
||||
database_id = MAFIA_MEDAL_HOP
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/warden
|
||||
name = "Warden Victory"
|
||||
desc = "Make changelings think you're detective, go on lockdown, actual detective investigates you and dies. Cha cha real smooth!"
|
||||
database_id = MAFIA_MEDAL_WARDEN
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/hos
|
||||
name = "Head of Security Victory"
|
||||
desc = "Certified not shitcurity."
|
||||
database_id = MAFIA_MEDAL_HOS
|
||||
icon = "town"
|
||||
|
||||
/datum/award/achievement/mafia/changeling
|
||||
name = "Changeling Victory"
|
||||
desc = "I think the changelings are metacomming."
|
||||
database_id = MAFIA_MEDAL_CHANGELING
|
||||
icon = "mafia"
|
||||
|
||||
/datum/award/achievement/mafia/thoughtfeeder
|
||||
name = "Thoughtfeeder Victory"
|
||||
desc = "Clown's best friend. And Obsessed. And fugitive? Whose side are you on?!"
|
||||
database_id = MAFIA_MEDAL_THOUGHTFEEDER
|
||||
icon = "mafia"
|
||||
|
||||
/datum/award/achievement/mafia/traitor
|
||||
name = "Traitor Victory"
|
||||
desc = "Guys, we still have two more changelings to ki-!! TRAITOR VICTORY !!"
|
||||
database_id = MAFIA_MEDAL_TRAITOR
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/nightmare
|
||||
name = "Nightmare Victory"
|
||||
desc = "DID YOUR LIGHT FLICKER?!"
|
||||
database_id = MAFIA_MEDAL_NIGHTMARE
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/fugitive
|
||||
name = "Fugitive Victory"
|
||||
desc = "I'm just the description on an achievement, but if you end up having to choose between town and changelings, go changelings."
|
||||
database_id = MAFIA_MEDAL_FUGITIVE
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/obsessed
|
||||
name = "Obsessed Victory"
|
||||
desc = "You got your target lynched, so instead of being spiteful and annoying, you're just smug and annoying."
|
||||
database_id = MAFIA_MEDAL_OBSESSED
|
||||
icon = "neutral"
|
||||
|
||||
/datum/award/achievement/mafia/clown
|
||||
name = "Clown Victory"
|
||||
desc = "Did you know this works on traitors, despite their immunity? If you hit the jackpot and manage to kill one, they'll salt into the next dimension. Clown tips!"
|
||||
database_id = MAFIA_MEDAL_CLOWN
|
||||
icon = "neutral"
|
||||
|
||||
///ALL THE ACHIEVEMENTS FOR MISC MAFIA ODDITIES///
|
||||
|
||||
/datum/award/achievement/mafia/universally_hated
|
||||
name = "Universally Hated"
|
||||
desc = "Managed to get more than 12 votes when put up on trial, jesus christ."
|
||||
database_id = MAFIA_MEDAL_HATED
|
||||
icon = "hated"
|
||||
@@ -0,0 +1,161 @@
|
||||
/datum/award/achievement/misc
|
||||
category = "Misc"
|
||||
icon = "basemisc"
|
||||
|
||||
/datum/award/achievement/misc/meteor_examine
|
||||
name = "Your Life Before Your Eyes"
|
||||
desc = "Take a close look at hurtling space debris"
|
||||
database_id = MEDAL_METEOR
|
||||
icon = "meteors"
|
||||
|
||||
/datum/award/achievement/misc/pulse
|
||||
name = "Jackpot"
|
||||
desc = "Win a pulse rifle from an arcade machine"
|
||||
database_id = MEDAL_PULSE
|
||||
icon = "jackpot"
|
||||
|
||||
/datum/award/achievement/misc/time_waste
|
||||
name = "Time waster"
|
||||
desc = "Speak no evil, hear no evil, see just errors"
|
||||
database_id = MEDAL_TIMEWASTE
|
||||
icon = "timewaste"
|
||||
|
||||
/datum/award/achievement/misc/feat_of_strength
|
||||
name = "Feat of Strength"
|
||||
desc = "If the rod is immovable, is it passing you or are you passing it?"
|
||||
database_id = MEDAL_RODSUPLEX
|
||||
icon = "featofstrength"
|
||||
|
||||
/datum/award/achievement/misc/round_and_full
|
||||
name = "Round and Full"
|
||||
desc = "Well at least you aren't down the river, I hear they eat people there."
|
||||
database_id = MEDAL_CLOWNCARKING
|
||||
icon = "clownking"
|
||||
|
||||
/datum/award/achievement/misc/the_best_driver
|
||||
name = "The Best Driver"
|
||||
desc = "100 honks later"
|
||||
database_id = MEDAL_THANKSALOT
|
||||
icon = "clownthanks"
|
||||
|
||||
/datum/award/achievement/misc/helbitaljanken
|
||||
name = "Helbitaljanken"
|
||||
desc = "You janked hard"
|
||||
database_id = MEDAL_HELBITALJANKEN
|
||||
icon = "helbital"
|
||||
|
||||
/datum/award/achievement/misc/getting_an_upgrade
|
||||
name = "Getting an upgrade"
|
||||
desc = "Make your first unique material item!"
|
||||
database_id = MEDAL_MATERIALCRAFT
|
||||
|
||||
/datum/award/achievement/misc/rocket_holdup
|
||||
name = "Disk, Please!"
|
||||
desc = "Is the man currently pointing a loaded rocket launcher at your head point blank really dumb enough to pull the trigger? Do you really want to find out?"
|
||||
database_id = MEDAL_DISKPLEASE
|
||||
|
||||
/datum/award/achievement/misc/gamer
|
||||
name = "My Watchlist Status is Not Important"
|
||||
desc = "You may be under the impression that violent video games are a harmless pastime, but the security and medical personnel swarming your location with batons and knockout gas look like they disagree."
|
||||
database_id = MEDAL_GAMER
|
||||
|
||||
/datum/award/achievement/misc/vendor_squish
|
||||
name = "I Was a Teenage Anarchist"
|
||||
desc = "You were doing a great job sticking it to the system until that vending machine decided to fight back."
|
||||
database_id = MEDAL_VENDORSQUISH
|
||||
|
||||
/datum/award/achievement/misc/swirlie
|
||||
name = "A Bowl-d New World"
|
||||
desc = "There's a lot of grisly ways to kick it on the Spinward Periphery, but drowning to death in a toilet probably wasn't what you had in mind. Probably."
|
||||
database_id = MEDAL_SWIRLIE
|
||||
|
||||
/datum/award/achievement/misc/selfouch
|
||||
name = "How Do I Switch Hands???"
|
||||
desc = "If you saw someone casually club themselves upside the head with a toolbox anywhere in the galaxy but here, you'd probably be pretty concerned for them."
|
||||
database_id = MEDAL_SELFOUCH
|
||||
|
||||
/datum/award/achievement/misc/sandman
|
||||
name = "Mister Sandman"
|
||||
desc = "Mechanically speaking, there's no real benefit to being unconscious during surgery. Weird how insistent this doctor is about using the N2O anyway though, huh?"
|
||||
database_id = MEDAL_SANDMAN
|
||||
|
||||
/datum/award/achievement/misc/cleanboss
|
||||
name = "One Lean, Mean, Cleaning Machine"
|
||||
desc = "How does it feel to know that your workplace values a mop bucket on wheels more than you?" // i can do better than this give me time
|
||||
database_id = MEDAL_CLEANBOSS
|
||||
|
||||
/datum/award/achievement/misc/rule8
|
||||
name = "Rule 8"
|
||||
desc = "Call an admin this is ILLEGAL!!"
|
||||
database_id = MEDAL_RULE8
|
||||
icon = "rule8"
|
||||
|
||||
/datum/award/achievement/misc/speed_round
|
||||
name = "Long shift"
|
||||
desc = "Well, that didn't take long."
|
||||
database_id = MEDAL_LONGSHIFT
|
||||
icon = "longshift"
|
||||
|
||||
/datum/award/achievement/misc/snail
|
||||
name = "KKKiiilll mmmeee"
|
||||
desc = "You were a little too ambitious, but hey, I guess you're still alive?"
|
||||
database_id = MEDAL_SNAIL
|
||||
icon = "snail"
|
||||
|
||||
/datum/award/achievement/misc/lookoutsir
|
||||
name = "Look Out, Sir!"
|
||||
desc = "Either awarded for making the ultimate sacrifice for your comrades, or a really dumb attempt at grenade jumping."
|
||||
database_id = MEDAL_LOOKOUTSIR
|
||||
|
||||
/datum/award/achievement/misc/gottem
|
||||
name = "HA, GOTTEM"
|
||||
desc = "Made you look!"
|
||||
database_id = MEDAL_GOTTEM
|
||||
|
||||
/datum/award/achievement/misc/ascension
|
||||
name = "Ascension"
|
||||
desc = "Caedite eos. Novit enim Dominus qui sunt eius."
|
||||
database_id = MEDAL_ASCENSION
|
||||
icon = "ascension"
|
||||
|
||||
/datum/award/achievement/misc/frenching
|
||||
name = "Frenching"
|
||||
desc = "Just a taste, for science!"
|
||||
database_id = MEDAL_FRENCHING
|
||||
icon = "frenching"
|
||||
|
||||
/datum/award/achievement/misc/ash_ascension
|
||||
name = "Nightwatcher's Eyes"
|
||||
desc = "You've risen above the flames, became one with the ashes. You've been reborn as one with the Nightwatcher."
|
||||
database_id = MEDAL_ASH_ASCENSION
|
||||
icon = "ashascend"
|
||||
|
||||
/datum/award/achievement/misc/flesh_ascension
|
||||
name = "Vortex of Arms"
|
||||
desc = "You've became something more, something greater. A piece of the emperor resides within you, and you within him."
|
||||
database_id = MEDAL_FLESH_ASCENSION
|
||||
icon = "fleshascend"
|
||||
|
||||
/datum/award/achievement/misc/rust_ascension
|
||||
name = "Hills of Rust"
|
||||
desc = "You've summoned a piece of the Hill of rust, and so the Hills welcome you."
|
||||
database_id = MEDAL_RUST_ASCENSION
|
||||
icon = "rustascend"
|
||||
|
||||
/datum/award/achievement/misc/void_ascension
|
||||
name = "All that perish"
|
||||
desc = "Place of a different being, different time. Everything ends there... but maybe it is just the beginning?"
|
||||
database_id = MEDAL_VOID_ASCENSION
|
||||
icon = "voidascend"
|
||||
|
||||
/datum/award/achievement/misc/toolbox_soul
|
||||
name = "SOUL'd Out"
|
||||
desc = "My eternal soul was destroyed to make a toolbox look funny and all I got was this achievement..."
|
||||
database_id = MEDAL_TOOLBOX_SOUL
|
||||
icon = "toolbox_soul"
|
||||
|
||||
/datum/award/achievement/misc/chemistry_tut
|
||||
name = "Perfect chemistry blossom"
|
||||
desc = "Passed the chemistry tutorial with perfect purity!"
|
||||
database_id = MEDAL_CHEM_TUT
|
||||
icon = "chem_tut"
|
||||
@@ -0,0 +1,11 @@
|
||||
///How many times did we survive being a cripple?
|
||||
/datum/award/score/hardcore_random
|
||||
name = "Hardcore random points"
|
||||
desc = "Well, I might be a blind, deaf, crippled guy, but hey, at least I'm alive."
|
||||
database_id = HARDCORE_RANDOM_SCORE
|
||||
|
||||
///How many maintenance pills did you eat?
|
||||
/datum/award/score/maintenance_pill
|
||||
name = "Maintenance Pills Consumed"
|
||||
desc = "Wait why?"
|
||||
database_id = MAINTENANCE_PILL_SCORE
|
||||
@@ -0,0 +1,10 @@
|
||||
/datum/award/achievement/skill
|
||||
category = "Skills"
|
||||
icon = "baseskill"
|
||||
|
||||
/datum/award/achievement/skill/legendary_miner
|
||||
name = "Legendary miner"
|
||||
desc = "No mere rock can stop me!"
|
||||
database_id = MEDAL_LEGENDARY_MINER
|
||||
icon = "mining"
|
||||
|
||||
+88
-88
@@ -1,53 +1,53 @@
|
||||
/**
|
||||
*# Callback Datums
|
||||
*A datum that holds a proc to be called on another object, used to track proccalls to other objects
|
||||
*
|
||||
* ## USAGE
|
||||
*
|
||||
* ```
|
||||
* var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn)
|
||||
* var/timerid = addtimer(C, time, timertype)
|
||||
* you can also use the compiler define shorthand
|
||||
* var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, arg1, arg2, ... argn), time, timertype)
|
||||
* ```
|
||||
*
|
||||
* Note: proc strings can only be given for datum proc calls, global procs must be proc paths
|
||||
*
|
||||
* Also proc strings are strongly advised against because they don't compile error if the proc stops existing
|
||||
*
|
||||
* In some cases you can provide a shortform of the procname, see the proc typepath shortcuts documentation below
|
||||
*
|
||||
* ## INVOKING THE CALLBACK
|
||||
*`var/result = C.Invoke(args, to, add)` additional args are added after the ones given when the callback was created
|
||||
*
|
||||
* `var/result = C.InvokeAsync(args, to, add)` Asyncronous - returns . on the first sleep then continues on in the background
|
||||
* after the sleep/block ends, otherwise operates normally.
|
||||
*
|
||||
* ## PROC TYPEPATH SHORTCUTS
|
||||
* (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...)
|
||||
*
|
||||
* ### global proc while in another global proc:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(GLOBAL_PROC, .some_proc_here)`
|
||||
*
|
||||
* ### proc defined on current(src) object (when in a /proc/ and not an override) OR overridden at src or any of it's parents:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(src, .some_proc_here)`
|
||||
*
|
||||
* ### when the above doesn't apply:
|
||||
*.proc/procname
|
||||
*
|
||||
* `CALLBACK(src, .proc/some_proc_here)`
|
||||
*
|
||||
*
|
||||
* proc defined on a parent of a some type
|
||||
*
|
||||
* `/some/type/.proc/some_proc_here`
|
||||
*
|
||||
* Otherwise you must always provide the full typepath of the proc (/type/of/thing/proc/procname)
|
||||
*/
|
||||
*# Callback Datums
|
||||
*A datum that holds a proc to be called on another object, used to track proccalls to other objects
|
||||
*
|
||||
* ## USAGE
|
||||
*
|
||||
* ```
|
||||
* var/datum/callback/C = new(object|null, /proc/type/path|"procstring", arg1, arg2, ... argn)
|
||||
* var/timerid = addtimer(C, time, timertype)
|
||||
* you can also use the compiler define shorthand
|
||||
* var/timerid = addtimer(CALLBACK(object|null, /proc/type/path|procstring, arg1, arg2, ... argn), time, timertype)
|
||||
* ```
|
||||
*
|
||||
* Note: proc strings can only be given for datum proc calls, global procs must be proc paths
|
||||
*
|
||||
* Also proc strings are strongly advised against because they don't compile error if the proc stops existing
|
||||
*
|
||||
* In some cases you can provide a shortform of the procname, see the proc typepath shortcuts documentation below
|
||||
*
|
||||
* ## INVOKING THE CALLBACK
|
||||
*`var/result = C.Invoke(args, to, add)` additional args are added after the ones given when the callback was created
|
||||
*
|
||||
* `var/result = C.InvokeAsync(args, to, add)` Asyncronous - returns . on the first sleep then continues on in the background
|
||||
* after the sleep/block ends, otherwise operates normally.
|
||||
*
|
||||
* ## PROC TYPEPATH SHORTCUTS
|
||||
* (these operate on paths, not types, so to these shortcuts, datum is NOT a parent of atom, etc...)
|
||||
*
|
||||
* ### global proc while in another global proc:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(GLOBAL_PROC, .some_proc_here)`
|
||||
*
|
||||
* ### proc defined on current(src) object (when in a /proc/ and not an override) OR overridden at src or any of it's parents:
|
||||
* .procname
|
||||
*
|
||||
* `CALLBACK(src, .some_proc_here)`
|
||||
*
|
||||
* ### when the above doesn't apply:
|
||||
*.proc/procname
|
||||
*
|
||||
* `CALLBACK(src, .proc/some_proc_here)`
|
||||
*
|
||||
*
|
||||
* proc defined on a parent of a some type
|
||||
*
|
||||
* `/some/type/.proc/some_proc_here`
|
||||
*
|
||||
* Otherwise you must always provide the full typepath of the proc (/type/of/thing/proc/procname)
|
||||
*/
|
||||
/datum/callback
|
||||
|
||||
///The object we will be calling the proc on
|
||||
@@ -60,13 +60,13 @@
|
||||
var/datum/weakref/user
|
||||
|
||||
/**
|
||||
* Create a new callback datum
|
||||
*
|
||||
* Arguments
|
||||
* * thingtocall the object to call the proc on
|
||||
* * proctocall the proc to call on the target object
|
||||
* * ... an optional list of extra arguments to pass to the proc
|
||||
*/
|
||||
* Create a new callback datum
|
||||
*
|
||||
* Arguments
|
||||
* * thingtocall the object to call the proc on
|
||||
* * proctocall the proc to call on the target object
|
||||
* * ... an optional list of extra arguments to pass to the proc
|
||||
*/
|
||||
/datum/callback/New(thingtocall, proctocall, ...)
|
||||
if (thingtocall)
|
||||
object = thingtocall
|
||||
@@ -76,13 +76,13 @@
|
||||
if(usr)
|
||||
user = WEAKREF(usr)
|
||||
/**
|
||||
* Immediately Invoke proctocall on thingtocall, with waitfor set to false
|
||||
*
|
||||
* Arguments:
|
||||
* * thingtocall Object to call on
|
||||
* * proctocall Proc to call on that object
|
||||
* * ... optional list of arguments to pass as arguments to the proc being called
|
||||
*/
|
||||
* Immediately Invoke proctocall on thingtocall, with waitfor set to false
|
||||
*
|
||||
* Arguments:
|
||||
* * thingtocall Object to call on
|
||||
* * proctocall Proc to call on that object
|
||||
* * ... optional list of arguments to pass as arguments to the proc being called
|
||||
*/
|
||||
/world/proc/ImmediateInvokeAsync(thingtocall, proctocall, ...)
|
||||
set waitfor = FALSE
|
||||
|
||||
@@ -97,13 +97,13 @@
|
||||
call(thingtocall, proctocall)(arglist(calling_arguments))
|
||||
|
||||
/**
|
||||
* Invoke this callback
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall
|
||||
*/
|
||||
* Invoke this callback
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via [WrapAdminProcCall][/proc/WrapAdminProcCall]
|
||||
*/
|
||||
/datum/callback/proc/Invoke(...)
|
||||
if(!usr)
|
||||
var/datum/weakref/W = user
|
||||
@@ -130,13 +130,13 @@
|
||||
return call(object, delegate)(arglist(calling_arguments))
|
||||
|
||||
/**
|
||||
* Invoke this callback async (waitfor=false)
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall
|
||||
*/
|
||||
* Invoke this callback async (waitfor=false)
|
||||
*
|
||||
* Calls the registered proc on the registered object, if the user ref
|
||||
* can be resolved it also inclues that as an arg
|
||||
*
|
||||
* If the datum being called on is varedited, the call is wrapped via WrapAdminProcCall
|
||||
*/
|
||||
/datum/callback/proc/InvokeAsync(...)
|
||||
set waitfor = FALSE
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
|
||||
/**
|
||||
Helper datum for the select callbacks proc
|
||||
*/
|
||||
*/
|
||||
/datum/callback_select
|
||||
var/list/finished
|
||||
var/pendingcount
|
||||
@@ -192,16 +192,16 @@
|
||||
finished[index] = rtn
|
||||
|
||||
/**
|
||||
* Runs a list of callbacks asyncronously, returning only when all have finished
|
||||
*
|
||||
* Callbacks can be repeated, to call it multiple times
|
||||
*
|
||||
* Arguments:
|
||||
* * list/callbacks the list of callbacks to be called
|
||||
* * list/callback_args the list of lists of arguments to pass into each callback
|
||||
* * savereturns Optionally save and return the list of returned values from each of the callbacks
|
||||
* * resolution The number of byond ticks between each time you check if all callbacks are complete
|
||||
*/
|
||||
* Runs a list of callbacks asyncronously, returning only when all have finished
|
||||
*
|
||||
* Callbacks can be repeated, to call it multiple times
|
||||
*
|
||||
* Arguments:
|
||||
* * list/callbacks the list of callbacks to be called
|
||||
* * list/callback_args the list of lists of arguments to pass into each callback
|
||||
* * savereturns Optionally save and return the list of returned values from each of the callbacks
|
||||
* * resolution The number of byond ticks between each time you check if all callbacks are complete
|
||||
*/
|
||||
/proc/callback_select(list/callbacks, list/callback_args, savereturns = TRUE, resolution = 1)
|
||||
if (!callbacks)
|
||||
return
|
||||
|
||||
@@ -10,25 +10,37 @@
|
||||
*/
|
||||
|
||||
/datum/component/material_container
|
||||
/// The total amount of materials this material container contains
|
||||
var/total_amount = 0
|
||||
/// The maximum amount of materials this material container can contain
|
||||
var/max_amount
|
||||
var/sheet_type
|
||||
/// Map of material ref -> amount
|
||||
var/list/materials //Map of key = material ref | Value = amount
|
||||
/// The list of materials that this material container can accept
|
||||
var/list/allowed_materials
|
||||
var/show_on_examine
|
||||
var/disable_attackby
|
||||
var/list/allowed_typecache
|
||||
/// The last main material that was inserted into this container
|
||||
var/last_inserted_id
|
||||
/// Whether or not this material container allows specific amounts from sheets to be inserted
|
||||
var/precise_insertion = FALSE
|
||||
/// A callback invoked before materials are inserted into this container
|
||||
var/datum/callback/precondition
|
||||
/// A callback invoked after materials are inserted into this container
|
||||
var/datum/callback/after_insert
|
||||
|
||||
/// Sets up the proper signals and fills the list of materials with the appropriate references.
|
||||
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert, _disable_attackby)
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
materials = list()
|
||||
max_amount = max(0, max_amt)
|
||||
show_on_examine = _show_on_examine
|
||||
disable_attackby = _disable_attackby
|
||||
|
||||
allowed_materials = mat_list || list()
|
||||
if(allowed_types)
|
||||
if(ispath(allowed_types) && allowed_types == /obj/item/stack)
|
||||
allowed_typecache = GLOB.typecache_stack
|
||||
@@ -38,14 +50,32 @@
|
||||
precondition = _precondition
|
||||
after_insert = _after_insert
|
||||
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/OnExamine)
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/on_attackby)
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine)
|
||||
|
||||
for(var/mat in mat_list) //Make the assoc list ref | amount
|
||||
var/datum/material/M = SSmaterials.GetMaterialRef(mat)
|
||||
materials[M] = 0
|
||||
for(var/mat in mat_list) //Make the assoc list material reference -> amount
|
||||
var/mat_ref = SSmaterials.GetMaterialRef(mat)
|
||||
if(isnull(mat_ref))
|
||||
continue
|
||||
var/mat_amt = mat_list[mat]
|
||||
if(isnull(mat_amt))
|
||||
mat_amt = 0
|
||||
materials[mat_ref] += mat_amt
|
||||
|
||||
/datum/component/material_container/Destroy(force, silent)
|
||||
materials = null
|
||||
allowed_typecache = null
|
||||
// if(insertion_check)
|
||||
// QDEL_NULL(insertion_check)
|
||||
if(precondition)
|
||||
QDEL_NULL(precondition)
|
||||
if(after_insert)
|
||||
QDEL_NULL(after_insert)
|
||||
return ..()
|
||||
|
||||
/datum/component/material_container/proc/on_examine(datum/source, mob/user, list/examine_list)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
/datum/component/material_container/proc/OnExamine(datum/source, mob/user, list/examine_list)
|
||||
if(show_on_examine)
|
||||
for(var/I in materials)
|
||||
var/datum/material/M = I
|
||||
@@ -54,7 +84,9 @@
|
||||
examine_list += "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>"
|
||||
|
||||
/// Proc that allows players to fill the parent with mats
|
||||
/datum/component/material_container/proc/OnAttackBy(datum/source, obj/item/I, mob/living/user)
|
||||
/datum/component/material_container/proc/on_attackby(datum/source, obj/item/I, mob/living/user)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/list/tc = allowed_typecache
|
||||
if(disable_attackby)
|
||||
return
|
||||
@@ -63,20 +95,21 @@
|
||||
if(I.item_flags & ABSTRACT)
|
||||
return
|
||||
if((I.flags_1 & HOLOGRAM_1) || (I.item_flags & NO_MAT_REDEMPTION) || (tc && !is_type_in_typecache(I, tc)))
|
||||
// if(!(mat_container_flags & MATCONTAINER_SILENT))
|
||||
to_chat(user, "<span class='warning'>[parent] won't accept [I]!</span>")
|
||||
return
|
||||
. = COMPONENT_NO_AFTERATTACK
|
||||
var/datum/callback/pc = precondition
|
||||
if(pc && !pc.Invoke(user))
|
||||
return
|
||||
var/material_amount = get_item_material_amount(I)
|
||||
var/material_amount = get_item_material_amount(I) //, mat_container_flags)
|
||||
if(!material_amount)
|
||||
to_chat(user, "<span class='warning'>[I] does not contain sufficient materials to be accepted by [parent].</span>")
|
||||
return
|
||||
if((!precise_insertion || !GLOB.typecache_stack[I.type]) && !has_space(material_amount))
|
||||
to_chat(user, "<span class='warning'>[parent] has not enough space. Please remove materials from [parent] in order to insert more.</span>")
|
||||
to_chat(user, "<span class='warning'>[parent] is full. Please remove materials from [parent] in order to insert more.</span>")
|
||||
return
|
||||
user_insert(I, user)
|
||||
user_insert(I, user) //, mat_container_flags)
|
||||
|
||||
/// Proc used for when player inserts materials
|
||||
/datum/component/material_container/proc/user_insert(obj/item/I, mob/living/user)
|
||||
@@ -94,7 +127,7 @@
|
||||
if(!user.temporarilyRemoveItemFromInventory(I))
|
||||
to_chat(user, "<span class='warning'>[I] is stuck to you and cannot be placed into [parent].</span>")
|
||||
return
|
||||
var/inserted = insert_item(I, stack_amt = requested_amount)
|
||||
var/inserted = insert_item(I, stack_amt = requested_amount)//, breakdown_flags= mat_container_flags)
|
||||
if(inserted)
|
||||
to_chat(user, "<span class='notice'>You insert a material total of [inserted] into [parent].</span>")
|
||||
qdel(I)
|
||||
@@ -117,16 +150,46 @@
|
||||
last_inserted_id = insert_item_materials(I, multiplier)
|
||||
return material_amount
|
||||
|
||||
/**
|
||||
* Inserts the relevant materials from an item into this material container.
|
||||
*
|
||||
* Arguments:
|
||||
* - [source][/obj/item]: The source of the materials we are inserting.
|
||||
* - multiplier: The multiplier for the materials being inserted.
|
||||
* - breakdown_flags: The breakdown bitflags that will be used to retrieve the materials from the source
|
||||
*/
|
||||
/datum/component/material_container/proc/insert_item_materials(obj/item/I, multiplier = 1)
|
||||
var/primary_mat
|
||||
var/max_mat_value = 0
|
||||
for(var/MAT in materials)
|
||||
materials[MAT] += I.custom_materials[MAT] * multiplier
|
||||
total_amount += I.custom_materials[MAT] * multiplier
|
||||
if(I.custom_materials[MAT] > max_mat_value)
|
||||
var/list/item_materials = I.custom_materials
|
||||
for(var/MAT in item_materials)
|
||||
if(!can_hold_material(MAT))
|
||||
continue
|
||||
materials[MAT] += item_materials[MAT] * multiplier
|
||||
total_amount += item_materials[MAT] * multiplier
|
||||
if(item_materials[MAT] > max_mat_value)
|
||||
max_mat_value = item_materials[MAT]
|
||||
primary_mat = MAT
|
||||
|
||||
return primary_mat
|
||||
|
||||
/**
|
||||
* The default check for whether we can add materials to this material container.
|
||||
*
|
||||
* Arguments:
|
||||
* - [mat][/atom/material]: The material we are checking for insertability.
|
||||
*/
|
||||
/datum/component/material_container/proc/can_hold_material(datum/material/mat)
|
||||
if(mat in allowed_typecache)
|
||||
return TRUE
|
||||
if(istype(mat) && ((mat.id in allowed_typecache) || (mat.type in allowed_materials)))
|
||||
allowed_materials += mat // This could get messy with passing lists by ref... but if you're doing that the list expansion is probably being taken care of elsewhere anyway...
|
||||
return TRUE
|
||||
// if(insertion_check?.Invoke(mat))
|
||||
// allowed_materials += mat
|
||||
// return TRUE
|
||||
return FALSE
|
||||
|
||||
/// For inserting an amount of material
|
||||
/datum/component/material_container/proc/insert_amount_mat(amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
|
||||
@@ -275,6 +275,11 @@
|
||||
else
|
||||
target.visible_message("<span class='danger'>[target] is hit by a [proj_name][hit_part ? " in the [hit_part.name]" : ""]!</span>", null, null, COMBAT_MESSAGE_RANGE, target)
|
||||
to_chat(target, "<span class='userdanger'>You're hit by a [proj_name][hit_part ? " in the [hit_part.name]" : ""]!</span>")
|
||||
|
||||
for(var/M in purple_hearts)
|
||||
var/mob/living/martyr = M
|
||||
if(martyr.stat == DEAD && martyr.client)
|
||||
martyr.client.give_award(/datum/award/achievement/misc/lookoutsir, martyr)
|
||||
UnregisterSignal(parent, COMSIG_PARENT_PREQDELETED)
|
||||
if(queued_delete)
|
||||
qdel(parent)
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
_S.add(can_insert)
|
||||
S.use(can_insert, TRUE)
|
||||
return TRUE
|
||||
return ..(S.change_stack(null, can_insert), override)
|
||||
I = S.split_stack(null, can_insert)
|
||||
return ..()
|
||||
|
||||
/datum/component/storage/concrete/stack/remove_from_storage(obj/item/I, atom/new_location)
|
||||
var/atom/real_location = real_location()
|
||||
|
||||
@@ -99,18 +99,18 @@
|
||||
falloff_exponent = 5
|
||||
volume = 50
|
||||
*/
|
||||
// /datum/looping_sound/computer
|
||||
// start_sound = 'sound/machines/computer/computer_start.ogg'
|
||||
// start_length = 7.2 SECONDS
|
||||
// start_volume = 10
|
||||
// mid_sounds = list('sound/machines/computer/computer_mid1.ogg'=1, 'sound/machines/computer/computer_mid2.ogg'=1)
|
||||
// mid_length = 1.8 SECONDS
|
||||
// end_sound = 'sound/machines/computer/computer_end.ogg'
|
||||
// end_volume = 10
|
||||
// volume = 2
|
||||
// falloff_exponent = 5 //Ultra quiet very fast
|
||||
// extra_range = -12
|
||||
// falloff_distance = 1 //Instant falloff after initial tile
|
||||
/datum/looping_sound/computer
|
||||
start_sound = 'sound/machines/computer/computer_start.ogg'
|
||||
start_length = 7.2 SECONDS
|
||||
start_volume = 10
|
||||
mid_sounds = list('sound/machines/computer/computer_mid1.ogg'=1, 'sound/machines/computer/computer_mid2.ogg'=1)
|
||||
mid_length = 1.8 SECONDS
|
||||
end_sound = 'sound/machines/computer/computer_end.ogg'
|
||||
end_volume = 10
|
||||
volume = 2
|
||||
falloff_exponent = 5 //Ultra quiet very fast
|
||||
extra_range = -12
|
||||
falloff_distance = 1 //Instant falloff after initial tile
|
||||
|
||||
// /datum/looping_sound/gravgen
|
||||
// mid_sounds = list('sound/machines/gravgen/gravgen_mid1.ogg'=1,'sound/machines/gravgen/gravgen_mid2.ogg'=1,'sound/machines/gravgen/gravgen_mid3.ogg'=1,'sound/machines/gravgen/gravgen_mid4.ogg'=1,)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
start_sound = 'sound/weather/ashstorm/outside/active_start.ogg'
|
||||
start_length = 130
|
||||
end_sound = 'sound/weather/ashstorm/outside/active_end.ogg'
|
||||
volume = 80
|
||||
volume = 60
|
||||
|
||||
/datum/looping_sound/active_inside_ashstorm
|
||||
mid_sounds = list(
|
||||
@@ -20,7 +20,7 @@
|
||||
start_sound = 'sound/weather/ashstorm/inside/active_start.ogg'
|
||||
start_length = 130
|
||||
end_sound = 'sound/weather/ashstorm/inside/active_end.ogg'
|
||||
volume = 60
|
||||
volume = 20
|
||||
|
||||
/datum/looping_sound/weak_outside_ashstorm
|
||||
mid_sounds = list(
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
/*! Material datum
|
||||
|
||||
Simple datum which is instanced once per type and is used for every object of said material. It has a variety of variables that define behavior. Subtyping from this makes it easier to create your own materials.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/datum/material
|
||||
/// What the material is referred to as IC.
|
||||
var/name = "material"
|
||||
/// A short description of the material. Not used anywhere, yet...
|
||||
var/desc = "its..stuff."
|
||||
/// What the material is indexed by in the SSmaterials.materials list. Defaults to the type of the material.
|
||||
var/id
|
||||
|
||||
///Base color of the material, is used for greyscale. Item isn't changed in color if this is null.
|
||||
var/color
|
||||
///Base alpha of the material, is used for greyscale icons.
|
||||
var/alpha
|
||||
///Bitflags that influence how SSmaterials handles this material.
|
||||
// var/init_flags = MATERIAL_INIT_MAPLOAD
|
||||
///Materials "Traits". its a map of key = category | Value = Bool. Used to define what it can be used for
|
||||
var/list/categories = list()
|
||||
///The type of sheet this material creates. This should be replaced as soon as possible by greyscale sheets
|
||||
@@ -22,7 +31,7 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
var/value_per_unit = 0
|
||||
///Armor modifiers, multiplies an items normal armor vars by these amounts.
|
||||
var/armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1)
|
||||
///How beautiful is this material per unit?
|
||||
///How beautiful is this material per unit.
|
||||
var/beauty_modifier = 0
|
||||
///Can be used to override the sound items make, lets add some SLOSHing.
|
||||
var/item_sound_override
|
||||
@@ -30,14 +39,31 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
var/turf_sound_override
|
||||
///what texture icon state to overlay
|
||||
var/texture_layer_icon_state
|
||||
///a cached filter for the texture icon
|
||||
///a cached icon for the texture filter
|
||||
var/cached_texture_filter
|
||||
///What type of shard the material will shatter to
|
||||
var/obj/item/shard_type
|
||||
|
||||
|
||||
/** Handles initializing the material.
|
||||
*
|
||||
* Arugments:
|
||||
* - _id: The ID the material should use. Overrides the existing ID.
|
||||
*/
|
||||
/datum/material/proc/Initialize(_id, ...)
|
||||
if(_id)
|
||||
id = _id
|
||||
else if(isnull(id))
|
||||
id = type
|
||||
|
||||
if(texture_layer_icon_state)
|
||||
cached_texture_filter = icon('icons/materials/composite.dmi', texture_layer_icon_state)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/material/New()
|
||||
. = ..()
|
||||
if(texture_layer_icon_state)
|
||||
var/texture_icon = icon('icons/materials/composite.dmi', texture_layer_icon_state)
|
||||
cached_texture_filter = filter(type="layer", icon=texture_icon, blend_mode = BLEND_INSET_OVERLAY)
|
||||
Initialize()
|
||||
|
||||
///This proc is called when the material is added to an object.
|
||||
/datum/material/proc/on_applied(atom/source, amount, material_flags)
|
||||
@@ -48,18 +74,20 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
source.alpha = alpha
|
||||
if(texture_layer_icon_state)
|
||||
ADD_KEEP_TOGETHER(source, MATERIAL_SOURCE(src))
|
||||
source.filters += cached_texture_filter
|
||||
source.add_filter("material_texture_[name]",1,layering_filter(icon=cached_texture_filter,blend_mode=BLEND_INSET_OVERLAY))
|
||||
|
||||
if(alpha < 255)
|
||||
source.opacity = FALSE
|
||||
if(material_flags & MATERIAL_ADD_PREFIX)
|
||||
source.name = "[name] [source.name]"
|
||||
|
||||
if(beauty_modifier)
|
||||
addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, beauty_modifier * amount)), 0)
|
||||
// if(beauty_modifier) returnign in hardsync2 if i ever port ebeauty cmp
|
||||
// addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, beauty_modifier * amount)), 0)
|
||||
|
||||
if(istype(source, /obj)) //objs
|
||||
on_applied_obj(source, amount, material_flags)
|
||||
|
||||
else if(isturf(source, /turf)) //turfs
|
||||
if(istype(source, /turf)) //turfs
|
||||
on_applied_turf(source, amount, material_flags)
|
||||
|
||||
source.mat_update_desc(src)
|
||||
@@ -67,8 +95,9 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
///This proc is called when a material updates an object's description
|
||||
/atom/proc/mat_update_desc(/datum/material/mat)
|
||||
return
|
||||
|
||||
///This proc is called when the material is added to an object specifically.
|
||||
/datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags)
|
||||
/datum/material/proc/on_applied_obj(obj/o, amount, material_flags)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
@@ -92,43 +121,73 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
I.hitsound = item_sound_override
|
||||
I.usesound = item_sound_override
|
||||
I.throwhitsound = item_sound_override
|
||||
// I.mob_throw_hit_sound = item_sound_override
|
||||
// I.equip_sound = item_sound_override
|
||||
// I.pickup_sound = item_sound_override
|
||||
// I.drop_sound = item_sound_override
|
||||
|
||||
/datum/material/proc/on_applied_turf(var/turf/T, amount, material_flags)
|
||||
/datum/material/proc/on_applied_turf(turf/T, amount, material_flags)
|
||||
if(isopenturf(T))
|
||||
if(!turf_sound_override)
|
||||
return
|
||||
var/turf/open/O = T
|
||||
O.footstep = turf_sound_override
|
||||
O.barefootstep = turf_sound_override
|
||||
O.clawfootstep = turf_sound_override
|
||||
O.heavyfootstep = turf_sound_override
|
||||
if(turf_sound_override)
|
||||
var/turf/open/O = T
|
||||
O.footstep = turf_sound_override
|
||||
O.barefootstep = turf_sound_override
|
||||
O.clawfootstep = turf_sound_override
|
||||
O.heavyfootstep = turf_sound_override
|
||||
// if(alpha < 255)
|
||||
// T.AddElement(/datum/element/turf_z_transparency, TRUE)
|
||||
return
|
||||
|
||||
///This proc is called when the material is removed from an object.
|
||||
/datum/material/proc/on_removed(atom/source, material_flags)
|
||||
/datum/material/proc/on_removed(atom/source, amount, material_flags)
|
||||
if(material_flags & MATERIAL_COLOR) //Prevent changing things with pre-set colors, to keep colored toolboxes their looks for example
|
||||
if(color)
|
||||
source.remove_atom_colour(FIXED_COLOUR_PRIORITY, color)
|
||||
source.alpha = initial(source.alpha)
|
||||
if(texture_layer_icon_state)
|
||||
source.filters -= cached_texture_filter
|
||||
source.remove_filter("material_texture_[name]")
|
||||
REMOVE_KEEP_TOGETHER(source, MATERIAL_SOURCE(src))
|
||||
source.alpha = initial(source.alpha)
|
||||
|
||||
if(material_flags & MATERIAL_ADD_PREFIX)
|
||||
source.name = initial(source.name)
|
||||
|
||||
if(istype(source, /obj)) //objs
|
||||
on_removed_obj(source, material_flags)
|
||||
// if(beauty_modifier) //component/beauty/InheritComponent() will handle the removal.
|
||||
// addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, -beauty_modifier * amount)), 0)
|
||||
|
||||
else if(istype(source, /turf)) //turfs
|
||||
on_removed_turf(source, material_flags)
|
||||
if(istype(source, /obj)) //objs
|
||||
on_removed_obj(source, amount, material_flags)
|
||||
|
||||
if(istype(source, /turf)) //turfs
|
||||
on_removed_turf(source, amount, material_flags)
|
||||
|
||||
///This proc is called when the material is removed from an object specifically.
|
||||
/datum/material/proc/on_removed_obj(obj/o, material_flags)
|
||||
/datum/material/proc/on_removed_obj(obj/o, amount, material_flags)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = initial(o.max_integrity)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force = initial(o.force)
|
||||
o.throwforce = initial(o.throwforce)
|
||||
|
||||
/datum/material/proc/on_removed_turf(turf/T, material_flags)
|
||||
return
|
||||
/datum/material/proc/on_removed_turf(turf/T, amount, material_flags)
|
||||
// if(alpha)
|
||||
// RemoveElement(/datum/element/turf_z_transparency, FALSE)
|
||||
|
||||
/**
|
||||
* This proc is called when the mat is found in an item that's consumed by accident. see /obj/item/proc/on_accidental_consumption.
|
||||
* Arguments
|
||||
* * M - person consuming the mat
|
||||
* * S - (optional) item the mat is contained in (NOT the item with the mat itself)
|
||||
*/
|
||||
/datum/material/proc/on_accidental_mat_consumption(mob/living/carbon/M, obj/item/S)
|
||||
return FALSE
|
||||
|
||||
/** Returns the composition of this material.
|
||||
*
|
||||
* Mostly used for alloys when breaking down materials.
|
||||
*
|
||||
* Arguments:
|
||||
* - amount: The amount of the material to break down.
|
||||
* - breakdown_flags: Some flags dictating how exactly this material is being broken down.
|
||||
*/
|
||||
/datum/material/proc/return_composition(amount=1, breakdown_flags=NONE)
|
||||
return list((src) = amount) // Yes we need the parenthesis, without them BYOND stringifies src into "src" and things break.
|
||||
|
||||
+158
-69
@@ -8,12 +8,16 @@
|
||||
var/description
|
||||
var/prerequisites
|
||||
var/admin_notes
|
||||
|
||||
/// How much does this shuttle cost the cargo budget to purchase? Put in terms of CARGO_CRATE_VALUE to properly scale the cost with the current balance of cargo's income.
|
||||
var/credit_cost = INFINITY
|
||||
/// Can the be legitimately purchased by the station? Used by hardcoded or pre-mapped shuttles like the lavaland or cargo shuttle.
|
||||
var/can_be_bought = TRUE
|
||||
/// If set, overrides default movement_force on shuttle
|
||||
var/list/movement_force
|
||||
|
||||
var/port_x_offset
|
||||
var/port_y_offset
|
||||
var/extra_desc = ""
|
||||
|
||||
/datum/map_template/shuttle/proc/prerequisites_met()
|
||||
return TRUE
|
||||
@@ -23,7 +27,7 @@
|
||||
mappath = "[prefix][shuttle_id].dmm"
|
||||
. = ..()
|
||||
|
||||
/datum/map_template/shuttle/preload_size(path = mappath, force_cache = FALSE)
|
||||
/datum/map_template/shuttle/preload_size(path, force_cache)
|
||||
. = ..(path, TRUE) // Done this way because we still want to know if someone actualy wanted to cache the map
|
||||
if(!cached_map)
|
||||
return
|
||||
@@ -64,6 +68,9 @@
|
||||
continue
|
||||
if(length(place.baseturfs) < 2) // Some snowflake shuttle shit
|
||||
continue
|
||||
// var/list/sanity = place.baseturfs.Copy() // we do not have new baseturfs yet
|
||||
// sanity.Insert(3, /turf/baseturf_skipover/shuttle)
|
||||
// place.baseturfs = baseturfs_string_list(sanity, place)
|
||||
place.baseturfs.Insert(3, /turf/baseturf_skipover/shuttle)
|
||||
|
||||
for(var/obj/docking_port/mobile/port in place)
|
||||
@@ -93,6 +100,7 @@
|
||||
port.dwidth = port_y_offset - 1
|
||||
port.dheight = width - port_x_offset
|
||||
|
||||
// these three for loops are cit specific.
|
||||
for(var/obj/structure/closet/closet in place)
|
||||
if(closet.anchorable)
|
||||
closet.anchored = TRUE
|
||||
@@ -104,11 +112,10 @@
|
||||
rack.AddComponent(/datum/component/magnetic_catch)
|
||||
|
||||
//Whatever special stuff you want
|
||||
/datum/map_template/shuttle/proc/post_load(obj/docking_port/mobile/M)
|
||||
return
|
||||
|
||||
/datum/map_template/shuttle/proc/on_bought()
|
||||
return
|
||||
/datum/map_template/shuttle/post_load(obj/docking_port/mobile/M)
|
||||
if(movement_force)
|
||||
M.movement_force = movement_force.Copy()
|
||||
M.linkup()
|
||||
|
||||
/datum/map_template/shuttle/emergency
|
||||
port_id = "emergency"
|
||||
@@ -117,6 +124,7 @@
|
||||
/datum/map_template/shuttle/cargo
|
||||
port_id = "cargo"
|
||||
name = "Base Shuttle Template (Cargo)"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/ferry
|
||||
port_id = "ferry"
|
||||
@@ -137,10 +145,6 @@
|
||||
port_id = "mining_common"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/cargo
|
||||
port_id = "cargo"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/arrival
|
||||
port_id = "arrival"
|
||||
can_be_bought = FALSE
|
||||
@@ -189,21 +193,23 @@
|
||||
name = "Backup Shuttle"
|
||||
can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/emergency/airless
|
||||
suffix = "airless"
|
||||
/datum/map_template/shuttle/emergency/construction
|
||||
suffix = "construction"
|
||||
name = "Build your own shuttle kit"
|
||||
description = "Save money by building your own shuttle! The chassis will dock upon purchase, but launch will have to be authorized as usual via shuttle call. Interior and lighting not included."
|
||||
description = "For the enterprising shuttle engineer! The chassis will dock upon purchase, but launch will have to be authorized as usual via shuttle call. Comes stocked with construction materials. Unlocks the ability to buy shuttle engine crates from cargo."
|
||||
admin_notes = "No brig, no medical facilities, just an empty box."
|
||||
credit_cost = -7500
|
||||
|
||||
/datum/map_template/shuttle/emergency/airless/prerequisites_met()
|
||||
/datum/map_template/shuttle/emergency/construction/prerequisites_met()
|
||||
// first 10 minutes only
|
||||
return world.time - SSticker.round_start_time < 6000
|
||||
|
||||
/datum/map_template/shuttle/emergency/airless/on_bought()
|
||||
//enable buying engines from cargo
|
||||
var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shuttle_engine]
|
||||
P.special_enabled = TRUE
|
||||
// this is broken and does not work. Thanks TG
|
||||
// /datum/map_template/shuttle/emergency/airless/post_load()
|
||||
// . = ..()
|
||||
// //enable buying engines from cargo
|
||||
// var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shuttle_engine]
|
||||
// P.special_enabled = TRUE
|
||||
|
||||
|
||||
/datum/map_template/shuttle/emergency/asteroid
|
||||
@@ -220,6 +226,13 @@
|
||||
Has medical facilities."
|
||||
credit_cost = 5000
|
||||
|
||||
// /datum/map_template/shuttle/emergency/pod
|
||||
// suffix = "pod"
|
||||
// name = "Emergency Pods"
|
||||
// description = "We did not expect an evacuation this quickly. All we have available is two escape pods."
|
||||
// admin_notes = "For player punishment."
|
||||
// can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/emergency/russiafightpit
|
||||
suffix = "russiafightpit"
|
||||
name = "Mother Russia Bleeds"
|
||||
@@ -230,9 +243,10 @@
|
||||
/datum/map_template/shuttle/emergency/meteor
|
||||
suffix = "meteor"
|
||||
name = "Asteroid With Engines Strapped To It"
|
||||
description = "A hollowed out asteroid with engines strapped to it. Due to its size and difficulty in steering it, this shuttle may damage the docking area."
|
||||
description = "A hollowed out asteroid with engines strapped to it, the hollowing procedure makes it very difficult to hijack but is very expensive. Due to its size and difficulty in steering it, this shuttle may damage the docking area."
|
||||
admin_notes = "This shuttle will likely crush escape, killing anyone there."
|
||||
credit_cost = -5000
|
||||
movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
|
||||
|
||||
/datum/map_template/shuttle/emergency/luxury
|
||||
suffix = "luxury"
|
||||
@@ -247,18 +261,30 @@
|
||||
description = "The glorious results of centuries of plasma research done by Nanotrasen employees. This is the reason why you are here. Get on and dance like you're on fire, burn baby burn!"
|
||||
admin_notes = "Flaming hot. The main area has a dance machine as well as plasma floor tiles that will be ignited by players every single time."
|
||||
credit_cost = 10000
|
||||
// can_be_bought = FALSE
|
||||
|
||||
/datum/map_template/shuttle/emergency/arena
|
||||
suffix = "arena"
|
||||
name = "The Arena"
|
||||
description = "The crew must pass through an otherworldy arena to board this shuttle. Expect massive casualties. The source of the Bloody Signal must be tracked down and eliminated to unlock this shuttle."
|
||||
admin_notes = "RIP AND TEAR."
|
||||
credit_cost = 10000
|
||||
// /datum/map_template/shuttle/emergency/arena
|
||||
// suffix = "arena"
|
||||
// name = "The Arena"
|
||||
// description = "The crew must pass through an otherworldy arena to board this shuttle. Expect massive casualties. The source of the Bloody Signal must be tracked down and eliminated to unlock this shuttle."
|
||||
// admin_notes = "RIP AND TEAR."
|
||||
// credit_cost = 10000
|
||||
// /// Whether the arena z-level has been created
|
||||
// var/arena_loaded = FALSE
|
||||
|
||||
/datum/map_template/shuttle/emergency/arena/prerequisites_met()
|
||||
if("bubblegum" in SSshuttle.shuttle_purchase_requirements_met)
|
||||
return TRUE
|
||||
return FALSE
|
||||
// /datum/map_template/shuttle/emergency/arena/prerequisites_met()
|
||||
// return SSshuttle.shuttle_purchase_requirements_met["bubblegum"]
|
||||
|
||||
// /datum/map_template/shuttle/emergency/arena/post_load(obj/docking_port/mobile/M)
|
||||
// . = ..()
|
||||
// if(!arena_loaded)
|
||||
// arena_loaded = TRUE
|
||||
// var/datum/map_template/arena/arena_template = new()
|
||||
// arena_template.load_new_z()
|
||||
|
||||
// /datum/map_template/arena
|
||||
// name = "The Arena"
|
||||
// mappath = "_maps/templates/the_arena.dmm"
|
||||
|
||||
/datum/map_template/shuttle/emergency/birdboat
|
||||
suffix = "birdboat"
|
||||
@@ -272,6 +298,13 @@
|
||||
credit_cost = 2000
|
||||
description = "The gold standard in emergency exfiltration, this tried and true design is equipped with everything the crew needs for a safe flight home."
|
||||
|
||||
// /datum/map_template/shuttle/emergency/donut
|
||||
// suffix = "donut"
|
||||
// name = "Donutstation Emergency Shuttle"
|
||||
// description = "The perfect spearhead for any crude joke involving the station's shape, this shuttle supports a separate containment cell for prisoners and a compact medical wing."
|
||||
// admin_notes = "Has airlocks on both sides of the shuttle and will probably intersect near the front on some stations that build past departures."
|
||||
// credit_cost = 2500
|
||||
|
||||
/datum/map_template/shuttle/emergency/clown
|
||||
suffix = "clown"
|
||||
name = "Snappop(tm)!"
|
||||
@@ -316,7 +349,9 @@
|
||||
credit_cost = -1000
|
||||
description = "Due to a lack of functional emergency shuttles, we bought this second hand from a scrapyard and pressed it into service. Please do not lean too heavily on the exterior windows, they are fragile."
|
||||
admin_notes = "An abomination with no functional medbay, sections missing, and some very fragile windows. Surprisingly airtight."
|
||||
movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
|
||||
|
||||
// CIT SPECIFIC
|
||||
/datum/map_template/shuttle/emergency/syndicate
|
||||
suffix = "syndicate"
|
||||
name = "Syndicate GM Battlecruiser"
|
||||
@@ -325,9 +360,7 @@
|
||||
admin_notes = "An emag exclusive, stocked with syndicate equipment and turrets that will target any simplemob."
|
||||
|
||||
/datum/map_template/shuttle/emergency/syndicate/prerequisites_met()
|
||||
if("emagged" in SSshuttle.shuttle_purchase_requirements_met)
|
||||
return TRUE
|
||||
return FALSE
|
||||
return SSshuttle.shuttle_purchase_requirements_met["emagged"]
|
||||
|
||||
/datum/map_template/shuttle/emergency/narnar
|
||||
suffix = "narnar"
|
||||
@@ -335,6 +368,10 @@
|
||||
description = "Looks like this shuttle may have wandered into the darkness between the stars on route to the station. Let's not think too hard about where all the bodies came from."
|
||||
admin_notes = "Contains real cult ruins, mob eyeballs, and inactive constructs. Cult mobs will automatically be sentienced by fun balloon. \
|
||||
Cloning pods in 'medbay' area are showcases and nonfunctional."
|
||||
credit_cost = 6667 ///The joke is the number so no defines
|
||||
|
||||
/datum/map_template/shuttle/emergency/narnar/prerequisites_met()
|
||||
return SSshuttle.shuttle_purchase_requirements_met["narsie"]
|
||||
|
||||
/datum/map_template/shuttle/emergency/pubby
|
||||
suffix = "pubby"
|
||||
@@ -354,7 +391,7 @@
|
||||
/datum/map_template/shuttle/emergency/supermatter
|
||||
suffix = "supermatter"
|
||||
name = "Hyperfractal Gigashuttle"
|
||||
description = "(Emag only) \"I dunno, this seems kinda needlessly complicated.\"\n\
|
||||
description = "\"I dunno, this seems kinda needlessly complicated.\"\n\
|
||||
\"This shuttle has very a very high safety record, according to CentCom Officer Cadet Yins.\"\n\
|
||||
\"Are you sure?\"\n\
|
||||
\"Yes, it has a safety record of N-A-N, which is apparently larger than 100%.\""
|
||||
@@ -363,19 +400,19 @@
|
||||
It does, however, still dust anything on contact, emits high levels of radiation, and induce hallucinations in anyone looking at it without protective goggles. \
|
||||
Emitters spawn powered on, expect admin notices, they are harmless."
|
||||
credit_cost = 15000
|
||||
movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
|
||||
|
||||
/datum/map_template/shuttle/emergency/supermatter/prerequisites_met()
|
||||
if("emagged" in SSshuttle.shuttle_purchase_requirements_met)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
return SSshuttle.shuttle_purchase_requirements_met["emagged"]
|
||||
/datum/map_template/shuttle/emergency/imfedupwiththisworld
|
||||
suffix = "imfedupwiththisworld"
|
||||
name = "Oh, Hi Daniel"
|
||||
description = "How was space work today? Oh, pretty good. We got a new space station and the company will make a lot of money. What space station? I cannot tell you; it's space confidential. \
|
||||
Aw, come space on. Why not? No, I can't. Anyway, how is your space roleplay life?"
|
||||
admin_notes = "Tiny, with a single airlock and wooden walls. What could go wrong?"
|
||||
// can_be_bought = FALSE
|
||||
credit_cost = -5000
|
||||
movement_force = list("KNOCKDOWN" = 3, "THROW" = 2)
|
||||
|
||||
/datum/map_template/shuttle/emergency/goon
|
||||
suffix = "goon"
|
||||
@@ -383,6 +420,14 @@
|
||||
description = "The Nanotrasen Emergency Shuttle Port(NES Port for short) is a shuttle used at other less known Nanotrasen facilities and has a more open inside for larger crowds, but fewer onboard shuttle facilities."
|
||||
credit_cost = 500
|
||||
|
||||
// /datum/map_template/shuttle/emergency/rollerdome
|
||||
// suffix = "rollerdome"
|
||||
// name = "Uncle Pete's Rollerdome"
|
||||
// description = "Developed by a member of Nanotrasen's R&D crew that claims to have travelled from the year 2028.
|
||||
// He says this shuttle is based off an old entertainment complex from the 1990s, though our database has no records on anything pertaining to that decade."
|
||||
// admin_notes = "ONLY NINETIES KIDS REMEMBER. Uses the fun balloon and drone from the Emergency Bar."
|
||||
// credit_cost = 500 * 5
|
||||
|
||||
/datum/map_template/shuttle/emergency/wabbajack
|
||||
suffix = "wabbajack"
|
||||
name = "NT Lepton Violet"
|
||||
@@ -398,6 +443,7 @@
|
||||
description = "On the smaller size with a modern design, this shuttle is for the crew who like the cosier things, while still being able to stretch their legs."
|
||||
credit_cost = 1000
|
||||
|
||||
// CIT SPECIFIC
|
||||
/datum/map_template/shuttle/emergency/gorilla
|
||||
suffix = "gorilla"
|
||||
name = "Gorilla Cargo Freighter"
|
||||
@@ -405,11 +451,17 @@
|
||||
credit_cost = 2000
|
||||
|
||||
/datum/map_template/shuttle/emergency/gorilla/prerequisites_met()
|
||||
if("emagged" in SSshuttle.shuttle_purchase_requirements_met)
|
||||
return TRUE
|
||||
return FALSE
|
||||
return SSshuttle.shuttle_purchase_requirements_met["emagged"]
|
||||
|
||||
/datum/map_template/shuttle/emergency/cruise
|
||||
|
||||
// /datum/map_template/shuttle/emergency/cruise
|
||||
// suffix = "cruise"
|
||||
// name = "The NTSS Independence"
|
||||
// description = "Ordinarily reserved for special functions and events, the Cruise Shuttle Independence can bring a summery cheer to your next station evacuation for a 'modest' fee!"
|
||||
// admin_notes = "This motherfucker is BIG. You might need to force dock it."
|
||||
// credit_cost = 8000
|
||||
|
||||
/datum/map_template/shuttle/emergency/monkey
|
||||
suffix = "nature"
|
||||
name = "Dynamic Environmental Interaction Shuttle"
|
||||
description = "A large shuttle with a center biodome that is flourishing with life. Frolick with the monkeys! (Extra monkeys are stored on the bridge.)"
|
||||
@@ -441,7 +493,7 @@
|
||||
/datum/map_template/shuttle/ferry/fancy
|
||||
suffix = "fancy"
|
||||
name = "fancy transport ferry"
|
||||
description = "At some point, someone upgraded the ferry to have fancier flooring... and less seats."
|
||||
description = "At some point, someone upgraded the ferry to have fancier flooring... and fewer seats."
|
||||
|
||||
/datum/map_template/shuttle/ferry/kilo
|
||||
suffix = "kilo"
|
||||
@@ -464,6 +516,14 @@
|
||||
suffix = "cere"
|
||||
name = "NT Construction Vessel"
|
||||
|
||||
// /datum/map_template/shuttle/whiteship/kilo
|
||||
// suffix = "kilo"
|
||||
// name = "NT Mining Shuttle"
|
||||
|
||||
// /datum/map_template/shuttle/whiteship/donut
|
||||
// suffix = "donut"
|
||||
// name = "NT Long-Distance Bluespace Jumper"
|
||||
|
||||
/datum/map_template/shuttle/whiteship/delta
|
||||
suffix = "delta"
|
||||
name = "NT Frigate"
|
||||
@@ -476,10 +536,6 @@
|
||||
suffix = "cog"
|
||||
name = "NT Prisoner Transport"
|
||||
|
||||
/datum/map_template/shuttle/cargo/box
|
||||
suffix = "box"
|
||||
name = "supply shuttle (Box)"
|
||||
|
||||
/datum/map_template/shuttle/cargo/kilo
|
||||
suffix = "kilo"
|
||||
name = "supply shuttle (Kilo)"
|
||||
@@ -488,6 +544,14 @@
|
||||
suffix = "birdboat"
|
||||
name = "supply shuttle (Birdboat)"
|
||||
|
||||
// /datum/map_template/shuttle/cargo/donut
|
||||
// suffix = "donut"
|
||||
// name = "supply shuttle (Donut)"
|
||||
|
||||
// /datum/map_template/shuttle/cargo/pubby
|
||||
// suffix = "pubby"
|
||||
// name = "supply shuttle (Pubby)"
|
||||
|
||||
/datum/map_template/shuttle/emergency/delta
|
||||
suffix = "delta"
|
||||
name = "Delta Station Emergency Shuttle"
|
||||
@@ -497,11 +561,24 @@
|
||||
|
||||
/datum/map_template/shuttle/emergency/raven
|
||||
suffix = "raven"
|
||||
name = "CentCom Raven Battlecruiser"
|
||||
description = "The CentCom Raven Battlecruiser is currently docked at the CentCom ship bay awaiting a mission, this Battlecruiser has been reassigned as an emergency escape shuttle for currently unknown reasons. The CentCom Raven Battlecruiser should comfortably fit a medium to large crew size crew and is complete with all required facitlities including a top of the range CentCom Medical Bay."
|
||||
admin_notes = "Comes with turrets that will target any simplemob."
|
||||
name = "CentCom Raven Cruiser"
|
||||
description = "The CentCom Raven Cruiser is a former high-risk salvage vessel, now repurposed into an emergency escape shuttle. \
|
||||
Once first to the scene to pick through warzones for valuable remains, it now serves as an excellent escape option for stations under heavy fire from outside forces. \
|
||||
This escape shuttle boasts shields and numerous anti-personnel turrets guarding its perimeter to fend off meteors and enemy boarding attempts."
|
||||
admin_notes = "Comes with turrets that will target anything without the neutral faction (nuke ops, xenos etc, but not pets)."
|
||||
credit_cost = 12500
|
||||
|
||||
// /datum/map_template/shuttle/emergency/zeta
|
||||
// suffix = "zeta"
|
||||
// name = "Tr%nPo2r& Z3TA"
|
||||
// description = "A glitch appears on your monitor, flickering in and out of the options laid before you.
|
||||
// It seems strange and alien, you may need a special technology to access the signal.."
|
||||
// admin_notes = "Has alien surgery tools, and a void core that provides unlimited power."
|
||||
// credit_cost = CARGO_CRATE_VALUE * 16
|
||||
|
||||
// /datum/map_template/shuttle/emergency/zeta/prerequisites_met()
|
||||
// return SSshuttle.shuttle_purchase_requirements_met[SHUTTLE_UNLOCK_ALIENTECH]
|
||||
|
||||
/datum/map_template/shuttle/emergency/cog
|
||||
suffix = "cog"
|
||||
name = "NES Classic"
|
||||
@@ -524,18 +601,22 @@
|
||||
suffix = "box"
|
||||
name = "labour shuttle (Box)"
|
||||
|
||||
/datum/map_template/shuttle/labour/kilo
|
||||
suffix = "kilo"
|
||||
name = "labour shuttle (Kilo)"
|
||||
|
||||
/datum/map_template/shuttle/labour/cog
|
||||
suffix = "cog"
|
||||
name = "labour shuttle (Cog)"
|
||||
|
||||
// /datum/map_template/shuttle/arrival/donut
|
||||
// suffix = "donut"
|
||||
// name = "arrival shuttle (Donut)"
|
||||
|
||||
/datum/map_template/shuttle/infiltrator/basic
|
||||
suffix = "basic"
|
||||
name = "basic syndicate infiltrator"
|
||||
|
||||
// /datum/map_template/shuttle/infiltrator/advanced
|
||||
// suffix = "advanced"
|
||||
// name = "advanced syndicate infiltrator"
|
||||
|
||||
/datum/map_template/shuttle/cargo/delta
|
||||
suffix = "delta"
|
||||
name = "cargo ferry (Delta)"
|
||||
@@ -548,17 +629,25 @@
|
||||
suffix = "kilo"
|
||||
name = "mining shuttle (Kilo)"
|
||||
|
||||
// /datum/map_template/shuttle/mining/large
|
||||
// suffix = "large"
|
||||
// name = "mining shuttle (Large)"
|
||||
|
||||
/datum/map_template/shuttle/labour/delta
|
||||
suffix = "delta"
|
||||
name = "labour shuttle (Delta)"
|
||||
|
||||
/datum/map_template/shuttle/labour/kilo
|
||||
suffix = "kilo"
|
||||
name = "labour shuttle (Kilo)"
|
||||
|
||||
/datum/map_template/shuttle/mining_common/meta
|
||||
suffix = "meta"
|
||||
name = "lavaland shuttle (Meta)"
|
||||
|
||||
/datum/map_template/shuttle/labour/kilo
|
||||
suffix = "kilo"
|
||||
name = "labour shuttle (Kilo)"
|
||||
// /datum/map_template/shuttle/mining_common/kilo
|
||||
// suffix = "kilo"
|
||||
// name = "lavaland shuttle (Kilo)"
|
||||
|
||||
/datum/map_template/shuttle/arrival/delta
|
||||
suffix = "delta"
|
||||
@@ -608,6 +697,18 @@
|
||||
suffix = "default"
|
||||
name = "pirate ship (Default)"
|
||||
|
||||
/datum/map_template/shuttle/hunter/space_cop
|
||||
suffix = "space_cop"
|
||||
name = "Police Spacevan"
|
||||
|
||||
/datum/map_template/shuttle/hunter/russian
|
||||
suffix = "russian"
|
||||
name = "Russian Cargo Ship"
|
||||
|
||||
/datum/map_template/shuttle/hunter/bounty
|
||||
suffix = "bounty"
|
||||
name = "Bounty Hunter Ship"
|
||||
|
||||
/datum/map_template/shuttle/ruin/caravan_victim
|
||||
suffix = "caravan_victim"
|
||||
name = "Small Freighter"
|
||||
@@ -631,15 +732,3 @@
|
||||
/datum/map_template/shuttle/snowdin/excavation
|
||||
suffix = "excavation"
|
||||
name = "Snowdin Excavation Elevator"
|
||||
|
||||
/datum/map_template/shuttle/hunter/space_cop
|
||||
suffix = "space_cop"
|
||||
name = "Police Spacevan"
|
||||
|
||||
/datum/map_template/shuttle/hunter/russian
|
||||
suffix = "russian"
|
||||
name = "Russian Cargo Ship"
|
||||
|
||||
/datum/map_template/shuttle/hunter/bounty
|
||||
suffix = "bounty"
|
||||
name = "Bounty Hunter Ship"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
switch(event_code)
|
||||
if(TGS_EVENT_REBOOT_MODE_CHANGE)
|
||||
var/list/reboot_mode_lookup = list ("[TGS_REBOOT_MODE_NORMAL]" = "be normal", "[TGS_REBOOT_MODE_SHUTDOWN]" = "shutdown the server", "[TGS_REBOOT_MODE_RESTART]" = "hard restart the server")
|
||||
var old_reboot_mode = args[2]
|
||||
var new_reboot_mode = args[3]
|
||||
var/old_reboot_mode = args[2]
|
||||
var/new_reboot_mode = args[3]
|
||||
message_admins("TGS: Reboot will no longer [reboot_mode_lookup["[old_reboot_mode]"]], it will instead [reboot_mode_lookup["[new_reboot_mode]"]]")
|
||||
if(TGS_EVENT_PORT_SWAP)
|
||||
message_admins("TGS: Changing port from [world.port] to [args[2]]")
|
||||
@@ -28,12 +28,14 @@
|
||||
var/datum/tgs_version/old_version = world.TgsVersion()
|
||||
var/datum/tgs_version/new_version = args[2]
|
||||
if(!old_version.Equals(new_version))
|
||||
to_chat(world, "<span class='boldannounce'>TGS updated to v[old_version.deprefixed_parameter]</span>")
|
||||
to_chat(world, "<span class='boldannounce'>TGS updated to v[new_version.deprefixed_parameter]</span>")
|
||||
else
|
||||
message_admins("TGS: Back online")
|
||||
if(reattach_timer)
|
||||
deltimer(reattach_timer)
|
||||
reattach_timer = null
|
||||
if(TGS_EVENT_WATCHDOG_SHUTDOWN)
|
||||
to_chat_immediate(world, "<span class='boldannounce'>Server is shutting down!</span>")
|
||||
|
||||
/datum/tgs_event_handler/impl/proc/LateOnReattach()
|
||||
message_admins("Warning: TGS hasn't notified us of it coming back for a full minute! Is there a problem?")
|
||||
|
||||
@@ -83,8 +83,6 @@
|
||||
/datum/viewData/proc/apply()
|
||||
chief.change_view(getView())
|
||||
safeApplyFormat()
|
||||
if(chief.prefs.auto_fit_viewport)
|
||||
chief.fit_viewport()
|
||||
|
||||
/datum/viewData/proc/supress()
|
||||
is_suppressed = TRUE
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
if(!is_new_ckey)
|
||||
log_admin("AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).")
|
||||
message_admins("AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).")
|
||||
send2irc("Panic Bunker", "AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).")
|
||||
send2adminchat("Panic Bunker", "AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).")
|
||||
return "Success"
|
||||
|
||||
/datum/world_topic/ahelp_relay
|
||||
@@ -106,8 +106,8 @@
|
||||
|
||||
/datum/world_topic/comms_console/Run(list/input, addr)
|
||||
minor_announce(input["message"], "Incoming message from [input["message_sender"]]")
|
||||
for(var/obj/machinery/computer/communications/CM in GLOB.machines)
|
||||
CM.overrideCooldown()
|
||||
for(var/obj/machinery/computer/communications/console in GLOB.machines)
|
||||
console.override_cooldown()
|
||||
|
||||
/datum/world_topic/news_report
|
||||
keyword = "News_Report"
|
||||
|
||||
Reference in New Issue
Block a user