diff --git a/SQL/paradise_schema.sql b/SQL/paradise_schema.sql
index 1069dd6b2d6..9bfc6fa90b0 100644
--- a/SQL/paradise_schema.sql
+++ b/SQL/paradise_schema.sql
@@ -140,6 +140,25 @@ CREATE TABLE `death` (
) ENGINE=MyISAM AUTO_INCREMENT=166546 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
+--
+-- Table structure for table `donators`
+--
+
+DROP TABLE IF EXISTS `donators`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `donators` (
+ `patreon_name` varchar(32) NOT NULL,
+ `tier` int(2),
+ `ckey` varchar(32) COMMENT 'Manual Field',
+ `start_date` datetime,
+ `end_date` datetime,
+ `active` boolean,
+ PRIMARY KEY (`patreon_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+
--
-- Table structure for table `admin`
--
diff --git a/SQL/paradise_schema_prefixed.sql b/SQL/paradise_schema_prefixed.sql
index 55e71aa2aab..c0cc8c86d6b 100644
--- a/SQL/paradise_schema_prefixed.sql
+++ b/SQL/paradise_schema_prefixed.sql
@@ -140,6 +140,24 @@ CREATE TABLE `SS13_death` (
) ENGINE=MyISAM AUTO_INCREMENT=166546 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
+--
+-- Table structure for table `donators`
+--
+
+DROP TABLE IF EXISTS `SS13_donators`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `donators` (
+ `patreon_name` varchar(32) NOT NULL,
+ `tier` int(2),
+ `ckey` varchar(32) COMMENT 'Manual Field',
+ `start_date` datetime,
+ `end_date` datetime,
+ `active` boolean,
+ PRIMARY KEY (`patreon_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
--
-- Table structure for table `SS13_admin`
--
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index dad6165400f..738549e8b1b 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -287,3 +287,9 @@
#define SHELTER_DEPLOY_BAD_TURFS "bad turfs"
#define SHELTER_DEPLOY_BAD_AREA "bad area"
#define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects"
+
+
+// Client donator levels
+#define DONATOR_LEVEL_NONE 0
+#define DONATOR_LEVEL_ONE 1
+#define DONATOR_LEVEL_TWO 2
\ No newline at end of file
diff --git a/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm
index 703b3e6b205..d39cc600221 100644
--- a/code/__DEFINES/preferences.dm
+++ b/code/__DEFINES/preferences.dm
@@ -24,5 +24,6 @@
#define DISABLE_KARMA_REMINDER 4096
#define MEMBER_PUBLIC 8192
#define CHAT_NO_ADMINLOGS 16384
+#define DONATOR_PUBLIC 32768
-#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC|MEMBER_PUBLIC)
+#define TOGGLES_DEFAULT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC|MEMBER_PUBLIC|DONATOR_PUBLIC)
diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm
index 2c896f3dbdf..ff517be2c1d 100644
--- a/code/game/verbs/ooc.dm
+++ b/code/game/verbs/ooc.dm
@@ -61,16 +61,24 @@ var/global/admin_ooc_colour = "#b82e00"
for(var/client/C in clients)
if(C.prefs.toggles & CHAT_OOC)
var/display_name = src.key
+
if(prefs.unlock_content)
if(prefs.toggles & MEMBER_PUBLIC)
var/icon/byond = icon('icons/member_content.dmi', "blag")
display_name = "[bicon(byond)][display_name]"
+
+ if(donator_level >= DONATOR_LEVEL_ONE)
+ if((prefs.toggles & DONATOR_PUBLIC))
+ var/icon/donator = icon('icons/ooc_tag_16x.dmi', "donator")
+ display_name = "[bicon(donator)][display_name]"
+
if(holder)
if(holder.fakekey)
if(C.holder)
display_name = "[holder.fakekey]/([src.key])"
else
display_name = holder.fakekey
+
to_chat(C, "OOC: [display_name]: ")
/proc/toggle_ooc()
diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm
index c1cbd07daee..d29197f3a1e 100644
--- a/code/modules/client/client defines.dm
+++ b/code/modules/client/client defines.dm
@@ -88,4 +88,7 @@
// Their chat window, sort of important.
// See /goon/code/datums/browserOutput.dm
- var/datum/chatOutput/chatOutput
\ No newline at end of file
+ var/datum/chatOutput/chatOutput
+
+ // Donator stuff.
+ var/donator_level = DONATOR_LEVEL_NONE
\ No newline at end of file
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index 7a668e375fc..aeec5f74bf7 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -299,6 +299,8 @@
admins += src
holder.owner = src
+ donator_check()
+
//preferences datum - also holds some persistant data for the client (because we may as well keep these datums to a minimum)
prefs = preferences_datums[ckey]
if(!prefs)
@@ -372,10 +374,29 @@
return ..()
+/client/proc/donator_check()
+ if(IsGuestKey(key))
+ return
+
+ establish_db_connection()
+ if(!dbcon.IsConnected())
+ return
+
+ //Donator stuff.
+ var/DBQuery/query_donor_select = dbcon.NewQuery("SELECT ckey, tier, active FROM `[format_table_name("donators")]` WHERE ckey = '[ckey]'")
+ query_donor_select.Execute()
+ while(query_donor_select.NextRow())
+ log_to_dd("Donor Query Result: [json_encode(query_donor_select.item)]")
+ if(!text2num(query_donor_select.item[3]))
+ log_to_dd("Donor inactive, removing benefits.")
+ // Inactive donator.
+ donator_level = DONATOR_LEVEL_NONE
+ return
+ donator_level = text2num(query_donor_select.item[2])
+ break
/client/proc/log_client_to_db()
-
- if( IsGuestKey(src.key) )
+ if(IsGuestKey(key))
return
establish_db_connection()
diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm
index 72ec8f101d2..62b02b51b34 100644
--- a/code/modules/client/preference/preferences.dm
+++ b/code/modules/client/preference/preferences.dm
@@ -61,7 +61,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
#define MAX_SAVE_SLOTS 20 // Save slots for regular players
#define MAX_SAVE_SLOTS_MEMBER 20 // Save slots for BYOND members
-#define MAX_GEAR_COST config.max_loadout_points
#define TAB_CHAR 0
#define TAB_GAME 1
@@ -73,6 +72,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used
// var/savefile_version = 0
var/max_save_slots = MAX_SAVE_SLOTS
+ var/max_gear_slots = 0
//non-preference stuff
var/warns = 0
@@ -212,11 +212,18 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
/datum/preferences/New(client/C)
b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
+
if(istype(C))
if(!IsGuestKey(C.key))
unlock_content = C.IsByondMember()
if(unlock_content)
max_save_slots = MAX_SAVE_SLOTS_MEMBER
+
+ max_gear_slots = config.max_loadout_points
+ if(C.donator_level >= DONATOR_LEVEL_ONE)
+ max_gear_slots += 5
+ log_to_dd("Added 5 gear slots to [C.ckey], now [max_gear_slots]")
+
var/loaded_preferences_successfully = load_preferences(C)
if(loaded_preferences_successfully)
if(load_character(C))
@@ -428,6 +435,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
dat += "OOC notes: Edit
"
if(unlock_content)
dat += "BYOND Membership Publicity: [(toggles & MEMBER_PUBLIC) ? "Public" : "Hidden"]
"
+ if(user.client.donator_level >= DONATOR_LEVEL_ONE)
+ dat += "Donator Publicity: [(toggles & DONATOR_PUBLIC) ? "Public" : "Hidden"]
"
dat += "Randomized character slot: [randomslot ? "Yes" : "No"]
"
dat += "Ghost ears: [(toggles & CHAT_GHOSTEARS) ? "Nearest Creatures" : "All Speech"]
"
@@ -464,10 +473,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
total_cost += G.cost
var/fcolor = "#3366CC"
- if(total_cost < MAX_GEAR_COST)
+ if(total_cost < max_gear_slots)
fcolor = "#E67300"
dat += "