Nukes karma (#20628)

* Nukes karma

* Skin + logic

* TGUI Build
This commit is contained in:
AffectedArc07
2023-03-14 19:14:47 +00:00
committed by GitHub
parent f33054212b
commit 72ba1ada7b
49 changed files with 73 additions and 922 deletions
-1
View File
@@ -122,7 +122,6 @@ GLOBAL_VAR_INIT(nologevent, 0)
body += "<A href='?_src_=holder;newban=[M.UID()];dbbanaddckey=[M.ckey]'>Ban</A> | "
body += "<A href='?_src_=holder;jobban2=[M.UID()];dbbanaddckey=[M.ckey]'>Jobban</A> | "
body += "<A href='?_src_=holder;shownoteckey=[M.ckey]'>Notes</A> | "
body += "<A href='?_src_=holder;viewkarma=[M.ckey]'>View Karma</A> | "
if(GLOB.configuration.url.forum_playerinfo_url)
body += "<A href='?_src_=holder;webtools=[M.ckey]'>WebInfo</A> | "
if(M.client)
-20
View File
@@ -3350,27 +3350,7 @@
if(!check_rights(R_ADMIN))
return
add_note(href_list["suppresscidwarning"], CIDWARNING_SUPPRESSED_NOTETEXT, show_after = FALSE)
else if(href_list["viewkarma"])
if(!check_rights(R_ADMIN))
return
var/client/C = GLOB.directory[href_list["viewkarma"]]
if(!C)
return
// Pack it into a dat
var/dat = {"
<ul>
<li>Total Karma: [C.karmaholder.karma_earned]</li>
<li>Spent Karma: [C.karmaholder.karma_spent]</li>
<li>Available Karma: [C.karmaholder.karma_earned - C.karmaholder.karma_spent]</li>
<li>Unlocked Packages: [C.karmaholder.purchased_packages.Join(", ")]</li>
</ul>
"}
var/datum/browser/popup = new(usr, "view_karma", "Karma stats for [C.ckey]", 600, 300)
popup.set_content(dat)
popup.open(FALSE)
else if(href_list["who_advanced"])
usr.client.who_advanced()
+2 -6
View File
@@ -21,6 +21,8 @@
var/move_delay = 1
var/moving = null
var/area = null
// why the hell do we track this when you can just file > reconnect to bypass it
var/time_died_as_mouse = null //when the client last died as a mouse
var/typing = FALSE // Prevents typing window stacking
@@ -113,9 +115,6 @@
/// List of the clients CUIs
var/list/datum/custom_user_item/cui_entries = list()
/// The client's karma holder
var/datum/karma_holder/karmaholder
/// The client's job ban holder
var/datum/job_ban_holder/jbh = new()
@@ -136,9 +135,6 @@
if("cui_entries")
return FALSE
// or this
if("karmaholder")
return FALSE
// or this
if("jbh")
return FALSE
return ..()
-10
View File
@@ -392,12 +392,6 @@
// activate_darkmode() calls the CL update button proc, so we dont want it double called
SSchangelog.UpdatePlayerChangelogButton(src)
if(prefs.toggles & PREFTOGGLE_DISABLE_KARMA) // activates if karma is disabled
to_chat(src,"<span class='notice'>You have disabled karma gains.") // reminds those who have it disabled
else
to_chat(src,"<span class='notice'>You have enabled karma gains.")
generate_clickcatcher()
apply_clickcatcher()
@@ -433,10 +427,6 @@
if(_2fa_alert)
to_chat(src,"<span class='boldannounce'><big>You do not have 2FA enabled. Admin verbs will be unavailable until you have enabled 2FA.</big></span>") // Very fucking obvious
// This happens "asyncronously"
if(karmaholder)
karmaholder.processRefunds(mob)
// Tell client about their connection
to_chat(src, "<span class='notice'>You are currently connected [prefs.server_region ? "via the <b>[prefs.server_region]</b> relay" : "directly"] to Paradise.</span>")
to_chat(src, "<span class='notice'>You can change this using the <code>Change Region</code> verb in the OOC tab, as selecting a region closer to you may reduce latency.</span>")
@@ -1,14 +0,0 @@
/datum/client_login_processor/karma_numbers
priority = 42
/datum/client_login_processor/karma_numbers/get_query(client/C)
var/datum/db_query/query = SSdbcore.NewQuery("SELECT karma, karmaspent FROM karma_totals WHERE byondkey=:ckey", list(
"ckey" = C.ckey
))
return query
/datum/client_login_processor/karma_numbers/process_result(datum/db_query/Q, client/C)
C.karmaholder = new()
while(Q.NextRow())
C.karmaholder.karma_earned = Q.item[1]
C.karmaholder.karma_spent = Q.item[2]
@@ -1,12 +0,0 @@
/datum/client_login_processor/karma_unlocks
priority = 43
/datum/client_login_processor/karma_unlocks/get_query(client/C)
var/datum/db_query/query = SSdbcore.NewQuery("SELECT purchase FROM karma_purchases WHERE ckey=:ckey", list(
"ckey" = C.ckey
))
return query
/datum/client_login_processor/karma_unlocks/process_result(datum/db_query/Q, client/C)
while(Q.NextRow())
C.karmaholder.addUnlock(Q.item[1])
@@ -216,10 +216,10 @@
if(new_age)
active_character.age = max(min(round(text2num(new_age)), AGE_MAX),AGE_MIN)
if("species")
var/list/new_species = list("Human", "Tajaran", "Skrell", "Unathi", "Diona", "Vulpkanin", "Nian")
var/list/new_species = list()
var/prev_species = active_character.species
for(var/_species in GLOB.whitelisted_species)
for(var/_species in GLOB.all_species)
if(can_use_species(user, _species))
new_species += _species
@@ -109,15 +109,6 @@
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_DISABLE_SCOREBOARD) ? "no longer" : "now"] see the end of round scoreboard.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Scoreboard") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/togglekarmareminder()
set name = "Hide/Display End Round Karma Reminder"
set category = "Preferences"
set desc = "Toggles displaying end of round karma reminder"
prefs.toggles ^= PREFTOGGLE_DISABLE_KARMA_REMINDER
prefs.save_preferences(src)
to_chat(src, "You will [(prefs.toggles & PREFTOGGLE_DISABLE_KARMA_REMINDER) ? "no longer" : "now"] see the end of round karma reminder.")
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Karma Reminder") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggletitlemusic()
set name = "Hear/Silence LobbyMusic"
set category = "Preferences"
@@ -254,17 +245,6 @@
deactivate_darkmode()
SSblackbox.record_feedback("tally", "toggle_verbs", 1, "Toggle Darkmode") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggle_karma()
set name = "Toggle Karma Gains"
set category = "Special Verbs"
set desc = "This button will allow you to stop other people giving you karma."
prefs.toggles ^= PREFTOGGLE_DISABLE_KARMA
prefs.save_preferences(src)
if(prefs.toggles & PREFTOGGLE_DISABLE_KARMA)
to_chat(usr, "<span class='notice'>You have disabled karma gains.")
else
to_chat(usr, "<span class='notice'>You have enabled karma gains.")
/client/verb/toggle_popup_limiter()
set name = "Toggle Text Popup Limiter"
set category = "Preferences"
-204
View File
@@ -1,204 +0,0 @@
// All karma procs that arent confined to the [/datum/karma_holder] are in here
/proc/sql_report_karma(mob/spender, mob/receiver)
var/receiverrole = "None"
var/receiverspecial = "None"
if(receiver.mind)
if(receiver.mind.special_role)
receiverspecial = receiver.mind.special_role
if(receiver.mind.assigned_role)
receiverrole = receiver.mind.assigned_role
if(!SSdbcore.IsConnected())
return
var/datum/db_query/log_query = SSdbcore.NewQuery({"
INSERT INTO karma_log (spendername, spenderkey, receivername, receiverkey, receiverrole, receiverspecial, spenderip, time, server_id)
VALUES (:sname, :skey, :rname, :rkey, :rrole, :rspecial, :sip, Now(), :server_id)"}, list(
"sname" = spender.name,
"skey" = spender.ckey,
"rname" = receiver.name,
"rkey" = receiver.ckey,
"rrole" = receiverrole,
"rspecial" = receiverspecial,
"sip" = spender.client.address,
"server_id" = GLOB.configuration.system.instance_id
))
if(!log_query.warn_execute())
qdel(log_query)
return
qdel(log_query)
var/datum/db_query/select_recv = SSdbcore.NewQuery("SELECT id, karma FROM karma_totals WHERE byondkey=:rkey", list(
"rkey" = receiver.ckey
))
if(!select_recv.warn_execute())
qdel(select_recv)
return
var/karma
var/id
while(select_recv.NextRow())
id = select_recv.item[1]
karma = text2num(select_recv.item[2])
qdel(select_recv)
// They dont exist, lets make them exist
if(karma == null)
karma = 1
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO karma_totals (byondkey, karma) VALUES (:rkey, :karma)", list(
"rkey" = receiver.ckey,
"karma" = karma
))
if(!insert_query.warn_execute())
qdel(insert_query)
return
qdel(insert_query)
// They do exist. Update it.
else
karma++
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE karma_totals SET karma=:karma WHERE id=:id", list(
"karma" = karma,
"id" = id
))
if(!update_query.warn_execute())
qdel(update_query)
return
qdel(update_query)
receiver?.client.karmaholder.sync_karma(receiver) // Refresh their end
GLOBAL_LIST_EMPTY(karma_spenders)
// Returns TRUE if mob can give karma at all; if not, tells them why
/mob/proc/can_give_karma()
if(!client)
to_chat(src, "<span class='warning'>You can't award karma without being connected.</span>")
return FALSE
if(!GLOB.configuration.general.enable_karma)
to_chat(src, "<span class='warning'>Karma is disabled.</span>")
return FALSE
if(!SSticker || !GLOB.player_list.len || (SSticker.current_state == GAME_STATE_PREGAME))
to_chat(src, "<span class='warning'>You can't award karma until the game has started.</span>")
return FALSE
if(ckey in GLOB.karma_spenders)
to_chat(src, "<span class='warning'>You've already spent your karma for the round.</span>")
return FALSE
return TRUE
// Returns TRUE if mob can give karma to M; if not, tells them why
/mob/proc/can_give_karma_to_mob(mob/M)
if(!can_give_karma())
return FALSE
if(!istype(M))
to_chat(src, "<span class='warning'>That's not a mob.</span>")
return FALSE
if(!M.client)
to_chat(src, "<span class='warning'>That mob has no client connected at the moment.</span>")
return FALSE
if(M.ckey == ckey)
to_chat(src, "<span class='warning'>You can't spend karma on yourself!</span>")
return FALSE
if(client.address == M.client.address)
message_admins("<span class='warning'>Illegal karma spending attempt detected from [key] to [M.key]. Using the same IP!</span>")
log_game("Illegal karma spending attempt detected from [key] to [M.key]. Using the same IP!")
to_chat(src, "<span class='warning'>You can't spend karma on someone connected from the same IP.</span>")
return FALSE
if(M.get_preference(PREFTOGGLE_DISABLE_KARMA))
to_chat(src, "<span class='warning'>That player has turned off incoming karma.")
return FALSE
return TRUE
/mob/verb/spend_karma_list()
set name = "Award Karma"
set desc = "Let the gods know whether someone's been nice. Can only be used once per round."
set category = "Special Verbs"
if(!can_give_karma())
return
var/list/karma_list = list()
for(var/mob/M in GLOB.player_list)
if(!(M.client && M.mind))
continue
if(M == src)
continue
if(M.get_preference(PREFTOGGLE_DISABLE_KARMA))
continue
if(!isobserver(src) && isNonCrewAntag(M))
continue // Don't include special roles for non-observers, because players use it to meta
karma_list += M
if(!length(karma_list))
to_chat(usr, "<span class='warning'>There's no-one to spend your karma on.</span>")
return
var/pickedmob = input("Who would you like to award Karma to?", "Award Karma", "Cancel") as null|mob in karma_list
if(isnull(pickedmob))
return
spend_karma(pickedmob)
/mob/verb/spend_karma(mob/M)
set name = "Award Karma to Player"
set desc = "Let the gods know whether someone's been nice. Can only be used once per round."
set category = "Special Verbs"
if(!M)
to_chat(usr, "Please right click a mob to award karma directly, or use the 'Award Karma' verb to select a player from the player listing.")
return
if(!GLOB.configuration.general.enable_karma) // this is here because someone thought it was a good idea to add an alert box before checking if they can even give a mob karma
to_chat(usr, "<span class='warning'>Karma is disabled.</span>")
return
if(alert("Give [M.name] good karma?", "Karma", "Yes", "No") != "Yes")
return
if(!can_give_karma_to_mob(M))
return // Check again, just in case things changed while the alert box was up
to_chat(usr, "Good karma spent on [M.name].")
GLOB.karma_spenders += ckey
var/special_role = "None"
var/assigned_role = "None"
if(M.mind)
if(M.mind.special_role)
special_role = M.mind.special_role
if(M.mind.assigned_role)
assigned_role = M.mind.assigned_role
log_karma("Karma awarded to [M.name] ([M.key]) (Role: [assigned_role] | Special: [special_role]) - Awarded by [ckey]")
sql_report_karma(src, M) // This proc doesnt just report the purchase. It actually updates their balances.
/client/verb/check_karma()
set name = "Check Karma"
set desc = "Reports how much karma you have accrued."
set category = "Special Verbs"
if(!GLOB.configuration.general.enable_karma)
to_chat(src, "<span class='warning'>Karma is disabled.</span>")
return
var/available_karma = karmaholder.karma_earned - karmaholder.karma_spent
to_chat(usr, "You have ["<b>[available_karma]</b>" || "a database error. Contact the host if they are"] available.")
/client/verb/karmashop()
set name = "karmashop"
set desc = "Spend your karma here"
set hidden = TRUE
if(!GLOB.configuration.general.enable_karma)
to_chat(src, "<span class='warning'>Karma is disabled.</span>")
return
karmaholder.ui_interact(usr)
-226
View File
@@ -1,226 +0,0 @@
// This file contains stuff regarding the karma holder datum
// This is attached to a client and holds their info
/datum/karma_holder
/// List of karma packages this user has purchased
var/list/purchased_packages = list()
/// List of packages where a refund is due
var/list/refundable_packages = list()
/// Amount of karma earned total
var/karma_earned = 0
/// Amount of karma spent total
var/karma_spent = 0
// Safety stuff
/datum/karma_holder/vv_edit_var(var_name, var_value)
return FALSE // no
/datum/karma_holder/CanProcCall(procname)
return FALSE // no
/datum/karma_holder/proc/addUnlock(package)
if(!(package in GLOB.karma_packages))
stack_trace("Someone removed a karma package [package] from the game entirely. This should never happen. Please beat the person who did this.")
return
purchased_packages += package
var/datum/karma_package/KP = GLOB.karma_packages[package]
if(KP.refundable)
refundable_packages += package // Put it in the pool of stuff to be refunded
/datum/karma_holder/proc/hasPackage(package)
return (package in purchased_packages)
/datum/karma_holder/proc/processRefunds(mob/user)
set waitfor = FALSE
if(!length(refundable_packages))
return
for(var/package_id in refundable_packages)
var/datum/karma_package/KP = GLOB.karma_packages[package_id]
make_refund(KP, user)
to_chat(user, "<span class='notice'>You had the Karma package <b>[KP.friendly_name]</b>, which is no longer a store item. You have been automatically refunded <b>[KP.karma_cost]</b> karma.")
// Reloads the values from the DB to ensure they havnt been gamed
/datum/karma_holder/proc/sync_karma(mob/M = usr)
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT karma, karmaspent FROM karma_totals WHERE byondkey=:ckey", list(
"ckey" = M.ckey
))
if(!select_query.warn_execute())
qdel(select_query)
return
while(select_query.NextRow())
karma_earned = select_query.item[1]
karma_spent = select_query.item[2]
qdel(select_query)
/datum/karma_holder/proc/make_purchase(datum/karma_package/package)
sync_karma() // Ensure its up to date
// INITIAL CHECKS
var/karma_available = karma_earned - karma_spent
if(karma_available < package.karma_cost)
to_chat(usr, "You do not have enough karma!")
return
if(alert("Are you sure you want to unlock [package.friendly_name]?", "Confirmation", "No", "Yes") != "Yes")
return
if(karma_available < package.karma_cost) // This is repeated for a reason. Someone could queue up 10 windows to buy things.
to_chat(usr, "You do not have enough karma!")
return
var/datum/db_query/select_query = SSdbcore.NewQuery("SELECT ckey FROM karma_purchases WHERE purchase=:package_id AND ckey=:ckey", list(
"package_id" = package.database_id,
"ckey" = usr.ckey
))
if(!select_query.warn_execute())
qdel(select_query)
return
if(select_query.NextRow())
to_chat(usr, "<span class='notice'>You have already purchased [package.friendly_name]. If you believe this is an error, please contact the server host.</span>")
qdel(select_query)
return
qdel(select_query)
// Update for this round
purchased_packages += package.database_id
// Make the insert
var/datum/db_query/insert_query = SSdbcore.NewQuery("INSERT INTO karma_purchases (ckey, purchase) VALUES (:ckey, :purchase)", list(
"ckey" = usr.ckey,
"purchase" = package.database_id
))
if(!insert_query.warn_execute())
to_chat(usr, "<span class='warning'>Failed to purchase [package.friendly_name]. Please contact the server host.</span>")
qdel(insert_query)
return
// Tell them
to_chat(usr, "<span class='notice'>You have purchased [package.friendly_name]</span>.")
log_karma("[key_name(usr)] has purchased [package.friendly_name].")
qdel(insert_query)
// Charge them
karma_spent += package.karma_cost
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE karma_totals SET karmaspent=:spent WHERE byondkey=:ckey", list(
"spent" = karma_spent,
"ckey" = usr.ckey
))
if(!update_query.warn_execute())
qdel(update_query)
message_admins("[key_name_admin(usr)] just bought something with karma but didnt get a balance deduction. Inform the host please.")
return
// Inform them
to_chat(usr, "You have been charged [package.karma_cost] karma.")
qdel(update_query)
// This is automatically invoked when a user logs in.
/datum/karma_holder/proc/make_refund(datum/karma_package/package, mob/user)
sync_karma(user) // Ensure its up to date
if(!(package.database_id in purchased_packages))
to_chat(user, "You do not own [package.friendly_name]!")
message_admins("[key_name_admin(user)] attempted to refund a karma package they do not have. Potential href exploit.")
return
// Do the delete
var/datum/db_query/insert_query = SSdbcore.NewQuery("DELETE FROM karma_purchases WHERE ckey=:ckey AND purchase=:purchase", list(
"ckey" = user.ckey,
"purchase" = package.database_id
))
if(!insert_query.warn_execute())
to_chat(user, "<span class='warning'>Failed to refund [package.friendly_name]. Please contact the server host.</span>")
qdel(insert_query)
return
qdel(insert_query)
// Update for this round
purchased_packages -= package.database_id
// Refund them
karma_spent -= package.karma_cost
var/datum/db_query/update_query = SSdbcore.NewQuery("UPDATE karma_totals SET karmaspent=:spent WHERE byondkey=:ckey", list(
"spent" = karma_spent,
"ckey" = user.ckey
))
if(!update_query.warn_execute())
qdel(update_query)
message_admins("[key_name_admin(user)] just tried to refund a karma purchase but didnt get a balance deduction. Inform the host please.")
return
qdel(update_query)
/datum/karma_holder/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "KarmaShop", "Karma Shop", 400, 700, master_ui, state)
ui.open()
// Packages they have + Balance
/datum/karma_holder/ui_data(mob/user)
var/list/data = list()
data["purchased_packages"] = purchased_packages.Copy() // Do I need to copy here? Probably
data["karma_balance"] = (karma_earned - karma_spent)
return data
// All the packages
/datum/karma_holder/ui_static_data(mob/user)
var/list/data = list()
var/list/packages = list()
for(var/kp_id in GLOB.karma_packages)
var/datum/karma_package/KP = GLOB.karma_packages[kp_id]
if(KP.refundable)
continue
var/list/package_data = list()
package_data["id"] = KP.database_id
package_data["name"] = KP.friendly_name
package_data["cat"] = KP.category
package_data["cost"] = KP.karma_cost
// Remember, TGUI lists need to be 2 layers deep because BYOND JSON memes
packages += list(package_data)
data["all_packages"] = packages
return data
// UI callback
/datum/karma_holder/ui_act(action, list/params)
if(..())
return
switch(action)
if("makepurchase")
var/purchase_id = params["id"]
if(!(purchase_id in GLOB.karma_packages))
to_chat(usr, "<span class='warning'>That isnt a purchaseable package. What the heck? Please make an issue report.</span>")
return FALSE
var/datum/karma_package/kp = GLOB.karma_packages[purchase_id]
if(kp.refundable)
to_chat(usr, "<span class='warning'>That isnt a purchaseable package. What the heck? Please make an issue report.</span>")
return FALSE
make_purchase(kp)
return TRUE
-109
View File
@@ -1,109 +0,0 @@
// This entire file makes me with DM had enums
/// Base datum for karma packages
/datum/karma_package
/// DB ID. MUST BE UNIQUE. It should follow CATEGORY_ProductName casing. Should be a respective define in [code/__DEFINES/karma.dm]
var/database_id = "ERROR_Unset"
/// Friendly name to show to the user
var/friendly_name = "Some coder was lazy"
/// Cost of karma
var/karma_cost = 0
/// Is this package refundable?
var/refundable = FALSE
/// Category to show in under the karma store
var/category = "UNSET"
/// List of "Meta" packages that arent entries, just organisers
var/list/meta_packages = list(/datum/karma_package/job, /datum/karma_package/species)
/datum/karma_package/vv_edit_var(var_name, var_value)
return FALSE // fuck off
// If you are ever removing something from the karma store, **DO NOT** delete its definition datum.
// Just set redunable = TRUE on it so people can get their karma refund
// Jobs - These no longer exist in the codebase
/datum/karma_package/job
category = "Karma Jobs"
/datum/karma_package/job/blueshield
database_id = KARMAPACKAGE_JOB_BLUESHIELD
friendly_name = "Blueshield"
karma_cost = 30
refundable = TRUE
/datum/karma_package/job/barber
database_id = KARMAPACKAGE_JOB_BARBER
friendly_name = "Barber"
karma_cost = 5
refundable = TRUE
/datum/karma_package/job/brigphys
database_id = KARMAPACKAGE_JOB_BRIGPHYSICIAN
friendly_name = "Brig Physician"
karma_cost = 5
refundable = TRUE
/datum/karma_package/job/ntrep
database_id = KARMAPACKAGE_JOB_NANOTRASENREPRESENTATIVE
friendly_name = "Nanotrasen Representative"
karma_cost = 30
refundable = TRUE
/datum/karma_package/job/secpodpilot
database_id = KARMAPACKAGE_JOB_SECURITYPODPILOT
friendly_name = "Security Pod Pilot"
karma_cost = 30
refundable = TRUE
/datum/karma_package/job/mechanic
database_id = KARMAPACKAGE_JOB_MECHANIC
friendly_name = "Mechanic"
karma_cost = 30
refundable = TRUE
/datum/karma_package/job/magistrate
database_id = KARMAPACKAGE_JOB_MAGISTRATE
friendly_name = "Magistrate"
karma_cost = 45
refundable = TRUE
// Species
/datum/karma_package/species
category = "Karma Species"
/datum/karma_package/species/grey
database_id = KARMAPACKAGE_SPECIES_GREY
friendly_name = "Grey"
karma_cost = 30
/datum/karma_package/species/kidan
database_id = KARMAPACKAGE_SPECIES_KIDAN
friendly_name = "Kidan"
karma_cost = 30
/datum/karma_package/species/slimepeople
database_id = KARMAPACKAGE_SPECIES_SLIMEPEOPLE
friendly_name = "Slime People"
karma_cost = 45
/datum/karma_package/species/vox
database_id = KARMAPACKAGE_SPECIES_VOX
friendly_name = "Vox" // pox
karma_cost = 45
/datum/karma_package/species/drask
database_id = KARMAPACKAGE_SPECIES_DRASK
friendly_name = "Drask"
karma_cost = 30
/datum/karma_package/species/machine
database_id = KARMAPACKAGE_SPECIES_MACHINE
friendly_name = "Machine People (IPC)"
karma_cost = 15
/datum/karma_package/species/plasmaman
database_id = KARMAPACKAGE_SPECIES_PLASMAMAN
friendly_name = "Plasmaman"
karma_cost = 45
@@ -347,14 +347,12 @@
/mob/living/carbon/human/proc/generate_valid_species(check_whitelist = TRUE, list/whitelist = list(), list/blacklist = list())
var/list/valid_species = new()
for(var/current_species_name in GLOB.all_species)
var/datum/species/current_species = GLOB.all_species[current_species_name]
if(check_whitelist && !check_rights(R_ADMIN, FALSE, src)) //If we're using the whitelist, make sure to check it!
if(whitelist.len && !(current_species_name in whitelist))
continue
if(blacklist.len && (current_species_name in blacklist))
continue
if((IS_WHITELISTED in current_species.species_traits) && !can_use_species(src, current_species_name))
if(!can_use_species(src, current_species_name))
continue
valid_species += current_species_name
@@ -13,7 +13,7 @@
"eyes" = /obj/item/organ/internal/eyes/abductor //3 darksight.
)
species_traits = list(NO_BLOOD, NO_HAIR)
species_traits = list(NO_BLOOD, NO_HAIR, NOT_SELECTABLE)
inherent_traits = list(TRAIT_VIRUSIMMUNE, TRAIT_CHUNKYFINGERS, TRAIT_NOHUNGER, TRAIT_NOBREATH, TRAIT_NOEXAMINE, TRAIT_REPEATSURGERY)
dies_at_threshold = TRUE
@@ -31,7 +31,7 @@
"is sucking in warm air!",
"is holding their breath!")
species_traits = list(LIPS, IS_WHITELISTED, NO_HAIR)
species_traits = list(LIPS, NO_HAIR)
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT
bodyflags = HAS_SKIN_TONE | HAS_BODY_MARKINGS | BALD | SHAVED
has_gender = FALSE
@@ -4,7 +4,7 @@
icobase = 'icons/mob/human_races/r_golem.dmi'
species_traits = list(NO_BLOOD, NO_HAIR)
species_traits = list(NO_BLOOD, NO_HAIR, NOT_SELECTABLE)
inherent_traits = list(TRAIT_RESISTHEAT, TRAIT_NOBREATH, TRAIT_RESISTCOLD, TRAIT_RESISTHIGHPRESSURE, TRAIT_RESISTLOWPRESSURE, TRAIT_NOFIRE, TRAIT_CHUNKYFINGERS, TRAIT_RADIMMUNE, TRAIT_PIERCEIMMUNE, TRAIT_NOPAIN, TRAIT_NO_BONES, TRAIT_STURDY_LIMBS, TRAIT_XENO_IMMUNE)
inherent_biotypes = MOB_HUMANOID | MOB_MINERAL
dies_at_threshold = TRUE
@@ -16,7 +16,7 @@
"eyes" = /obj/item/organ/internal/eyes/grey //5 darksight.
)
species_traits = list(LIPS, IS_WHITELISTED, CAN_WINGDINGS, NO_HAIR)
species_traits = list(LIPS, CAN_WINGDINGS, NO_HAIR)
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
bodyflags = HAS_BODY_MARKINGS | HAS_BODYACC_COLOR | SHAVED | BALD
dietflags = DIET_HERB
@@ -9,7 +9,7 @@
hunger_drain = 0.15
tox_mod = 1.7
species_traits = list(IS_WHITELISTED, NO_HAIR)
species_traits = list(NO_HAIR)
inherent_biotypes = MOB_ORGANIC | MOB_HUMANOID | MOB_BUG
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
bodyflags = HAS_HEAD_ACCESSORY | HAS_HEAD_MARKINGS | HAS_BODY_MARKINGS | HAS_BODYACC_COLOR | SHAVED
@@ -22,7 +22,7 @@
death_message = "gives a short series of shrill beeps, their chassis shuddering before falling limp, nonfunctional."
death_sounds = list('sound/voice/borg_deathsound.ogg') //I've made this a list in the event we add more sounds for dead robots.
species_traits = list(IS_WHITELISTED, NO_BLOOD, NO_CLONESCAN, NO_INTORGANS)
species_traits = list(NO_BLOOD, NO_CLONESCAN, NO_INTORGANS)
inherent_traits = list(TRAIT_VIRUSIMMUNE, TRAIT_NOBREATH, TRAIT_NOGERMS, TRAIT_NODECAY, TRAIT_NOPAIN, TRAIT_GENELESS) //Computers that don't decay? What a lie!
inherent_biotypes = MOB_ROBOTIC | MOB_HUMANOID
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
@@ -10,6 +10,7 @@
language = null
default_language = "Chimpanzee"
inherent_traits = list(TRAIT_NOEXAMINE)
species_traits = list(NOT_SELECTABLE)
skinned_type = /obj/item/stack/sheet/animalhide/monkey
greater_form = /datum/species/human
no_equip = list(slot_belt, slot_wear_id, slot_l_ear, slot_r_ear, slot_glasses, slot_gloves, slot_shoes, slot_wear_suit, slot_w_uniform, slot_l_store, slot_r_store, slot_s_store, slot_wear_pda)
@@ -13,7 +13,7 @@
language = "Sol Common"
burn_mod = 4 // holy shite, poor guys wont survive half a second cooking smores
brute_mod = 2 // damn, double wham, double dam
species_traits = list(LIPS, IS_WHITELISTED, NO_BLOOD, NO_CLONESCAN)
species_traits = list(LIPS, NO_BLOOD, NO_CLONESCAN)
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RADIMMUNE, TRAIT_NOPAIN)
bodyflags = SHAVED
dies_at_threshold = TRUE
@@ -5,7 +5,7 @@
dangerous_existence = TRUE //So so much
//language = "Clatter"
species_traits = list(IS_WHITELISTED, NO_BLOOD, NO_HAIR)
species_traits = list(NO_BLOOD, NO_HAIR)
inherent_traits = list(TRAIT_RADIMMUNE, TRAIT_NOHUNGER)
inherent_biotypes = MOB_HUMANOID | MOB_MINERAL
forced_heartattack = TRUE // Plasmamen have no blood, but they should still get heart-attacks
@@ -15,7 +15,7 @@
"eyes" = /obj/item/organ/internal/eyes/night_vision/nightmare //8 darksight.
)
species_traits = list(NO_BLOOD)
species_traits = list(NO_BLOOD, NOT_SELECTABLE)
inherent_traits = list(TRAIT_VIRUSIMMUNE, TRAIT_NOBREATH, TRAIT_RADIMMUNE)
dies_at_threshold = TRUE
@@ -9,7 +9,7 @@
blood_color = "#FFFFFF"
flesh_color = "#E6E6C6"
species_traits = list(NO_BLOOD, NO_HAIR)
species_traits = list(NO_BLOOD, NO_HAIR, NOT_SELECTABLE)
inherent_traits = list(TRAIT_RESISTHEAT, TRAIT_NOBREATH, TRAIT_RESISTCOLD, TRAIT_RESISTHIGHPRESSURE, TRAIT_RESISTLOWPRESSURE, TRAIT_RADIMMUNE, TRAIT_PIERCEIMMUNE, TRAIT_NOHUNGER, TRAIT_XENO_IMMUNE)
inherent_biotypes = MOB_UNDEAD | MOB_HUMANOID
tox_mod = 0
@@ -25,7 +25,7 @@
male_cough_sounds = list('sound/effects/slime_squish.ogg')
female_cough_sounds = list('sound/effects/slime_squish.ogg')
species_traits = list(LIPS, IS_WHITELISTED, NO_CLONESCAN, EXOTIC_COLOR)
species_traits = list(LIPS, NO_CLONESCAN, EXOTIC_COLOR)
inherent_traits = list(TRAIT_WATERBREATH, TRAIT_NO_BONES)
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
bodyflags = HAS_SKIN_COLOR | NO_EYES
@@ -114,6 +114,7 @@
default_language = "Sinta'unathi"
speed_mod = -0.80
species_traits = list(LIPS, NOT_SELECTABLE)
inherent_traits = list(TRAIT_CHUNKYFINGERS)
has_organ = list( // same as unathi's organs, aside for the lungs as they need to be able to breathe on lavaland.
@@ -20,7 +20,7 @@
eyes = "vox_eyes_s"
species_traits = list(NO_CLONESCAN, IS_WHITELISTED)
species_traits = list(NO_CLONESCAN)
inherent_traits = list(TRAIT_NOGERMS, TRAIT_NODECAY)
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS //Species-fitted 'em all.
dietflags = DIET_OMNI
@@ -144,7 +144,7 @@
eyes = "blank_eyes"
species_traits = list(NO_CLONESCAN, NO_BLOOD, IS_WHITELISTED)
species_traits = list(NO_CLONESCAN, NO_BLOOD)
inherent_traits = list(TRAIT_RESISTHEAT, TRAIT_RESISTCOLD, TRAIT_RESISTHIGHPRESSURE, TRAIT_RESISTLOWPRESSURE, TRAIT_NOFIRE, TRAIT_NOPAIN, TRAIT_NOGERMS, TRAIT_NODECAY)
clothing_flags = 0 //IDK if you've ever seen underwear on an Armalis, but it ain't pretty.
bodyflags = HAS_TAIL
+9 -11
View File
@@ -225,11 +225,9 @@
if(!SSticker || SSticker.current_state != GAME_STATE_PLAYING)
to_chat(usr, "<span class='warning'>The round is either not ready, or has already finished...</span>")
return
if(client.prefs.active_character.species in GLOB.whitelisted_species)
if(!can_use_species(src, client.prefs.active_character.species))
to_chat(src, alert("You are currently not whitelisted to play [client.prefs.active_character.species]."))
return FALSE
if(!can_use_species(src, client.prefs.active_character.species))
to_chat(src, alert("You are currently not whitelisted to play [client.prefs.active_character.species]."))
return FALSE
LateChoices()
@@ -245,10 +243,9 @@
if(client.prefs.toggles2 & PREFTOGGLE_2_RANDOMSLOT)
client.prefs.load_random_character_slot(client)
if(client.prefs.active_character.species in GLOB.whitelisted_species)
if(!can_use_species(src, client.prefs.active_character.species))
to_chat(src, alert("You are currently not whitelisted to play [client.prefs.active_character.species]."))
return FALSE
if(!can_use_species(src, client.prefs.active_character.species))
to_chat(src, alert("You are currently not whitelisted to play [client.prefs.active_character.species]."))
return FALSE
AttemptLateSpawn(href_list["SelectedJob"])
return
@@ -601,8 +598,9 @@
return check_rights(R_ADMIN, 0, src)
/mob/new_player/proc/is_species_whitelisted(datum/species/S)
if(!S) return 1
return can_use_species(src, S.name) || !(IS_WHITELISTED in S.species_traits)
if(!S)
return TRUE // Allow null species?
return can_use_species(src, S.name)
/mob/new_player/get_gender()
if(!client || !client.prefs) ..()
-3
View File
@@ -410,9 +410,6 @@
"The Emergency Shuttle has left the station. Estimate [timeLeft(600)] minutes until the shuttle docks at Central Command.",
new_title = "Priority Announcement"
)
for(var/mob/M in GLOB.player_list)
if(!isnewplayer(M) && !(M.client.ckey in GLOB.karma_spenders) && !M.get_preference(PREFTOGGLE_DISABLE_KARMA_REMINDER))
to_chat(M, "<i>You have not yet spent your karma for the round; was there a player worthy of receiving your reward? Look under Special Verbs tab, Award Karma.</i>")
if(SHUTTLE_ESCAPE)
if(time_left <= 0)