[MIRROR] Mafia can be played on your PDA [MDB IGNORE] (#24485)

* Mafia can be played on your PDA (#78576)

## About The Pull Request

Mafia is now friggin playable from the PDA, I also changed other stuff
too

- You can't use abilities on dead people if you're not supposed to (cant
kill the same person over and over)
- Changelings cant kill other Changelings
- Changelings can now only talk to eachother at night, rather than using
:j
- Everyone starts spawned in the center of the map, since people playing
on PDA can't move their characters. This is so everyone can hear PDA
users in person, as I don't want the chat log to be mandatory.

To do this, all messages you are meant to be able to see, is now logged
for you to see in your Mafia panel. This essentially means that people
playing through the PDA get a downgraded version of it, but I don't know
how much larger I want this UI to be.

Playing Mafia through the PDA will not tell you of other players ahead
of time when signing up (as it shows ckeys + pdas), but they can see the
names in-game. Unfortunately this means we'll have to remove your
customization coming with you, to prevent using it to tell who is dead
in round.

Things I am missing
- Program overlays on PDA/Laptop/Computer
- Icon for the app's header while a game is active

I'm not a spriter and can't make either of these

This is the new UI

![image](https://github.com/tgstation/tgstation/assets/53777086/7cf503d9-b2e2-4127-874a-acad6425d649)

I also fixed alert calls for PDAs and stuff

![image](https://github.com/tgstation/tgstation/assets/53777086/e09b2e5e-b9e7-43ae-9273-c168e9c8e642)

and removed the X at the top on computers since they had no battery

![image](https://github.com/tgstation/tgstation/assets/53777086/d3dd8307-805c-4aba-be5e-4c24a0bdcb91)

Looks a little better now hopefully 👍

## Why It's Good For The Game

- The current Arcade app sucks, and is a solo game. This is much more
entertaining and you can talk to others in it, which is swag as fuck.
- There's a larger potential playerbase for the Minigame making it more
likely to be played.
- Sets groundwork for a better version of
https://github.com/tgstation/tgstation/pull/75879
- Adds more suspense and teamwork in the minigame.

## Changelog

🆑 JohnFulpWillard, sprites by CoiledLamb
add: You can now play Mafia on your PDA.
balance: Mafia changelings can now only talk to eachother during the
night.
fix: Mafia abilities can't be repeatedly used on people.
/🆑

* Mafia can be played on your PDA

---------

Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-10-21 14:25:33 -04:00
committed by GitHub
co-authored by John Willard
parent 9a62cb272b
commit 69ea3c81ad
43 changed files with 711 additions and 409 deletions
+20 -14
View File
@@ -5,6 +5,10 @@
"b" = (
/turf/closed/indestructible/alien,
/area/centcom/mafia)
"d" = (
/obj/effect/landmark/mafia,
/turf/open/floor/plating/abductor,
/area/centcom/mafia)
"g" = (
/obj/mafia_game_board,
/obj/effect/mapping_helpers/broken_floor,
@@ -32,12 +36,10 @@
/turf/open/floor/plating/abductor,
/area/centcom/mafia)
"m" = (
/obj/effect/landmark/mafia,
/obj/structure/bed/abductor,
/turf/open/floor/plating/abductor,
/area/centcom/mafia)
"n" = (
/obj/effect/landmark/mafia,
/obj/structure/bed/abductor,
/turf/open/floor/plating/abductor2,
/area/centcom/mafia)
@@ -146,6 +148,10 @@
icon_state = "alien21"
},
/area/centcom/mafia)
"O" = (
/obj/effect/landmark/mafia,
/turf/open/floor/plating/abductor2,
/area/centcom/mafia)
"P" = (
/turf/closed/indestructible/abductor,
/area/centcom/mafia)
@@ -394,13 +400,13 @@ W
G
x
r
r
O
x
q
d
x
r
O
x
q
d
q
x
E
@@ -444,13 +450,13 @@ j
m
q
q
q
d
x
t
t
t
x
r
O
r
r
n
@@ -494,13 +500,13 @@ j
n
r
r
r
O
x
t
t
t
x
q
d
q
q
m
@@ -544,13 +550,13 @@ I
J
x
q
q
d
x
r
O
x
q
d
x
r
O
r
x
Y
+28 -28
View File
@@ -252,11 +252,11 @@ b
o
r
p
m
q
q
p
r
n
r
p
q
l
@@ -274,7 +274,7 @@ c
d
d
b
n
r
r
b
b
@@ -284,7 +284,7 @@ r
b
b
q
m
q
b
d
d
@@ -301,13 +301,13 @@ b
b
p
r
r
n
p
q
m
p
r
n
p
q
m
q
p
b
@@ -348,19 +348,19 @@ b
c
d
j
q
q
q
m
q
q
q
p
s
t
s
p
r
r
r
n
r
r
r
j
i
c
@@ -398,19 +398,19 @@ b
c
d
j
r
r
r
n
r
r
r
p
s
t
s
p
q
q
q
m
q
q
q
j
d
c
@@ -451,13 +451,13 @@ b
b
p
q
q
m
p
r
n
p
q
m
p
r
n
r
p
b
@@ -474,7 +474,7 @@ c
f
d
b
m
q
q
b
b
@@ -484,7 +484,7 @@ q
b
b
r
n
r
b
d
d
@@ -502,11 +502,11 @@ b
l
q
p
n
r
r
p
q
m
q
p
r
o
+26 -26
View File
@@ -297,11 +297,11 @@ b
J
r
p
m
q
q
p
E
N
O
p
q
l
@@ -319,7 +319,7 @@ c
d
d
b
D
E
O
b
b
@@ -329,7 +329,7 @@ r
b
b
q
m
q
b
d
d
@@ -346,13 +346,13 @@ b
b
p
X
r
M
p
q
m
p
O
N
p
q
m
q
p
b
@@ -393,19 +393,19 @@ b
c
d
j
q
q
q
m
q
q
q
p
t
t
t
p
X
n
r
E
N
O
j
i
c
@@ -443,19 +443,19 @@ b
c
d
j
n
X
r
E
O
N
p
t
t
t
p
q
q
q
m
q
q
q
j
d
c
@@ -496,13 +496,13 @@ b
b
p
q
q
m
p
X
n
p
q
m
p
E
D
O
p
b
@@ -519,7 +519,7 @@ c
f
d
b
m
q
q
b
b
@@ -529,7 +529,7 @@ q
b
b
X
M
r
b
d
d
@@ -547,11 +547,11 @@ b
l
q
p
n
X
r
p
q
m
q
p
E
P
+21 -47
View File
@@ -60,7 +60,6 @@
/turf/open/floor/fakebasalt,
/area/centcom/mafia)
"an" = (
/obj/effect/landmark/mafia,
/obj/effect/turf_decal/trimline/brown/filled/line{
dir = 9
},
@@ -126,6 +125,7 @@
/obj/effect/turf_decal/trimline/brown/filled/end{
dir = 4
},
/obj/effect/landmark/mafia,
/turf/open/floor/iron,
/area/centcom/mafia)
"az" = (
@@ -137,17 +137,11 @@
/obj/structure/closet/secure_closet/miner/unlocked,
/turf/open/floor/iron,
/area/centcom/mafia)
"aA" = (
/obj/effect/landmark/mafia,
/obj/effect/turf_decal/trimline/brown/filled/line{
dir = 6
},
/turf/open/floor/iron,
/area/centcom/mafia)
"aB" = (
/obj/effect/turf_decal/trimline/brown/filled/end{
dir = 1
},
/obj/effect/landmark/mafia,
/turf/open/floor/iron,
/area/centcom/mafia)
"aC" = (
@@ -183,13 +177,6 @@
},
/turf/open/floor/iron,
/area/centcom/mafia)
"aG" = (
/obj/effect/landmark/mafia,
/obj/effect/turf_decal/trimline/brown/filled/line{
dir = 10
},
/turf/open/floor/iron,
/area/centcom/mafia)
"aH" = (
/obj/effect/turf_decal/trimline/brown/filled/line{
dir = 10
@@ -209,7 +196,6 @@
/turf/open/floor/iron,
/area/centcom/mafia)
"aJ" = (
/obj/effect/landmark/mafia,
/obj/effect/turf_decal/trimline/brown/filled/line{
dir = 6
},
@@ -227,13 +213,6 @@
/obj/structure/closet/secure_closet/miner/unlocked,
/turf/open/floor/iron,
/area/centcom/mafia)
"aL" = (
/obj/effect/landmark/mafia,
/obj/effect/turf_decal/trimline/brown/filled/line{
dir = 5
},
/turf/open/floor/iron,
/area/centcom/mafia)
"aM" = (
/obj/effect/turf_decal/trimline/brown/filled/line{
dir = 10
@@ -258,13 +237,7 @@
/area/centcom/mafia)
"aP" = (
/obj/effect/turf_decal/trimline/brown/filled/end,
/turf/open/floor/iron,
/area/centcom/mafia)
"aQ" = (
/obj/effect/landmark/mafia,
/obj/effect/turf_decal/trimline/brown/filled/line{
dir = 9
},
/turf/open/floor/iron,
/area/centcom/mafia)
"aR" = (
@@ -277,6 +250,7 @@
/obj/effect/turf_decal/trimline/brown/filled/end{
dir = 8
},
/obj/effect/landmark/mafia,
/turf/open/floor/iron,
/area/centcom/mafia)
"aT" = (
@@ -473,11 +447,11 @@ aY
ar
aM
ap
am
aq
aq
ap
aw
aA
aV
ap
aq
al
@@ -495,7 +469,7 @@ ac
ad
ad
aY
aL
aF
aN
aY
aY
@@ -505,7 +479,7 @@ ax
aY
aY
aq
am
aq
aY
ad
ad
@@ -524,11 +498,11 @@ ap
aO
aP
ap
aq
am
ap
ay
ap
aq
am
aq
ap
aY
@@ -569,10 +543,10 @@ aY
ac
ad
aj
aq
aq
aq
am
aq
aq
aq
ap
aq
aZ
@@ -628,10 +602,10 @@ aq
ab
aq
ap
aq
aq
aq
am
aq
aq
aq
aj
ad
ac
@@ -672,11 +646,11 @@ aY
aY
ap
aq
aq
am
ap
aS
ap
aq
am
ap
aB
aD
@@ -695,7 +669,7 @@ ac
af
ad
aY
am
aq
aq
aY
aY
@@ -705,7 +679,7 @@ aq
aY
aY
aE
aG
aM
aY
ad
ad
@@ -723,11 +697,11 @@ aY
al
aq
ap
aQ
as
aU
ap
aq
am
aq
ap
aF
aI
+39 -35
View File
@@ -8,6 +8,10 @@
"d" = (
/turf/open/floor/plating,
/area/centcom/mafia)
"e" = (
/obj/effect/landmark/mafia,
/turf/open/floor/iron/dark,
/area/centcom/mafia)
"f" = (
/obj/effect/mapping_helpers/burnt_floor,
/turf/open/floor/plating,
@@ -46,10 +50,6 @@
},
/turf/open/floor/holofloor/wood,
/area/centcom/mafia)
"m" = (
/obj/effect/landmark/mafia,
/turf/open/floor/holofloor/wood,
/area/centcom/mafia)
"n" = (
/obj/item/bedsheet/green,
/obj/structure/bed,
@@ -133,11 +133,6 @@
},
/turf/open/floor/iron,
/area/centcom/mafia)
"B" = (
/obj/effect/landmark/mafia,
/obj/structure/lattice/catwalk,
/turf/open/lava/plasma/mafia,
/area/centcom/mafia)
"C" = (
/obj/mafia_game_board,
/turf/open/floor/holofloor/snow,
@@ -181,6 +176,15 @@
"K" = (
/turf/closed/indestructible/rock/snow,
/area/centcom/mafia)
"R" = (
/obj/effect/landmark/mafia,
/turf/open/floor/iron,
/area/centcom/mafia)
"W" = (
/obj/structure/lattice/catwalk,
/obj/effect/landmark/mafia,
/turf/open/lava/plasma/mafia,
/area/centcom/mafia)
(1,1,1) = {"
a
@@ -342,11 +346,11 @@ s
o
F
p
m
F
q
p
t
y
t
p
z
E
@@ -364,7 +368,7 @@ s
d
d
s
m
F
r
s
s
@@ -374,7 +378,7 @@ t
p
p
z
B
z
p
w
w
@@ -391,13 +395,13 @@ s
s
p
r
r
R
p
q
e
p
t
y
p
z
W
z
p
p
@@ -438,19 +442,19 @@ b
s
d
j
m
F
F
q
q
e
x
J
t
t
p
t
t
t
y
t
t
t
p
w
t
@@ -488,19 +492,19 @@ b
s
d
j
m
F
F
r
r
R
A
J
t
t
p
t
t
t
y
t
t
t
p
w
w
@@ -541,13 +545,13 @@ s
s
p
q
q
e
p
r
R
p
t
y
p
z
W
z
p
p
@@ -564,7 +568,7 @@ s
f
d
s
m
F
q
s
s
@@ -574,7 +578,7 @@ t
p
p
z
B
z
p
w
w
@@ -592,11 +596,11 @@ s
G
F
p
m
F
r
p
t
y
t
p
z
E
+28 -28
View File
@@ -258,11 +258,11 @@ S
b
r
p
m
q
q
p
r
n
r
p
q
o
@@ -280,7 +280,7 @@ c
d
d
S
n
r
r
S
S
@@ -290,7 +290,7 @@ r
S
S
q
m
q
S
d
d
@@ -307,13 +307,13 @@ S
S
p
r
r
n
p
q
m
p
r
n
p
q
m
q
p
S
@@ -354,19 +354,19 @@ S
c
d
j
q
q
q
m
q
q
q
p
t
t
t
p
r
r
r
n
r
r
r
j
i
c
@@ -404,19 +404,19 @@ S
c
d
j
r
r
r
n
r
r
r
p
t
t
t
p
q
q
q
m
q
q
q
j
d
c
@@ -457,13 +457,13 @@ S
S
p
q
q
m
p
r
n
p
q
m
p
r
n
r
p
S
@@ -480,7 +480,7 @@ c
f
d
S
m
q
q
S
S
@@ -490,7 +490,7 @@ q
S
S
r
n
r
S
d
d
@@ -508,11 +508,11 @@ S
o
q
p
n
r
r
p
q
m
q
p
r
b
+20 -21
View File
@@ -45,10 +45,6 @@
/obj/mafia_game_board,
/turf/open/floor/plating,
/area/centcom/mafia)
"n" = (
/obj/effect/landmark/mafia,
/turf/open/floor/mineral/plastitanium,
/area/centcom/mafia)
"o" = (
/obj/effect/turf_decal/tile/red/fourcorners,
/turf/open/floor/iron/dark,
@@ -68,6 +64,7 @@
name = "tactical swivel chair"
},
/obj/effect/turf_decal/tile/red/fourcorners,
/obj/effect/landmark/mafia,
/turf/open/floor/iron/dark,
/area/centcom/mafia)
"r" = (
@@ -93,12 +90,14 @@
name = "tactical swivel chair"
},
/obj/effect/turf_decal/tile/red/fourcorners,
/obj/effect/landmark/mafia,
/turf/open/floor/iron/dark,
/area/centcom/mafia)
"y" = (
/obj/structure/chair/office{
name = "tactical swivel chair"
},
/obj/effect/landmark/mafia,
/turf/open/floor/mineral/plastitanium,
/area/centcom/mafia)
"z" = (
@@ -106,6 +105,7 @@
name = "tactical swivel chair"
},
/obj/effect/turf_decal/tile/red/fourcorners,
/obj/effect/landmark/mafia,
/turf/open/floor/iron/dark,
/area/centcom/mafia)
"A" = (
@@ -113,6 +113,7 @@
dir = 8;
name = "tactical swivel chair"
},
/obj/effect/landmark/mafia,
/turf/open/floor/mineral/plastitanium,
/area/centcom/mafia)
"B" = (
@@ -120,6 +121,7 @@
dir = 4;
name = "tactical swivel chair"
},
/obj/effect/landmark/mafia,
/turf/open/floor/mineral/plastitanium,
/area/centcom/mafia)
"C" = (
@@ -128,6 +130,7 @@
name = "tactical swivel chair"
},
/obj/effect/turf_decal/tile/red/fourcorners,
/obj/effect/landmark/mafia,
/turf/open/floor/iron/dark,
/area/centcom/mafia)
"E" = (
@@ -135,6 +138,7 @@
dir = 1;
name = "tactical swivel chair"
},
/obj/effect/landmark/mafia,
/turf/open/floor/mineral/plastitanium,
/area/centcom/mafia)
"G" = (
@@ -146,11 +150,6 @@
/obj/effect/spawner/random/clothing/syndie,
/turf/open/floor/iron/dark,
/area/centcom/mafia)
"H" = (
/obj/effect/landmark/mafia,
/obj/effect/turf_decal/tile/red/fourcorners,
/turf/open/floor/iron/dark,
/area/centcom/mafia)
"Q" = (
/turf/open/floor/circuit/red,
/area/centcom/mafia)
@@ -318,11 +317,11 @@ w
G
o
p
n
r
r
p
o
H
o
p
r
b
@@ -340,7 +339,7 @@ c
d
d
w
H
o
o
w
w
@@ -350,7 +349,7 @@ o
w
w
r
n
r
w
d
d
@@ -414,7 +413,7 @@ w
c
d
j
n
r
r
r
y
@@ -426,7 +425,7 @@ p
q
o
o
H
o
j
i
c
@@ -464,7 +463,7 @@ w
c
d
j
H
o
o
o
z
@@ -476,7 +475,7 @@ p
E
r
r
n
r
j
d
c
@@ -540,7 +539,7 @@ c
f
d
w
n
r
r
w
w
@@ -550,7 +549,7 @@ r
w
w
o
H
o
w
d
d
@@ -568,11 +567,11 @@ w
b
r
p
H
o
o
p
r
n
r
p
o
G
-14
View File
@@ -96,17 +96,3 @@
AI.holopad_talk(message, language)
return FALSE
return TRUE
/datum/saymode/mafia
key = "j"
mode = MODE_MAFIA
/datum/saymode/mafia/handle_message(mob/living/user, message, datum/language/language)
var/datum/mafia_controller/MF = GLOB.mafia_game
if (!MF)
return TRUE
var/datum/mafia_role/R = MF.player_role_lookup[user]
if(!R || R.team != "mafia")
return TRUE
MF.send_message(span_changeling("<b>[R.body.real_name]:</b> [message]"), "mafia")
return FALSE
+12
View File
@@ -213,6 +213,18 @@
name = "Syndicate Elite Squad"
icon_state = "syndie-elite"
//MAFIA
/area/centcom/mafia
name = "Mafia Minigame"
icon_state = "mafia"
static_lighting = FALSE
base_lighting_alpha = 255
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
area_flags = BLOCK_SUICIDE | UNIQUE_AREA
//CAPTURE THE FLAG
/area/centcom/ctf
name = "Capture the Flag"
@@ -62,6 +62,7 @@
mask = /obj/item/clothing/mask/surgical
neck = /obj/item/camera
suit = /obj/item/clothing/suit/apron
shoes = /obj/item/clothing/shoes/sneakers/black
/datum/outfit/obsessed/post_equip(mob/living/carbon/human/H)
for(var/obj/item/carried_item in H.get_equipped_items(include_pockets = TRUE, include_accessories = TRUE))
@@ -382,6 +382,7 @@
mask = /obj/item/clothing/mask/gas
l_hand = /obj/item/melee/energy/sword
r_hand = /obj/item/gun/energy/recharge/ebow
shoes = /obj/item/clothing/shoes/magboots/advance
/datum/outfit/traitor/post_equip(mob/living/carbon/human/H, visualsOnly)
var/obj/item/melee/energy/sword/sword = locate() in H.held_items
@@ -27,4 +27,5 @@
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif',
"borg_mon.gif" = 'icons/program_icons/borg_mon.gif',
"robotact.gif" = 'icons/program_icons/robotact.gif',
"mafia.gif" = 'icons/program_icons/mafia.gif',
)
+4
View File
@@ -100,6 +100,8 @@
/// now clearing refs to prepare for the next day. Do not do any actions here, it's just for ref clearing.
#define COMSIG_MAFIA_NIGHT_END "night_end"
/// signal sent to roles when the game is confirmed starting
#define COMSIG_MAFIA_GAME_START "game_start"
/// signal sent to roles when the game is confirmed ending
#define COMSIG_MAFIA_GAME_END "game_end"
@@ -107,6 +109,8 @@
GLOBAL_LIST_EMPTY(mafia_signup)
/// list of ghosts who want to play mafia that have since disconnected. They are kept in the lobby, but not counted for starting a game.
GLOBAL_LIST_EMPTY(mafia_bad_signup)
/// list of PDAs who want to play mafia, every time someone enters the list it checks to see if enough are in
GLOBAL_LIST_EMPTY(pda_mafia_signup)
/// the current global mafia game running.
GLOBAL_VAR(mafia_game)
/// list of ghosts in mafia_signup who have voted to start early
+19 -7
View File
@@ -29,6 +29,11 @@
target_role = null
return ..()
///Handles special messagese sent by ability-specific stuff (such as changeling chat).
/datum/mafia_ability/proc/handle_speech(datum/source, list/speech_args)
SIGNAL_HANDLER
return FALSE
/**
* Called when refs need to be cleared, when the target is no longer set.
*/
@@ -52,21 +57,28 @@
if(game.phase != valid_use_period)
return FALSE
if(host_role.role_flags & ROLE_ROLEBLOCKED)
to_chat(host_role.body, span_warning("You were roleblocked!"))
host_role.send_message_to_player(span_warning("You were roleblocked!"))
return FALSE
if(host_role.game_status == MAFIA_DEAD)
return FALSE
if(potential_target)
if((use_flags & CAN_USE_ON_DEAD) && (potential_target.game_status != MAFIA_DEAD))
if(use_flags & CAN_USE_ON_DEAD)
if(potential_target.game_status != MAFIA_DEAD)
if(!silent)
host_role.send_message_to_player(span_notice("This can only be used on dead players."))
return FALSE
else if(potential_target.game_status == MAFIA_DEAD)
if(!silent)
to_chat(host_role.body, span_notice("This can only be used on dead players."))
host_role.send_message_to_player(span_notice("This can only be used on living players."))
return FALSE
if(!(use_flags & CAN_USE_ON_SELF) && (potential_target == host_role))
if(!silent)
to_chat(host_role.body, span_notice("This can only be used on others."))
host_role.send_message_to_player(span_notice("This can only be used on others."))
return FALSE
if(!(use_flags & CAN_USE_ON_OTHERS) && (potential_target != host_role))
if(!silent)
to_chat(host_role.body, span_notice("This can only be used on yourself."))
host_role.send_message_to_player(span_notice("This can only be used on yourself."))
return FALSE
return TRUE
@@ -90,7 +102,7 @@
if(target_role)
if(SEND_SIGNAL(target_role, COMSIG_MAFIA_ON_VISIT, game, host_role) & MAFIA_VISIT_INTERRUPTED) //visited a warden. something that prevents you by visiting that person
to_chat(host_role.body, span_danger("Your [name] was interrupted!"))
host_role.send_message_to_player(span_danger("Your [name] was interrupted!"))
return FALSE
return TRUE
@@ -121,5 +133,5 @@
target_role = new_target
feedback_text = replacetext(feedback_text, "%WILL_PERFORM%", "now")
to_chat(host_role.body, span_notice(feedback_text))
host_role.send_message_to_player(span_notice(feedback_text))
return TRUE
@@ -20,5 +20,5 @@
if(MAFIA_TEAM_SOLO)
fluff = "rogue, with their own objectives..."
to_chat(host_role.body, span_warning("Your investigations reveal that [target_role.body.real_name] is [fluff]"))
host_role.send_message_to_player(span_warning("Your investigations reveal that [target_role.body.real_name] is [fluff]"))
return TRUE
@@ -14,5 +14,5 @@
if(!.)
return FALSE
to_chat(host_role.body, span_warning("You invoke spirit of [target_role.body.real_name] and learn their role was <b>[target_role.name]<b>."))
host_role.send_message_to_player(span_warning("You invoke spirit of [target_role.body.real_name] and learn their role was <b>[target_role.name]<b>."))
return TRUE
@@ -13,7 +13,7 @@
if(!.)
return FALSE
to_chat(host_role.body, span_warning("You have revealed the true nature of the [target_role]!"))
host_role.send_message_to_player(span_warning("You have revealed the true nature of the [target_role]!"))
target_role.reveal_role(game, verbose = TRUE)
return TRUE
@@ -13,7 +13,7 @@
return FALSE
if((target_role.role_flags & ROLE_UNDETECTABLE))
to_chat(host_role.body,span_warning("[target_role.body.real_name]'s memories reveal that they are the [pick(game.all_roles - target_role)]."))
host_role.send_message_to_player(span_warning("[target_role.body.real_name]'s memories reveal that they are the [pick(game.all_roles - target_role)]."))
else
to_chat(host_role.body,span_warning("[target_role.body.real_name]'s memories reveal that they are the [target_role.name]."))
host_role.send_message_to_player(span_warning("[target_role.body.real_name]'s memories reveal that they are the [target_role.name]."))
return TRUE
@@ -22,8 +22,8 @@
SIGNAL_HANDLER
if(attacker == host_role)
return
to_chat(host_role.body, span_userdanger("You have shot a visitor!"))
to_chat(attacker.body, span_userdanger("You have visited the warden!"))
host_role.send_message_to_player(span_userdanger("You have shot a visitor!"))
attacker.send_message_to_player(span_userdanger("You have visited the warden!"))
attacker.kill(game, host_role, lynch = FALSE)
return MAFIA_VISIT_INTERRUPTED
@@ -22,11 +22,11 @@
return FALSE
if(!(target_role in darkened_players))
to_chat(target_role.body, span_userdanger("The lights begin to flicker and dim. You're in danger."))
target_role.send_message_to_player(span_userdanger("The lights begin to flicker and dim. You're in danger."))
darkened_players += target_role
else
for(var/datum/mafia_role/dead_players as anything in darkened_players)
to_chat(dead_players.body, span_userdanger("A shadowy figure appears out of the darkness!"))
dead_players.send_message_to_player(span_userdanger("A shadowy figure appears out of the darkness!"))
dead_players.kill(game, host_role, FALSE)
darkened_players -= dead_players
return TRUE
@@ -37,6 +37,6 @@
return //no chance man, that's a town lynch
if(attacker in darkened_players)
to_chat(host_role.body, span_userdanger("You were attacked by someone in a flickering room. You have danced in the shadows, evading them."))
host_role.send_message_to_player(span_userdanger("You were attacked by someone in a flickering room. You have danced in the shadows, evading them."))
return MAFIA_PREVENT_KILL
+4 -4
View File
@@ -18,17 +18,17 @@
return FALSE
if(!target_role.kill(game, host_role, FALSE))
to_chat(host_role.body, span_danger("Your attempt at killing [target_role.body.real_name] was prevented!"))
host_role.send_message_to_player(span_danger("Your attempt at killing [target_role.body.real_name] was prevented!"))
else
to_chat(target_role.body, span_userdanger("You have been [attack_action] \a [host_role.name]!"))
target_role.send_message_to_player(span_userdanger("You have been [attack_action] \a [host_role.name]!"))
if(honorable && (target_role.team != MAFIA_TEAM_TOWN))
to_chat(host_role.body, span_userdanger("You have killed an innocent crewmember. You will die tomorrow night."))
host_role.send_message_to_player(span_userdanger("You have killed an innocent crewmember. You will die tomorrow night."))
RegisterSignal(game, COMSIG_MAFIA_SUNDOWN, PROC_REF(internal_affairs))
return TRUE
/datum/mafia_ability/attack_player/proc/internal_affairs(datum/mafia_controller/game)
SIGNAL_HANDLER
to_chat(host_role.body, span_userdanger("You have been killed by Nanotrasen Internal Affairs!"))
host_role.send_message_to_player(span_userdanger("You have been killed by Nanotrasen Internal Affairs!"))
host_role.reveal_role(game, verbose = TRUE)
host_role.kill(game, host_role, FALSE) //you technically kill yourself but that shouldn't matter
@@ -18,7 +18,7 @@
if(!.)
return FALSE
if(new_target.role_flags & ROLE_VULNERABLE)
to_chat(host_role.body, span_notice("[new_target] can't be protected."))
host_role.send_message_to_player(span_notice("[new_target] can't be protected."))
return FALSE
/datum/mafia_ability/heal/perform_action_target(datum/mafia_controller/game, datum/mafia_role/day_target)
@@ -39,10 +39,10 @@
/datum/mafia_ability/heal/proc/prevent_kill(datum/source, datum/mafia_controller/game, datum/mafia_role/attacker, lynch)
SIGNAL_HANDLER
if(host_role == target_role)
to_chat(host_role.body, span_warning("You were attacked last night!"))
host_role.send_message_to_player(span_warning("You were attacked last night!"))
return MAFIA_PREVENT_KILL
to_chat(host_role.body, span_warning("The person you protected tonight was attacked!"))
to_chat(target_role.body, span_greentext("You were attacked last night, but [saving_message]!"))
host_role.send_message_to_player(span_warning("The person you protected tonight was attacked!"))
target_role.send_message_to_player(span_greentext("You were attacked last night, but [saving_message]!"))
return MAFIA_PREVENT_KILL
/**
@@ -60,6 +60,6 @@
return FALSE
if(attacker.kill(game, host_role, FALSE)) //you attack the attacker
to_chat(attacker.body, span_userdanger("You have been ambushed by Security!"))
attacker.send_message_to_player(span_userdanger("You have been ambushed by Security!"))
host_role.kill(game, attacker, FALSE) //the attacker attacks you, they were able to attack the target so they can attack you.
return FALSE
@@ -33,7 +33,7 @@
/datum/mafia_ability/vest/proc/self_defense(datum/source, datum/mafia_controller/game, datum/mafia_role/attacker, lynch)
SIGNAL_HANDLER
to_chat(host_role.body, span_greentext("Your vest saved you!"))
host_role.send_message_to_player(span_greentext("Your vest saved you!"))
return MAFIA_PREVENT_KILL
/datum/mafia_ability/vest/proc/end_protection(datum/mafia_controller/game)
@@ -30,12 +30,32 @@
ling_sent = TRUE
if(target_role.kill(game, host_role, FALSE))
to_chat(target_role.body, span_userdanger("You have been killed by a Changeling!"))
target_role.send_message_to_player(span_userdanger("You have been killed by a Changeling!"))
game.send_message(span_danger("[host_role.body.real_name] was selected to attack [target_role.body.real_name] tonight!"), MAFIA_TEAM_MAFIA)
return TRUE
/datum/mafia_ability/changeling_kill/set_target(datum/mafia_controller/game, datum/mafia_role/new_target)
if(new_target.team == MAFIA_TEAM_MAFIA)
return FALSE
if(!validate_action_target(game, new_target))
return FALSE
using_ability = TRUE
game.vote_for(host_role, new_target, "Mafia", MAFIA_TEAM_MAFIA)
/**
* handle_message
*
* During the night, Changelings talking will instead redirect it to Changeling chat.
*/
/datum/mafia_ability/changeling_kill/handle_speech(datum/source, list/speech_args)
. = ..()
var/datum/mafia_controller/mafia_game = GLOB.mafia_game
if(!mafia_game)
return FALSE
if (mafia_game.phase != MAFIA_PHASE_NIGHT)
return FALSE
var/phrase = html_decode(speech_args[SPEECH_MESSAGE])
mafia_game.send_message(span_changeling("<b>[host_role.body.real_name]:</b> [phrase]"), MAFIA_TEAM_MAFIA)
speech_args[SPEECH_MESSAGE] = ""
return TRUE
+142 -56
View File
@@ -2,6 +2,9 @@ GLOBAL_LIST_INIT(mafia_roles_by_name, setup_mafia_roles_by_name())
GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
///How many votes are needed to unlock the 'Universally Hated' achievement.
#define UNIVERSALLY_HATED_REQUIREMENT 12
/**
* The mafia controller handles the mafia minigame in progress.
* It is first created when the first ghost signs up to play.
@@ -11,7 +14,8 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
var/list/datum/mafia_role/all_roles = list()
///all living roles in the game, removed on death.
var/list/datum/mafia_role/living_roles = list()
///exists to speed up role retrieval, it's a dict. `player_role_lookup[player ckey]` will give you the role they play
///exists to speed up role retrieval, it's a dict.
/// `player_role_lookup[player ckey/PDA]` will give you the role they play
var/list/player_role_lookup = list()
///what part of the game you're playing in. day phases, night phases, judgement phases, etc.
var/phase = MAFIA_PHASE_SETUP
@@ -105,10 +109,10 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
/datum/mafia_controller/Destroy(force, ...)
. = ..()
if(GLOB.mafia_game == src)
GLOB.mafia_game = null
end_game()
QDEL_NULL(map_deleter)
if(GLOB.mafia_game == src)
GLOB.mafia_game = null
/**
* Triggers at beginning of the game when there is a confirmed list of valid, ready players.
@@ -122,9 +126,10 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
* * Puts players in each role randomly
* Arguments:
* * setup_list: list of all the datum setups (fancy list of roles) that would work for the game
* * ready_players: list of filtered, sane players (so not playing or disconnected) for the game to put into roles
* * ready_ghosts: list of filtered, sane players (so not playing or disconnected) for the game to put into roles
* * ready_pdas: list of PDAs wanting to play the Mafia game.
*/
/datum/mafia_controller/proc/prepare_game(setup_list, ready_players)
/datum/mafia_controller/proc/prepare_game(setup_list, ready_ghosts, ready_pdas)
var/static/list/possible_maps = subtypesof(/datum/map_template/mafia)
var/turf/spawn_area = get_turf(locate(/obj/effect/landmark/mafia_game_area) in GLOB.landmarks_list)
@@ -156,16 +161,32 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
var/list/spawnpoints = landmarks.Copy()
for(var/datum/mafia_role/role as anything in all_roles)
role.assigned_landmark = pick_n_take(spawnpoints)
var/selected_player
if(!debug)
role.player_key = pick_n_take(ready_players)
if(length(ready_pdas))
selected_player = pick(ready_pdas)
else
selected_player = pick(ready_ghosts)
else
role.player_key = pop(ready_players)
if(length(ready_pdas))
selected_player = peek(ready_pdas)
else
selected_player = peek(ready_ghosts)
if(selected_player in ready_pdas)
role.player_pda = selected_player
ready_pdas -= selected_player
else
role.player_key = selected_player
ready_ghosts -= selected_player
/datum/mafia_controller/proc/send_message(msg, team)
///Sends a global message to all players, or just 'team' if set.
/datum/mafia_controller/proc/send_message(msg, team, log_only = FALSE)
for(var/datum/mafia_role/role as anything in all_roles)
if(team && role.team != team)
continue
to_chat(role.body, msg)
role.role_messages += msg
if(!log_only)
to_chat(role.body, msg)
/**
* The game by this point is now all set up, and so we can put people in their bodies and start the first phase.
@@ -176,10 +197,16 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
*/
/datum/mafia_controller/proc/start_game()
create_bodies()
SEND_GLOBAL_SIGNAL(COMSIG_MAFIA_GAME_START, src)
start_day(can_vote = FALSE)
send_message(span_notice("<b>The selected map is [current_map.name]!</b></br>[current_map.description]"))
send_message(span_notice("<b>The selected map is [current_map.name]!</b></br> [current_map.description]"))
send_message("<b>Day [turn] started! There is no voting on the first day. Say hello to everybody!</b>")
next_phase_timer = addtimer(CALLBACK(src, PROC_REF(check_trial), FALSE), (FIRST_DAY_PERIOD_LENGTH / time_speedup), TIMER_STOPPABLE) //no voting period = no votes = instant night
for(var/datum/mafia_role/roles as anything in all_roles)
var/obj/item/modular_computer/modpc = roles.player_pda
if(!modpc)
continue
modpc.update_static_data_for_all_viewers()
/**
* How every day starts.
@@ -229,7 +256,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
var/datum/mafia_role/loser = get_vote_winner("Day")//, majority_of_town = TRUE)
var/loser_votes = get_vote_count(loser, "Day")
if(loser)
if(loser_votes > 12)
if(loser_votes > UNIVERSALLY_HATED_REQUIREMENT)
award_role(/datum/award/achievement/mafia/universally_hated, loser)
//refresh the lists
judgement_abstain_votes = list()
@@ -369,8 +396,11 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
* * role: mafia_role datum to reward.
*/
/datum/mafia_controller/proc/award_role(award, datum/mafia_role/rewarded)
var/client/role_client = rewarded.body.client
role_client?.give_award(award, rewarded.body)
rewarded.body?.client?.give_award(award, rewarded.body)
if(!rewarded.player_pda)
return
for(var/datum/tgui/window as anything in rewarded.player_pda.open_uis)
window.user?.client?.give_award(award, rewarded.body)
/**
* The end of the game is in two procs, because we want a bit of time for players to see eachothers roles.
@@ -584,21 +614,28 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
RegisterSignal(H, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(display_votes))
var/datum/action/innate/mafia_panel/mafia_panel = new(null,src)
mafia_panel.Grant(H)
var/obj/item/modular_computer/modpc = role.player_pda
role.register_body(H)
if(modpc)
player_role_lookup[modpc] = role
else
player_role_lookup[H] = role
var/client/player_client = GLOB.directory[role.player_key]
if(player_client)
player_client.prefs.safe_transfer_prefs_to(H, is_antag = TRUE)
role.body = H
player_role_lookup[H] = role
role.put_player_in_body(player_client)
role.put_player_in_body(player_client)
role.greet()
/datum/mafia_controller/ui_static_data(mob/user)
/datum/mafia_controller/ui_static_data(atom/user)
var/list/data = list()
if(user.client?.holder)
if(usr.client?.holder)
data["admin_controls"] = TRUE //show admin buttons to start/setup/stop
data["is_observer"] = isobserver(user)
data["all_roles"] = current_setup_text
if(phase == MAFIA_PHASE_SETUP)
return data
var/datum/mafia_role/user_role = player_role_lookup[user]
if(user_role)
data["roleinfo"] = list(
@@ -610,7 +647,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
return data
/datum/mafia_controller/ui_data(mob/user)
/datum/mafia_controller/ui_data(atom/user)
var/list/data = list()
data["phase"] = phase
@@ -619,18 +656,25 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
if(phase == MAFIA_PHASE_SETUP)
data["lobbydata"] = list()
for(var/key in GLOB.mafia_signup + GLOB.mafia_bad_signup)
for(var/key in GLOB.mafia_signup + GLOB.mafia_bad_signup + GLOB.pda_mafia_signup)
var/list/lobby_member = list()
lobby_member["name"] = key
lobby_member["status"] = (key in GLOB.mafia_bad_signup) ? "Disconnected" : "Ready"
data["lobbydata"] += list(lobby_member)
return data
data["timeleft"] = next_phase_timer ? timeleft(next_phase_timer) : 0 //the tgui menu counts this down.
data["timeleft"] = next_phase_timer ? timeleft(next_phase_timer) : 0
var/datum/mafia_role/user_role = player_role_lookup[user]
if(user_role)
data["user_notes"] = user_role.written_notes
data["messages"] = list()
var/list/ui_messages = list()
for(var/i = user_role.role_messages.len to 1 step -1)
ui_messages.Add(list(list(
"msg" = user_role.role_messages[i],
)))
data["messages"] = ui_messages
data["players"] = list()
for(var/datum/mafia_role/role as anything in all_roles)
@@ -659,8 +703,13 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
if(.)
return
var/datum/mafia_role/user_role = player_role_lookup[usr]
var/obj/item/modular_computer/modpc = ui.src_object
if(istype(modpc))
user_role = player_role_lookup[modpc]
else
modpc = null
//Admin actions
if(usr.client?.holder)
if(ui.user.client.holder)
switch(action)
if("new_game")
if(phase == MAFIA_PHASE_SETUP)
@@ -686,9 +735,8 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
player.body.forceMove(get_turf(player.assigned_landmark))
if(failed.len)
to_chat(usr, "List of players who no longer had a body (if you see this, the game is runtiming anyway so just hit \"New Game\" to end it)")
for(var/i in failed)
var/datum/mafia_role/fail = i
to_chat(usr, fail.player_key)
for(var/datum/mafia_role/fail as anything in failed)
to_chat(usr, fail.player_key || fail.player_pda)
if("debug_setup")
var/list/debug_setup = list()
var/list/rolelist_dict = list("CANCEL", "FINISH") + GLOB.mafia_roles_by_name
@@ -732,38 +780,61 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
if(!user_role)//just the dead
switch(action)
if("mf_signup")
var/client/C = ui.user.client
var/client/ghost_client = ui.user.client
if(!SSticker.HasRoundStarted())
to_chat(usr, span_warning("Wait for the round to start."))
return
if(GLOB.mafia_signup[C.ckey])
GLOB.mafia_signup -= C.ckey
GLOB.mafia_early_votes -= C.ckey //Remove their early start vote as well
to_chat(usr, span_notice("You unregister from Mafia."))
return TRUE
if(isnull(modpc))
if(GLOB.mafia_signup[ghost_client.ckey])
GLOB.mafia_signup -= ghost_client.ckey
GLOB.mafia_early_votes -= ghost_client.ckey //Remove their early start vote as well
to_chat(usr, span_notice("You unregister from Mafia."))
return TRUE
else
GLOB.mafia_signup[ghost_client.ckey] = TRUE
to_chat(usr, span_notice("You sign up for Mafia."))
else
GLOB.mafia_signup[C.ckey] = TRUE
to_chat(usr, span_notice("You sign up for Mafia."))
if(GLOB.pda_mafia_signup[modpc])
GLOB.pda_mafia_signup -= modpc
GLOB.mafia_early_votes -= modpc //Remove their early start vote as well
to_chat(usr, span_notice("You unregister from Mafia."))
return TRUE
else
GLOB.pda_mafia_signup[modpc] = TRUE
to_chat(usr, span_notice("You sign up for Mafia."))
if(phase == MAFIA_PHASE_SETUP)
check_signups()
try_autostart()
return TRUE
if("vote_to_start")
var/client/C = ui.user.client
var/client/ghost_client = ui.user.client
if(phase != MAFIA_PHASE_SETUP)
to_chat(usr, span_notice("You cannot vote to start while a game is underway!"))
return
if(!GLOB.mafia_signup[C.ckey])
to_chat(usr, span_notice("You must be signed up for this game to vote!"))
return
if(GLOB.mafia_early_votes[C.ckey])
GLOB.mafia_early_votes -= C.ckey
to_chat(usr, span_notice("You are no longer voting to start the game early."))
if(isnull(modpc))
if(!GLOB.mafia_signup[ghost_client.ckey])
to_chat(usr, span_notice("You must be signed up for this game to vote!"))
return
if(GLOB.mafia_early_votes[ghost_client.ckey])
GLOB.mafia_early_votes -= ghost_client.ckey
to_chat(usr, span_notice("You are no longer voting to start the game early."))
else
GLOB.mafia_early_votes[ghost_client.ckey] = ghost_client
to_chat(usr, span_notice("You vote to start the game early ([length(GLOB.mafia_early_votes)] out of [max(round(length(GLOB.mafia_signup) / 2), round(MAFIA_MIN_PLAYER_COUNT / 2))])."))
if(check_start_votes()) //See if we have enough votes to start
forced_setup()
else
GLOB.mafia_early_votes[C.ckey] = C
to_chat(usr, span_notice("You vote to start the game early ([length(GLOB.mafia_early_votes)] out of [max(round(length(GLOB.mafia_signup) / 2), round(MAFIA_MIN_PLAYER_COUNT / 2))])."))
if(check_start_votes()) //See if we have enough votes to start
forced_setup()
if(!GLOB.pda_mafia_signup[modpc])
to_chat(usr, span_notice("You must be signed up for this game to vote!"))
return
if(GLOB.mafia_early_votes[modpc])
GLOB.mafia_early_votes -= modpc
to_chat(usr, span_notice("You are no longer voting to start the game early."))
else
GLOB.mafia_early_votes[modpc] = modpc
to_chat(usr, span_notice("You vote to start the game early ([length(GLOB.mafia_early_votes)] out of [max(round(length(GLOB.mafia_signup) / 2), round(MAFIA_MIN_PLAYER_COUNT / 2))])."))
if(check_start_votes()) //See if we have enough votes to start
forced_setup()
return TRUE
if(user_role && user_role.game_status == MAFIA_DEAD)
@@ -774,8 +845,14 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
if("change_notes")
if(user_role.game_status == MAFIA_DEAD)
return TRUE
user_role.written_notes = params["new_notes"]
user_role.body.balloon_alert(user_role.body, "notes saved")
user_role.written_notes = sanitize_text(params["new_notes"])
user_role.send_message_to_player("notes saved", balloon_alert = TRUE)
return TRUE
if("send_message_to_chat")
if(user_role.game_status == MAFIA_DEAD)
return TRUE
var/message_said = sanitize_text(params["message"])
user_role.body.say(message_said, forced = "mafia chat (sent by [ui.user.client])")
return TRUE
if("send_notes_to_chat")
if(user_role.game_status == MAFIA_DEAD || !user_role.written_notes)
@@ -807,21 +884,21 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
if("vote_abstain")
if(phase != MAFIA_PHASE_JUDGEMENT || (user_role in judgement_abstain_votes))
return
to_chat(user_role.body,"You have decided to abstain.")
user_role.send_message_to_player("You have decided to abstain.")
judgement_innocent_votes -= user_role
judgement_guilty_votes -= user_role
judgement_abstain_votes += user_role
if("vote_innocent")
if(phase != MAFIA_PHASE_JUDGEMENT || (user_role in judgement_innocent_votes))
return
to_chat(user_role.body,"Your vote on [on_trial.body.real_name] submitted as INNOCENT!")
user_role.send_message_to_player("Your vote on [on_trial.body.real_name] submitted as INNOCENT!")
judgement_abstain_votes -= user_role//no fakers, and...
judgement_guilty_votes -= user_role//no radical centrism
judgement_innocent_votes += user_role
if("vote_guilty")
if(phase != MAFIA_PHASE_JUDGEMENT || (user_role in judgement_guilty_votes))
return
to_chat(user_role.body,"Your vote on [on_trial.body.real_name] submitted as GUILTY!")
user_role.send_message_to_player("Your vote on [on_trial.body.real_name] submitted as GUILTY!")
judgement_abstain_votes -= user_role//no fakers, and...
judgement_innocent_votes -= user_role//no radical centrism
judgement_guilty_votes += user_role
@@ -886,12 +963,15 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
if(setup.len)
req_players = assoc_value_sum(setup)
var/list/filtered_pdas = GLOB.pda_mafia_signup
if(!isnull(filtered_pdas)) //pdas get priority
req_players -= length(GLOB.pda_mafia_signup)
var/list/filtered_keys = filter_players(req_players)
var/needed_players = length(filtered_keys)
var/needed_players = length(filtered_keys) + length(filtered_pdas)
if(!setup.len) //don't actually have one yet, so generate a max player random setup. it's good to do this here instead of above so it doesn't generate one every time a game could possibly start.
setup = generate_standard_setup(needed_players)
prepare_game(setup, filtered_keys)
prepare_game(setup, filtered_keys, filtered_pdas)
start_game()
/**
@@ -902,8 +982,9 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
/datum/mafia_controller/proc/forced_setup()
check_signups() //Refresh the signup list, so our numbers are accurate and we only take active players into consideration.
var/list/filtered_pdas = GLOB.pda_mafia_signup
var/list/filtered_keys = filter_players(length(GLOB.mafia_signup))
var/req_players = length(filtered_keys)
var/req_players = length(filtered_keys) + length(filtered_pdas)
if(!req_players) //If we have nobody signed up, we give up on starting
log_admin("Attempted to force a mafia game to start with nobody signed up!")
@@ -911,7 +992,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
var/list/setup = generate_standard_setup(req_players)
prepare_game(setup, filtered_keys)
prepare_game(setup, filtered_keys, filtered_pdas)
early_start = TRUE
start_game()
@@ -983,7 +1064,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
/datum/mafia_controller/proc/try_autostart()
if(phase != MAFIA_PHASE_SETUP || !(GLOB.ghost_role_flags & GHOSTROLE_MINIGAME))
return
if(GLOB.mafia_signup.len >= MAFIA_MAX_PLAYER_COUNT || custom_setup)//enough people to try and make something (or debug mode)
if((GLOB.mafia_signup.len + GLOB.pda_mafia_signup.len) >= MAFIA_MAX_PLAYER_COUNT || custom_setup)//enough people to try and make something (or debug mode)
basic_setup()
/**
@@ -1034,7 +1115,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
maptext_height = 480
maptext_width = 480
///The client that owns the popup.
var/datum/mafia_role/mafia/owner
var/datum/mafia_role/owner
/atom/movable/screen/mafia_popup/Initialize(mapload, datum/mafia_role/mafia)
. = ..()
@@ -1045,6 +1126,9 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
return ..()
/atom/movable/screen/mafia_popup/proc/update_text(text)
owner.role_messages += text
if(!owner.body.client)
return
maptext = MAPTEXT("<span style='color: [COLOR_RED]; text-align: center; font-size: 24pt'> [text]</span>")
maptext_width = view_to_pixels(owner.body.client?.view_size.getView())[1]
owner.body.client?.screen += src
@@ -1063,3 +1147,5 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
QDEL_NULL(GLOB.mafia_game)
var/datum/mafia_controller/new_controller = new()
return new_controller
#undef UNIVERSALLY_HATED_REQUIREMENT
-11
View File
@@ -26,17 +26,6 @@
MF = create_mafia_game()
MF.ui_interact(user)
/area/centcom/mafia
name = "Mafia Minigame"
icon_state = "mafia"
static_lighting = FALSE
base_lighting_alpha = 255
requires_power = FALSE
has_gravity = STANDARD_GRAVITY
flags_1 = NONE
area_flags = BLOCK_SUICIDE | UNIQUE_AREA
/datum/map_template/mafia
should_place_on_top = FALSE
///A brief background tidbit
@@ -1,6 +1,6 @@
/datum/mafia_role/mafia
name = "Changeling"
desc = "You're a member of the changeling hive. Use ':j' talk prefix to talk to your fellow lings."
desc = "You're a member of the changeling hive. You may speak with your fellow Changelings at night."
team = MAFIA_TEAM_MAFIA
role_type = MAFIA_REGULAR
role_flags = ROLE_CAN_KILL
+49
View File
@@ -15,7 +15,15 @@
///The player's written notes, that they can send to chat at any time.
var/written_notes
///The ckey of the person playing as this Mafia role, CAN BE NULL IN FAVOR OF player_pda.
var/player_key
///The PDA of the person playing as this Mafia role, CAN BE NULL IN FAVOR OF player_key.
var/obj/item/modular_computer/player_pda
///List of all messages this role got throughout the game.
var/list/role_messages = list()
var/mob/living/carbon/human/body
var/obj/effect/landmark/mafia/assigned_landmark
@@ -46,11 +54,52 @@
role_unique_actions -= abilities
/datum/mafia_role/Destroy(force, ...)
UnregisterSignal(body, COMSIG_MOB_SAY)
QDEL_NULL(mafia_alert)
QDEL_NULL(body)
QDEL_LIST(role_unique_actions)
role_messages = null
return ..()
/datum/mafia_role/proc/register_body(mob/living/carbon/human/new_body)
body = new_body
RegisterSignal(new_body, COMSIG_MOB_SAY, PROC_REF(handle_speech))
/**
* send_message_to_player
*
* Sends a message to a player, checking if they are playing through a PDA or not.
* Args:
* * message - The message to send to the person
* * balloon_alert - Whether it should be as a balloon alert, only if it's to a non-PDA user.
*/
/datum/mafia_role/proc/send_message_to_player(message, balloon_alert = FALSE)
if(player_pda)
role_messages += message
return
if(balloon_alert)
body.balloon_alert(body, message)
return
to_chat(body, message)
/**
* handle_speech
*
* Handles Mafia roles talking in chat.
* First it will go through their abilities for Ability-specific speech,
* if none affects it, we will go to day chat.
*/
/datum/mafia_role/proc/handle_speech(datum/source, list/speech_args)
SIGNAL_HANDLER
for(var/datum/mafia_ability/abilities as anything in role_unique_actions)
if(abilities.handle_speech(source, speech_args))
return
var/datum/mafia_controller/mafia_game = GLOB.mafia_game
if(!mafia_game || mafia_game.phase == MAFIA_PHASE_NIGHT)
return
var/message = "[source]: [html_decode(speech_args[SPEECH_MESSAGE])]"
mafia_game.send_message(message, log_only = TRUE)
/**
* Puts the player in their body and keeps track of their previous one to put them back in later.
* Adds the playing_mafia trait so people examining them will know why they're currently lacking a soul.
@@ -500,7 +500,7 @@
if(!caller || !caller.alert_able || caller.alert_silenced || !alerttext) //Yeah, we're checking alert_able. No, you don't get to make alerts that the user can't silence.
return FALSE
playsound(src, sound, 50, TRUE)
loc.visible_message(span_notice("[icon2html(src)] [span_notice("The [src] displays a [caller.filedesc] notification: [alerttext]")]"))
physical.loc.visible_message(span_notice("[icon2html(physical, viewers(physical.loc))] \The [src] displays a [caller.filedesc] notification: [alerttext]"))
/obj/item/modular_computer/proc/ring(ringtone) // bring bring
if(HAS_TRAIT(SSstation, STATION_TRAIT_PDA_GLITCHED))
@@ -517,7 +517,6 @@
var/list/data = list()
data["PC_device_theme"] = device_theme
data["PC_showbatteryicon"] = !!internal_cell
if(internal_cell)
switch(internal_cell.percent())
@@ -535,8 +534,8 @@
data["PC_batteryicon"] = "batt_5.gif"
data["PC_batterypercent"] = "[round(internal_cell.percent())]%"
else
data["PC_batteryicon"] = "batt_5.gif"
data["PC_batterypercent"] = "N/C"
data["PC_batteryicon"] = null
data["PC_batterypercent"] = null
switch(get_ntnet_status())
if(NTNET_NO_SIGNAL)
@@ -132,7 +132,7 @@
if(isAdminGhostAI(user))
return TRUE
if(!transfer && computer && (computer.obj_flags & EMAGGED)) //emags can bypass the execution locks but not the download ones.
if(computer && (computer.obj_flags & EMAGGED) && (available_on_syndinet || !transfer)) //emagged can run anything on syndinet, and can bypass execution locks, but not download.
return TRUE
// Defaults to required_access
@@ -19,11 +19,11 @@
/datum/computer_file/program/ntnet_dos/process_tick(seconds_per_tick)
dos_speed = 0
switch(ntnet_status)
if(1)
if(NTNET_LOW_SIGNAL)
dos_speed = NTNETSPEED_LOWSIGNAL * 10
if(2)
if(NTNET_GOOD_SIGNAL)
dos_speed = NTNETSPEED_HIGHSIGNAL * 10
if(3)
if(NTNET_ETHERNET_SIGNAL)
dos_speed = NTNETSPEED_ETHERNET * 10
if(target && executed)
target.dos_overload += dos_speed
@@ -18,12 +18,9 @@
/// The file under consideration.
var/datum/computer_file/data/ordnance/selected_file
/datum/computer_file/program/scipaper_program/New()
/datum/computer_file/program/scipaper_program/on_install(datum/computer_file/source, obj/item/modular_computer/computer_installing)
. = ..()
paper_to_be = new
/datum/computer_file/program/scipaper_program/on_start(mob/living/user)
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !linked_techweb)
CONNECT_TO_RND_SERVER_ROUNDSTART(linked_techweb, computer)
@@ -0,0 +1,72 @@
/datum/computer_file/program/mafia
filename = "mafia"
filedesc = "Mafia"
program_icon_state = "mafia"
extended_desc = "A program that allows you to play the infamous Mafia game, straight from your Modular PC."
requires_ntnet = FALSE
size = 6
tgui_id = "NtosMafiaPanel"
program_icon = "user-secret"
alert_able = TRUE
/datum/computer_file/program/mafia/on_install(datum/computer_file/source, obj/item/modular_computer/computer_installing)
. = ..()
RegisterSignal(SSdcs, COMSIG_MAFIA_GAME_START, PROC_REF(on_game_start))
/datum/computer_file/program/mafia/Destroy(force)
var/datum/mafia_controller/game = GLOB.mafia_game
if(!game)
return
UnregisterSignal(game, COMSIG_MAFIA_GAME_END)
var/datum/mafia_role/pda_role = game.player_role_lookup[computer]
if(!pda_role)
return
game.send_message(span_notice("[pda_role.body] has deleted the game from their PDA, and therefore has left the game."))
pda_role.kill(game)
return ..()
/datum/computer_file/program/mafia/ui_static_data(mob/user)
var/list/data = list()
var/datum/mafia_controller/game = GLOB.mafia_game
if(!game)
game = create_mafia_game()
data += game.ui_static_data(computer)
return data
/datum/computer_file/program/mafia/ui_data(mob/user)
var/list/data = list()
var/datum/mafia_controller/game = GLOB.mafia_game
if(!game)
game = create_mafia_game()
data += game.ui_data(computer)
return data
/datum/computer_file/program/mafia/ui_assets(mob/user)
var/list/data = list()
var/datum/mafia_controller/game = GLOB.mafia_game
if(!game)
game = create_mafia_game()
data += game.ui_assets(user)
return data
/datum/computer_file/program/mafia/ui_act(mob/user, params, datum/tgui/ui, datum/ui_state/state)
var/datum/mafia_controller/game = GLOB.mafia_game
if(!game)
game = create_mafia_game()
return game.ui_act(user, params, ui, state)
///Called when a game of Mafia starts, sets the ui header to the proper one.
/datum/computer_file/program/mafia/proc/on_game_start(datum/controller/subsystem/processing/dcs/source, datum/mafia_controller/game)
SIGNAL_HANDLER
RegisterSignal(game, COMSIG_MAFIA_GAME_END, PROC_REF(on_game_end))
ui_header = "mafia.gif"
if(game.player_role_lookup[computer])
alert_pending = TRUE
computer.alert_call(src, "Mafia game started!")
///Called when a game of Mafia ends, deletes its ui header.
/datum/computer_file/program/mafia/proc/on_game_end(datum/mafia_controller/game)
SIGNAL_HANDLER
UnregisterSignal(game, COMSIG_MAFIA_GAME_END)
ui_header = null
update_static_data_for_all_viewers()
@@ -7,19 +7,16 @@
size = 4
requires_ntnet = TRUE
available_on_ntnet = FALSE
ui_header = "downloader_finished.gif"
tgui_id = "NtosNetDownloader"
program_icon = "download"
var/datum/computer_file/program/downloaded_file = null
var/datum/computer_file/program/downloaded_file
var/hacked_download = FALSE
var/download_completion = FALSE //GQ of downloaded data.
var/download_netspeed = 0
var/downloaderror = ""
var/list/main_repo
var/list/antag_repo
var/list/show_categories = list(
var/static/list/show_categories = list(
PROGRAM_CATEGORY_CREW,
PROGRAM_CATEGORY_ENGI,
PROGRAM_CATEGORY_SCI,
@@ -27,10 +24,9 @@
PROGRAM_CATEGORY_MISC,
)
/datum/computer_file/program/ntnetdownload/on_start()
/datum/computer_file/program/ntnetdownload/kill_program(mob/user)
. = ..()
main_repo = SSmodular_computers.available_station_software
antag_repo = SSmodular_computers.available_antag_software
ui_header = null
/datum/computer_file/program/ntnetdownload/proc/begin_file_download(filename)
if(downloaded_file)
@@ -50,10 +46,10 @@
ui_header = "downloader_running.gif"
if(PRG in main_repo)
if(PRG in SSmodular_computers.available_station_software)
generate_network_log("Began downloading file [PRG.filename].[PRG.filetype] from NTNet Software Repository.")
hacked_download = FALSE
else if(PRG in antag_repo)
else if(PRG in SSmodular_computers.available_antag_software)
generate_network_log("Began downloading file **ENCRYPTED**.[PRG.filetype] from unspecified server.")
hacked_download = TRUE
else
@@ -68,7 +64,7 @@
generate_network_log("Aborted download of file [hacked_download ? "**ENCRYPTED**" : "[downloaded_file.filename].[downloaded_file.filetype]"].")
downloaded_file = null
download_completion = FALSE
ui_header = "downloader_finished.gif"
ui_header = null
/datum/computer_file/program/ntnetdownload/proc/complete_file_download()
if(!downloaded_file)
@@ -90,11 +86,11 @@
download_netspeed = 0
// Speed defines are found in misc.dm
switch(ntnet_status)
if(1)
if(NTNET_LOW_SIGNAL)
download_netspeed = NTNETSPEED_LOWSIGNAL
if(2)
if(NTNET_GOOD_SIGNAL)
download_netspeed = NTNETSPEED_HIGHSIGNAL
if(3)
if(NTNET_ETHERNET_SIGNAL)
download_netspeed = NTNETSPEED_ETHERNET
download_completion += download_netspeed
@@ -132,7 +128,7 @@
data["disk_used"] = computer.used_capacity
data["emagged"] = (computer.obj_flags & EMAGGED)
var/list/repo = antag_repo | main_repo
var/list/repo = SSmodular_computers.available_antag_software | SSmodular_computers.available_station_software
var/list/program_categories = list()
for(var/datum/computer_file/program/programs as anything in repo)
@@ -147,7 +143,7 @@
"installed" = !!computer.find_file_by_name(programs.filename),
"compatible" = check_compatibility(programs),
"size" = programs.size,
"access" = (computer.obj_flags & EMAGGED) && programs.available_on_syndinet ? TRUE : programs.can_run(user, transfer = TRUE, access = access),
"access" = programs.can_run(user, transfer = TRUE, access = access),
"verifiedsource" = programs.available_on_ntnet,
))
@@ -21,7 +21,7 @@
/// Sequence var for the id cache
var/id_cache_seq = 1
/datum/computer_file/program/science/on_start(mob/living/user)
/datum/computer_file/program/science/on_install(datum/computer_file/source, obj/item/modular_computer/computer_installing)
. = ..()
if(!CONFIG_GET(flag/no_default_techweb_link) && !stored_research)
CONNECT_TO_RND_SERVER_ROUNDSTART(stored_research, computer)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

+1
View File
@@ -4963,6 +4963,7 @@
#include "code\modules\modular_computers\file_system\programs\file_browser.dm"
#include "code\modules\modular_computers\file_system\programs\frontier.dm"
#include "code\modules\modular_computers\file_system\programs\jobmanagement.dm"
#include "code\modules\modular_computers\file_system\programs\mafia_ntos.dm"
#include "code\modules\modular_computers\file_system\programs\newscasterapp.dm"
#include "code\modules\modular_computers\file_system\programs\notepad.dm"
#include "code\modules\modular_computers\file_system\programs\nt_pay.dm"
+151 -69
View File
@@ -1,4 +1,5 @@
import { classes } from 'common/react';
import { decodeHtmlEntities } from 'common/string';
import { multiline } from 'common/string';
import { useBackend, useLocalState } from '../backend';
import { Box, Button, Collapsible, Flex, NoticeBox, Section, Stack, Tabs, TextArea } from '../components';
@@ -31,39 +32,58 @@ type LobbyData = {
status: string;
};
type MessageData = {
msg: string;
};
type MafiaData = {
players: PlayerInfo[];
lobbydata: LobbyData[];
messages: MessageData[];
user_notes: string;
roleinfo: RoleInfo;
phase: string;
turn: number;
timeleft: number;
is_observer: boolean;
all_roles: string[];
admin_controls: boolean;
};
export const MafiaPanel = (props, context) => {
export const MafiaPanelData = (props, context) => {
const { act, data } = useBackend<MafiaData>(context);
const { phase, roleinfo, admin_controls } = data;
const { phase, roleinfo, admin_controls, messages } = data;
const [mafia_tab, setMafiaMode] = useLocalState(
context,
'mafia_tab',
'Role list'
);
if (phase === 'No Game') {
return (
<Stack fill>
<Stack.Item grow={1}>
<Stack fill vertical>
<MafiaLobby />
<Stack grow>
<Stack.Item>{!!admin_controls && <MafiaAdmin />}</Stack.Item>
</Stack>
</Stack>
</Stack.Item>
</Stack>
);
}
return (
<Window
title="Mafia"
theme={roleinfo && roleinfo.role_theme}
width={650}
height={580}>
<Window.Content>
<Stack fill>
{!!roleinfo && (
<Stack.Item grow={1}>
<MafiaChat />
</Stack.Item>
)}
<Stack.Item grow={1}>
<Stack fill vertical>
{!roleinfo && (
<Stack.Item grow>
<MafiaLobby />
</Stack.Item>
)}
{!!roleinfo && (
<>
<Stack.Item>
@@ -76,65 +96,125 @@ export const MafiaPanel = (props, context) => {
)}
</>
)}
{!!admin_controls && <MafiaAdmin />}
<Stack grow>
<Stack.Item>{!!admin_controls && <MafiaAdmin />}</Stack.Item>
</Stack>
{phase !== 'No Game' && (
<Stack.Item grow>
<Stack grow fill>
<>
<Stack.Item grow>
<MafiaPlayers />
</Stack.Item>
<Stack.Item fluid grow>
<Stack.Item>
<Tabs fluid>
<Tabs.Tab
align="center"
selected={mafia_tab === 'Role list'}
onClick={() => setMafiaMode('Role list')}>
Role list
<Button
color="transparent"
icon="address-book"
tooltipPosition="bottom-start"
tooltip={multiline`
<Stack grow fill>
<>
<Stack.Item grow>
<MafiaPlayers />
</Stack.Item>
<Stack.Item fluid grow>
<Stack.Item>
<Tabs fluid>
<Tabs.Tab
align="center"
selected={mafia_tab === 'Role list'}
onClick={() => setMafiaMode('Role list')}>
Role list
<Button
color="transparent"
icon="address-book"
tooltipPosition="bottom-start"
tooltip={multiline`
This is the list of roles in the game. You can
press the question mark to get a quick blurb
about the role itself.`}
/>
</Tabs.Tab>
<Tabs.Tab
align="center"
selected={mafia_tab === 'Notes'}
onClick={() => setMafiaMode('Notes')}>
Notes
<Button
color="transparent"
icon="pencil"
tooltipPosition="bottom-start"
tooltip={multiline`
/>
</Tabs.Tab>
<Tabs.Tab
align="center"
selected={mafia_tab === 'Notes'}
onClick={() => setMafiaMode('Notes')}>
Notes
<Button
color="transparent"
icon="pencil"
tooltipPosition="bottom-start"
tooltip={multiline`
This is your notes, anything you want to write
can be saved for future reference. You can
also send it to chat with a button.`}
/>
</Tabs.Tab>
</Tabs>
</Stack.Item>
{mafia_tab === 'Role list' && <MafiaListOfRoles />}
{mafia_tab === 'Notes' && <MafiaNotesTab />}
/>
</Tabs.Tab>
</Tabs>
</Stack.Item>
</>
</Stack>
</Stack.Item>
{mafia_tab === 'Role list' && <MafiaListOfRoles />}
{mafia_tab === 'Notes' && <MafiaNotesTab />}
</Stack.Item>
</>
</Stack>
)}
</Stack>
</Stack.Item>
</Stack>
);
};
export const MafiaPanel = (props, context) => {
const { act, data } = useBackend<MafiaData>(context);
const { roleinfo } = data;
return (
<Window
title="Mafia"
theme={roleinfo && roleinfo.role_theme}
width={900}
height={600}>
<Window.Content>
<MafiaPanelData />
</Window.Content>
</Window>
);
};
const MafiaChat = (props, context) => {
const { act, data } = useBackend<MafiaData>(context);
const { messages } = data;
const [message_to_send, setMessagingBox] = useLocalState(context, 'Chat', '');
return (
<Stack vertical fill>
{!!messages && (
<>
{' '}
<Section fill scrollable title="Chat Logs">
{messages.map((message) => (
<Box key={message.msg}>{decodeHtmlEntities(message.msg)}</Box>
))}
</Section>
<TextArea
fluid
height="10%"
maxLength={300}
className="Section__title candystripe"
onChange={(e, value) => setMessagingBox(value)}
placeholder={'Type to chat'}
value={message_to_send}
/>
<Stack grow>
<Stack.Item grow fill>
<Button
color="bad"
fluid
content="Send to Chat"
textAlign="center"
tooltip="Sends your message to chat."
onClick={() => {
setMessagingBox('');
act('send_message_to_chat', { message: message_to_send });
}}
/>
</Stack.Item>
</Stack>
</>
)}
</Stack>
);
};
const MafiaLobby = (props, context) => {
const { act, data } = useBackend<MafiaData>(context);
const { lobbydata = [] } = data;
const { lobbydata = [], is_observer } = data;
const readyGhosts = lobbydata
? lobbydata.filter((player) => player.status === 'Ready')
: null;
@@ -173,18 +253,22 @@ const MafiaLobby = (props, context) => {
The lobby currently has {readyGhosts ? readyGhosts.length : '0'}/12
valid players signed up.
</NoticeBox>
<NoticeBox color="green" textAlign="center">
Players who sign up for Mafia while dead will be returned to their
bodies after the game finishes, allowing you to temporarily exit to play
a match.
</NoticeBox>
{!!is_observer && (
<NoticeBox color="green" textAlign="center">
Players who sign up for Mafia while dead will be returned to their
bodies after the game finishes, allowing you to temporarily exit to
play a match.
</NoticeBox>
)}
{lobbydata.map((lobbyist) => (
<Stack
key={lobbyist.name}
className="candystripe"
p={1}
align="baseline">
<Stack.Item grow>{lobbyist.name}</Stack.Item>
<Stack.Item grow>
{!is_observer ? 'Unknown Player' : lobbyist.name}
</Stack.Item>
<Stack.Item>Status:</Stack.Item>
<Stack.Item color={lobbyist.status === 'Ready' ? 'green' : 'red'}>
{lobbyist.status}
@@ -200,6 +284,7 @@ const MafiaRole = (props, context) => {
const { phase, turn, roleinfo, timeleft } = data;
return (
<Section
fill
title={phase + turn}
minHeight="100px"
maxHeight="50px"
@@ -341,22 +426,19 @@ const MafiaPlayers = (props, context) => {
const { players } = data;
return (
<Section fill scrollable title="Players">
<Flex direction="column">
<Flex direction="column" fill justify="space-around">
{players?.map((player) => (
<Flex.Item
height="30px"
className="Section__title candystripe"
key={player.ref}>
<Stack height="18px" align="center">
<Flex.Item className="Section__title candystripe" key={player.ref}>
<Stack align="center">
<Stack.Item grow color={!player.alive && 'red'}>
{player.name} {!player.alive && '(DEAD)'}
</Stack.Item>
<Stack.Item shrink={0}>
<Stack.Item>
{player.votes !== undefined &&
!!player.alive &&
`Votes: ${player.votes}`}
</Stack.Item>
<Stack.Item shrink={0} minWidth="42px" textAlign="center">
<Stack.Item minWidth="42px" textAlign="center">
{player.possible_actions?.map((action) => (
<Button
key={action.name}
@@ -0,0 +1,12 @@
import { MafiaPanelData } from './MafiaPanel';
import { NtosWindow } from '../layouts';
export const NtosMafiaPanel = (props, context) => {
return (
<NtosWindow width={900} height={600}>
<NtosWindow.Content>
<MafiaPanelData />
</NtosWindow.Content>
</NtosWindow>
);
};
+1 -2
View File
@@ -15,7 +15,6 @@ export const NtosWindow = (props, context) => {
const {
PC_device_theme,
PC_batteryicon,
PC_showbatteryicon,
PC_batterypercent,
PC_ntneticon,
PC_stationdate,
@@ -61,7 +60,7 @@ export const NtosWindow = (props, context) => {
/>
)}
</Box>
{!!(PC_showbatteryicon && PC_batteryicon) && (
{!!PC_batteryicon && (
<Box inline mr={1}>
<img
className="NtosHeader__icon"