mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-12 07:33:34 +01:00
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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) ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user