diff --git a/code/controllers/subsystems/garbage-debug.dm b/code/controllers/subsystems/garbage-debug.dm
index 774c2d54070..7d81e3fb6c3 100644
--- a/code/controllers/subsystems/garbage-debug.dm
+++ b/code/controllers/subsystems/garbage-debug.dm
@@ -871,5 +871,6 @@
SearchVar(mark)
SearchVar(contamination_overlay)
SearchVar(vsc)
+ SearchVar(global_player_panel)
#endif
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index bcabfae87fb..aeb90e4df37 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -1,7 +1,7 @@
//admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless
var/list/admin_verbs_default = list(
/datum/admins/proc/show_player_panel, //shows an interface for individual players, with various links (links require additional flags,
- /client/proc/player_panel,
+ /client/proc/player_panel_modern,
/client/proc/toggleadminhelpsound, /*toggles whether we hear a sound when adminhelps/PMs are used*/
/client/proc/deadmin_self, /*destroys our own admin datum so we can play as a regular player*/
/client/proc/hide_verbs, /*hides all our adminverbs*/
@@ -11,7 +11,6 @@ var/list/admin_verbs_default = list(
)
var/list/admin_verbs_admin = list(
/client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game.*/
- /client/proc/player_panel_new, /*shows an interface for all players, with links to various panels*/
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
// /datum/admins/proc/show_traitor_panel, /*interface which shows a mob's mind*/ -Removed due to rare practical use. Moved to debug verbs ~Errorage */
/datum/admins/proc/show_game_mode, /*Configuration window for the current game mode.*/
@@ -327,7 +326,6 @@ var/list/admin_verbs_mod = list(
/client/proc/admin_ghost, // allows us to ghost/reenter body at will,
/client/proc/cmd_mod_say,
/datum/admins/proc/show_player_info,
- /client/proc/player_panel_new,
/client/proc/dsay,
/datum/admins/proc/show_skills,
/datum/admins/proc/show_player_panel,
@@ -371,7 +369,7 @@ var/list/admin_verbs_dev = list( //will need to be altered - Ryan784
/client/proc/hide_most_verbs,
/client/proc/kill_air,
/client/proc/kill_airgroup,
- /client/proc/player_panel,
+ /client/proc/player_panel_modern,
/client/proc/togglebuildmodeself,
/client/proc/toggledebuglogs,
/client/proc/ZASSettings,
@@ -515,22 +513,16 @@ var/list/admin_verbs_cciaa = list(
to_chat(mob, "Invisimin on. You are now as invisible as a ghost.")
mob.alpha = max(mob.alpha - 100, 0)
-
-/client/proc/player_panel()
+/client/proc/player_panel_modern()
set name = "Player Panel"
set category = "Admin"
if(holder)
- holder.player_panel_old()
- feedback_add_details("admin_verb","PP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ if(!global_player_panel)
+ global_player_panel = new()
+ global_player_panel.ui_interact(usr)
+ feedback_add_details("admin_verb","PPM") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
-/client/proc/player_panel_new()
- set name = "Player Panel New"
- set category = "Admin"
- if(holder)
- holder.player_panel_new()
- feedback_add_details("admin_verb","PPN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
- return
/client/proc/check_antagonists()
set name = "Check Antagonists"
diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm
index 97bb3d693f8..c0e6d3a1a8a 100644
--- a/code/modules/admin/player_panel.dm
+++ b/code/modules/admin/player_panel.dm
@@ -1,393 +1,3 @@
-
-/datum/admins/proc/player_panel_new()//The new one
- if (!usr.client.holder)
- return
- var/dat = "
Admin Player Panel"
-
- //javascript, the part that does most of the work~
- dat += {"
-
-
-
-
-
-
- "}
-
- //body tag start + onload and onkeypress (onkeyup) javascript event calls
- dat += ""
-
- //title + search bar
- dat += {"
-
-
-
- "}
-
- //player table header
- dat += {"
-
- "}
-
- var/list/mobs = sortmobs()
- var/i = 1
- for(var/mob/M in mobs)
- if(M.ckey)
-
- var/color = "#e6e6e6"
- if(i%2 == 0)
- color = "#f2f2f2"
- var/is_antagonist = is_special_character(M)
-
- var/M_job = ""
-
- if(isliving(M))
-
- if(iscarbon(M)) //Carbon stuff
- if(ishuman(M))
- M_job = M.job
- else if(isslime(M))
- M_job = "slime"
- else if(issmall(M))
- M_job = "Monkey"
- else if(isalien(M))
- M_job = "Alien"
- else
- M_job = "Carbon-based"
-
- else if(issilicon(M)) //silicon
- if(isAI(M))
- M_job = "AI"
- else if(ispAI(M))
- M_job = "pAI"
- else if(isrobot(M))
- M_job = "Cyborg"
- else
- M_job = "Silicon-based"
-
- else if(isanimal(M)) //simple animals
- if(iscorgi(M))
- M_job = "Corgi"
- else
- M_job = "Animal"
-
- else
- M_job = "Living"
-
- else if(istype(M,/mob/abstract/new_player))
- M_job = "New player"
-
- else if(isobserver(M))
- M_job = "Ghost"
-
- M_job = replacetext(M_job, "'", "")
- M_job = replacetext(M_job, "\"", "")
- M_job = replacetext(M_job, "\\", "")
-
- var/M_name = M.name
- M_name = replacetext(M_name, "'", "")
- M_name = replacetext(M_name, "\"", "")
- M_name = replacetext(M_name, "\\", "")
- var/M_rname = M.real_name
- M_rname = replacetext(M_rname, "'", "")
- M_rname = replacetext(M_rname, "\"", "")
- M_rname = replacetext(M_rname, "\\", "")
-
- var/M_key = M.key
- M_key = replacetext(M_key, "'", "")
- M_key = replacetext(M_key, "\"", "")
- M_key = replacetext(M_key, "\\", "")
-
- //output for each mob
- dat += {"
-
-
-
-
-
- [M_name] - [M_rname] - [M_key] ([M_job])
-
-
- |
-
-
- "}
-
- i++
-
-
- //player table ending
- dat += {"
-
-
-
-
-
- "}
-
- usr << browse(dat, "window=players;size=600x480")
-
-//The old one
-/datum/admins/proc/player_panel_old()
- if (!usr.client.holder)
- return
-
- var/dat = "Player Menu"
- dat += "| Name | Real Name | Assigned Job | Key | Options | PM | Traitor? |
"
- //add IP: | to this if wanting to add back in IP checking
- //add (IP: [M.lastKnownIP]) | if you want to know their ip to the lists below
- var/list/mobs = sortmobs()
-
- for(var/mob/M in mobs)
- if(!M.ckey) continue
-
- dat += "| [M.name] | "
- if(isAI(M))
- dat += "AI | "
- else if(isrobot(M))
- dat += "Cyborg | "
- else if(ishuman(M))
- dat += "[M.real_name] | "
- else if(istype(M, /mob/living/silicon/pai))
- dat += "pAI | "
- else if(istype(M, /mob/abstract/new_player))
- dat += "New Player | "
- else if(isobserver(M))
- dat += "Ghost | "
- else if(issmall(M))
- dat += "Monkey | "
- else if(isalien(M))
- dat += "Alien | "
- else
- dat += "Unknown | "
-
-
- if(istype(M,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- if(H.mind && H.mind.assigned_role)
- dat += "[H.mind.assigned_role] | "
- else
- dat += "NA | "
-
-
- dat += {"[M.key ? (M.client ? M.key : "[M.key] (DC)") : "No key"] |
- X |
- PM |
- "}
-
-
-
- if(usr.client)
- if(!check_rights(R_MOD|R_ADMIN, 0))
- dat += {" N/A | "}
- else
- switch(is_special_character(M))
- if(0)
- dat += {"Traitor? | "}
- if(1)
- dat += {"Traitor? | "}
- if(2)
- dat += {"Traitor? | "}
- else
- dat += {" N/A | "}
-
-
-
- dat += "
"
-
- usr << browse(dat, "window=players;size=640x480")
-
-
-
/datum/admins/proc/check_antagonists()
if (SSticker.current_state >= GAME_STATE_PLAYING)
var/dat = "Round StatusRound Status
"
@@ -418,3 +28,87 @@
usr << browse(dat, "window=roundstatus;size=400x500")
else
alert("The game hasn't started yet!")
+
+var/datum/vueui_module/player_panel/global_player_panel
+/datum/vueui_module/player_panel
+ var/something = TRUE
+
+/datum/vueui_module/player_panel/ui_interact(var/mob/user)
+ if (!usr.client.holder)
+ return
+ var/datum/vueui/ui = SSvueui.get_open_ui(user, src)
+ if(!ui)
+ ui = new(user, src, "admin-player-panel", 640, 480, "Modern player panel", nstate = interactive_state)
+ ui.header = "minimal"
+ ui.auto_update_content = TRUE
+
+ ui.open()
+
+/datum/vueui_module/player_panel/vueui_data_change(var/list/data, var/mob/user, var/datum/vueui/ui)
+ if(!data)
+ . = data = list()
+ if(!user.client.holder)
+ return
+ var/isMod = check_rights(R_MOD|R_ADMIN, 0, user)
+ VUEUI_SET_CHECK(data["holder_ref"], "\ref[user.client.holder]", ., data)
+ VUEUI_SET_CHECK(data["ismod"], isMod, ., data)
+
+
+ var/list/mobs = sortmobs()
+
+ LAZYINITLIST(data["players"])
+ if(data["players"].len != mobs.len)
+ data["players"].Cut()
+ for(var/mob/M in mobs)
+ var/ref = "\ref[M]"
+ if(!M.ckey)
+ data["players"][ref] = FALSE
+ continue
+ LAZYINITLIST(data["players"][ref])
+ VUEUI_SET_CHECK(data["players"][ref]["ref"], ref, ., data)
+ VUEUI_SET_CHECK(data["players"][ref]["name"], M.name, ., data)
+ var/real_name = GetMobRealName(M)
+ VUEUI_SET_CHECK(data["players"][ref]["real_name"], real_name, ., data)
+ if(istype(M,/mob/living/carbon/human))
+ var/mob/living/carbon/human/H = M
+ if(H.mind?.assigned_role)
+ VUEUI_SET_CHECK(data["players"][ref]["assigment"], H.mind.assigned_role, ., data)
+ else
+ VUEUI_SET_CHECK(data["players"][ref]["assigment"], "NA", ., data)
+ VUEUI_SET_CHECK(data["players"][ref]["key"], M.key, ., data)
+ if(isMod)
+ VUEUI_SET_CHECK(data["players"][ref]["ip"], M.lastKnownIP, ., data)
+ else
+ VUEUI_SET_CHECK(data["players"][ref]["ip"], FALSE, ., data)
+ VUEUI_SET_CHECK(data["players"][ref]["connected"], !!M.client, ., data)
+ if(isMod)
+ var/special_char = is_special_character(M)
+ VUEUI_SET_CHECK(data["players"][ref]["antag"], special_char, ., data)
+ else
+ VUEUI_SET_CHECK(data["players"][ref]["antag"], -1, ., data)
+ if(isMod && M.client?.player_age)
+ var/age = M.client.player_age
+ if(age == "Requires database")
+ age = "NA"
+ VUEUI_SET_CHECK(data["players"][ref]["age"], age, ., data)
+ else
+ VUEUI_SET_CHECK(data["players"][ref]["age"], FALSE, ., data)
+
+/datum/vueui_module/player_panel/proc/GetMobRealName(var/mob/M)
+ if(isAI(M))
+ return "AI"
+ if(isrobot(M))
+ return "Cyborg"
+ if(ishuman(M))
+ return M.real_name
+ if(istype(M, /mob/living/silicon/pai))
+ return "pAI"
+ if(istype(M, /mob/abstract/new_player))
+ return "New Player"
+ if(isobserver(M))
+ return "Ghost"
+ if(issmall(M))
+ return "Monkey"
+ if(isalien(M))
+ return "Alien"
+ return "Unknown"
\ No newline at end of file
diff --git a/html/changelogs/karolis-modern playerpannel.yml b/html/changelogs/karolis-modern playerpannel.yml
new file mode 100644
index 00000000000..33109114dbf
--- /dev/null
+++ b/html/changelogs/karolis-modern playerpannel.yml
@@ -0,0 +1,4 @@
+author: Karolis2011
+delete-after: True
+changes:
+ - rscadd: "Added new player panel to make player management easier."
\ No newline at end of file
diff --git a/interface/skin.dmf b/interface/skin.dmf
index d8d04231449..e27b6bf0b37 100644
--- a/interface/skin.dmf
+++ b/interface/skin.dmf
@@ -187,7 +187,7 @@ macro "borghotkeymode"
command = "asay"
elem
name = "F6"
- command = "Player-Panel-New"
+ command = "Player-Panel"
elem
name = "F7"
command = "Admin-PM"
@@ -357,7 +357,7 @@ macro "macro"
command = "asay"
elem
name = "F6"
- command = "Player-Panel-New"
+ command = "Player-Panel"
elem
name = "F7"
command = "Admin-PM"
@@ -590,7 +590,7 @@ macro "hotkeymode"
command = "asay"
elem
name = "F6"
- command = "Player-Panel-New"
+ command = "Player-Panel"
elem
name = "F7"
command = "Admin-PM"
@@ -760,7 +760,7 @@ macro "borgmacro"
command = "asay"
elem
name = "F6"
- command = "Player-Panel-New"
+ command = "Player-Panel"
elem
name = "F7"
command = "Admin-PM"
diff --git a/vueui/README.md b/vueui/README.md
index 9d308fd4672..57fd04c4283 100644
--- a/vueui/README.md
+++ b/vueui/README.md
@@ -185,10 +185,14 @@ Example:
```
Parameters:
- `$slot` - Contents of button.
- - `params` - key value pairs to send to `Topic` of object.
+ - `params` - key value pairs to send to `Topic` of object. Can contain objects or arrays (DM keyed lists and lists respectively).
+ - `unsafe-params` - Used to execute a generic `Topic()` call to the game. Requires that you specify the `src` object as a valid reference, otherwise it will not function. **Should not generally be used**, primary use-case is backwards compatibility with older APIs that are spread out over multiple objects.
- `icon` - icon that should be used in that button. For available icons look at `\vueui\styles\icons.scss`
- `push-state` - Boolean determining if current ui state should be pushed on button click. This often results in `vueui_data_change` call right before `Topic` call.
+Events:
+ - `click` - Fires when button is clicked.
+
### VuiProgress ``
Simple progress bar for representing progress of a process or indicate status.
@@ -235,6 +239,20 @@ Example:
```
Parameters:
- `label` - Label to display next to contents.
+
+### VuiTooltip ``
+Helper to getting nice tooltips when you hover over text. Works with buttons.
+
+Example:
+```Vue
+VueUi UI element
+ADVAdvanced use of tooltips
+```
+Parameters:
+ - `$slot` - Contents of tooltip
+ - `$slot:label` - Actual content that is always shown. If slot is set, `label` parameter is ignored.
+ - `label` - Actual text that is always shown
+
### VuiInputNumeric ``
Numeric input helper to help inputting large and small numbers.
@@ -250,6 +268,7 @@ Parameters:
- `push-state` - Boolean determining if current ui state should be pushed on input change.
- `width` - Determines width of input text field.
- `decimal-places` - How many decimal places are allowed.
+
Events:
- `input` - Fires when value changes. Value is number currently entered.
@@ -263,5 +282,6 @@ Example:
Parameters:
- `input` - Initial array with elements to search.
- `keys` - Array of strings listing keys to be searched.
+
Events:
- - `input` - Fires when search text changes. Event value is new sorted array.
\ No newline at end of file
+ - `input` - Fires when search text changes. Event value is new sorted array.
diff --git a/vueui/src/assets/global.scss b/vueui/src/assets/global.scss
index 4c98e65ffd1..86899614379 100644
--- a/vueui/src/assets/global.scss
+++ b/vueui/src/assets/global.scss
@@ -93,4 +93,22 @@ input, textarea, button, select, .button {
.csserror {
display: none;
+}
+
+.tooltip {
+ &.label {
+ text-decoration: underline;
+ }
+}
+
+.red {
+ color: red;
+}
+
+.green {
+ color: green;
+}
+
+.blue {
+ color: green;
}
\ No newline at end of file
diff --git a/vueui/src/assets/theme-basic.scss b/vueui/src/assets/theme-basic.scss
index 7d45f5aa8c7..fda8fddc32a 100644
--- a/vueui/src/assets/theme-basic.scss
+++ b/vueui/src/assets/theme-basic.scss
@@ -17,6 +17,13 @@
border-bottom:1px solid #ee0000;
}
}
+
+ .tooltip {
+ &.content {
+ background: #ffffff;
+ border: 1px solid darkgrey;
+ }
+ }
}
.theme-basic-dark {
@@ -38,4 +45,11 @@
.uiTitleWrapper {
background-color: #464646;
}
+
+ .tooltip {
+ &.content {
+ background: #000000;
+ border: 1px solid darkgrey;
+ }
+ }
}
\ No newline at end of file
diff --git a/vueui/src/assets/theme-nano.scss b/vueui/src/assets/theme-nano.scss
index 25ba4190bb8..2f78dc2021d 100644
--- a/vueui/src/assets/theme-nano.scss
+++ b/vueui/src/assets/theme-nano.scss
@@ -186,6 +186,13 @@
vertical-align: top;
margin: 0 2px 2px 0;
}
+
+ .tooltip {
+ &.content {
+ background: #272727;
+ border: 1px solid darkgrey;
+ }
+ }
}
.theme-nano-light {
@@ -275,4 +282,11 @@
}
}
}
+ .tooltip {
+ &.content {
+ color: black;
+ background: #c9c9c9;
+ border: 1px solid darkgrey;
+ }
+ }
}
diff --git a/vueui/src/components/view/admin/player-panel.vue b/vueui/src/components/view/admin/player-panel.vue
new file mode 100644
index 00000000000..26265781b85
--- /dev/null
+++ b/vueui/src/components/view/admin/player-panel.vue
@@ -0,0 +1,88 @@
+
+
+
Check antagonists
+
+
+
+
+
+ {{p.name}}
+ {{p.real_name}}
+
+
+ {{p.real_name}}
+ {{p.assigment}}
+
+
+
+ {{p.key}} (DC)
+
+
+ {{p.key}} (DC)
+ {{p.ip}}
+
+
+
{{p.age}}
+
+ NA
+ No
+ This antag was added by admin.
+ This antag was added by gamemode.
+
+
+ PP
+ N
+ TP
+ PM
+ SM
+ JMP
+ WIND
+
+
+
+
+
+
+
+
+
+
diff --git a/vueui/src/components/vui/button.vue b/vueui/src/components/vui/button.vue
index 0a97aa2203c..9fe5bb8ebb0 100644
--- a/vueui/src/components/vui/button.vue
+++ b/vueui/src/components/vui/button.vue
@@ -18,6 +18,10 @@ export default {
type: Object,
default: null
},
+ unsafeParams: {
+ type: Object,
+ default: null
+ },
pushState: {
type: Boolean,
default: false
@@ -33,6 +37,9 @@ export default {
return
}
this.$emit('click')
+ if(this.unsafeParams) {
+ Utils.sendToTopicRaw(this.unsafeParams)
+ }
if(!this.params) {
if (this.pushState) {
Store.pushState()
diff --git a/vueui/src/components/vui/tooltip.vue b/vueui/src/components/vui/tooltip.vue
new file mode 100644
index 00000000000..1fedab417f9
--- /dev/null
+++ b/vueui/src/components/vui/tooltip.vue
@@ -0,0 +1,33 @@
+
+
+ {{label}}
+
+
+
+
+
+
diff --git a/vueui/src/store.js b/vueui/src/store.js
index af93935abe7..2792f477451 100644
--- a/vueui/src/store.js
+++ b/vueui/src/store.js
@@ -26,7 +26,10 @@ export default {
isUpdating: false,
lastUpdateTime: null,
getStatePushString () {
- return "vueuistateupdate=" + encodeURIComponent(JSON.stringify(this.state))
+ return "vueuistateupdate=" + encodeURIComponent(this.getStatePushDataString())
+ },
+ getStatePushDataString () {
+ return JSON.stringify(this.state)
},
pushState() {
if (this.isUpdating || (Date.now() - this.lastUpdateTime) < 100 ) {
diff --git a/vueui/src/utils.js b/vueui/src/utils.js
index a46fa899736..0a997c57447 100644
--- a/vueui/src/utils.js
+++ b/vueui/src/utils.js
@@ -1,14 +1,26 @@
import Store from './store.js'
+import store from './store.js';
export default {
- sendToTopic(data, pushState = false) {
- var r = new XMLHttpRequest()
- var sendUrl = "?src=" + Store.state.uiref + "&vueuihrefjson=" + encodeURIComponent(JSON.stringify(data))
- if (pushState) {
- sendUrl += "&" + Store.getStatePushString()
+ sendToTopicRaw(data) {
+ var sendparams = []
+ for(var val in data) {
+ sendparams.push(encodeURIComponent(val) + "=" + encodeURIComponent(data[val]))
}
+ var r = new XMLHttpRequest()
+ var sendUrl = "?" + sendparams.join("&")
r.open("GET", sendUrl, true);
r.send()
},
+ sendToTopic(data, pushState = false) {
+ var pushData = {
+ src: Store.state.uiref,
+ vueuihrefjson: JSON.stringify(data)
+ }
+ if(pushState) {
+ pushData["vueuistateupdate"] = store.getStatePushDataString()
+ }
+ this.sendToTopicRaw(pushData)
+ },
dotNotationRead(object, key) {
return key.split('.').reduce((a, b) => a[b], object);
}