mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-09 16:14:13 +00:00
Merge branch 'refs/heads/master' into Bleeding-Edge
This commit is contained in:
79
README.md
79
README.md
@@ -4,54 +4,40 @@
|
||||
|
||||
---
|
||||
|
||||
### GETTING THE CODE
|
||||
The simplest way to obtain the code is using the github .zip feature.
|
||||
|
||||
Click [here](https://github.com/Baystation12/Baystation12/archive/master.zip) to get the latest code as a .zip file, then unzip it to wherever you want.
|
||||
|
||||
The more complicated and easier to update method is using git. You'll need to download git or some client from [here](http://git-scm.com/). When that's installed, right click in any folder and click on "Git Bash". When that opens, type in:
|
||||
|
||||
git clone git@github.com:Baystation12/Baystation12.git
|
||||
|
||||
(hint: hold down ctrl and press insert to paste into git bash)
|
||||
|
||||
This will take a while to download, but it provides an easier method for updating.
|
||||
|
||||
### INSTALLATION
|
||||
|
||||
First-time installation should be fairly straightforward. First, you'll need
|
||||
BYOND installed. You can get it from http://www.byond.com/. Once you've done
|
||||
that, extract the game files to wherever you want to keep them. This is a
|
||||
sourcecode-only release, so the next step is to compile the server files.
|
||||
Open baystation12.dme by double-clicking it, open the Build menu, and click
|
||||
compile. This'll take a little while, and if everything's done right you'll get
|
||||
a message like this:
|
||||
First-time installation should be fairly straightforward. First, you'll need BYOND installed. You can get it from [here](http://www.byond.com/).
|
||||
|
||||
This is a sourcecode-only release, so the next step is to compile the server files. Open baystation12.dme by double-clicking it, open the Build menu, and click compile. This'll take a little while, and if everything's done right you'll get a message like this:
|
||||
|
||||
saving baystation12.dmb (DEBUG mode)
|
||||
|
||||
baystation12.dmb - 0 errors, 0 warnings
|
||||
|
||||
If you see any errors or warnings, something has gone wrong - possibly a corrupt
|
||||
download or the files extracted wrong.
|
||||
If you see any errors or warnings, something has gone wrong - possibly a corrupt download or the files extracted wrong, or a code issue on the main repo. Ask on IRC.
|
||||
|
||||
It could be an issue with the current version of the code, either. Ask on IRC
|
||||
or wait for a fix.
|
||||
Once that's done, open up the config folder. You'll want to edit config.txt to set the probabilities for different gamemodes in Secret and to set your server location so that all your players don't get disconnected at the end of each round. It's recommended you don't turn on the gamemodes with probability 0, as they have various issues and aren't currently being tested, so they may have unknown and bizarre bugs.
|
||||
|
||||
Once that's done, open up the config folder. You'll want to edit config.txt to
|
||||
set the probabilities for different gamemodes in Secret and to set your server
|
||||
location so that all your players don't get disconnected at the end of each
|
||||
round. It's recommended you don't turn on the gamemodes with probability 0,
|
||||
except Extended, as they have various issues and aren't currently being tested,
|
||||
so they may have unknown and bizarre bugs. Extended is essentially no mode, and
|
||||
isn't in the Secret rotation by default as it's just not very fun.
|
||||
|
||||
You'll also want to edit admins.txt to remove the default admins and add your
|
||||
own. "Game Master" is the highest level of access, and the other recommended
|
||||
admin level for now is "Game Admin". The format is:
|
||||
You'll also want to edit admins.txt to remove the default admins and add your own. "Game Master" is the highest level of access, and the other recommended admin levels for now are "Game Admin" and "Moderator". The format is:
|
||||
|
||||
byondkey - Rank
|
||||
|
||||
where the BYOND key must be in lowercase and the admin rank must be properly
|
||||
capitalised. There are a bunch more admin ranks, but these two should be
|
||||
enough for most servers, assuming you have trustworthy admins.
|
||||
where the BYOND key must be in lowercase and the admin rank must be properly capitalised. There are a bunch more admin ranks, but these two should be enough for most servers, assuming you have trustworthy admins.
|
||||
|
||||
Additionally, you can set up moderators in moderators.txt, with this format:
|
||||
|
||||
byondkey
|
||||
|
||||
Moderators have access to player notes and a few other low-level commands.
|
||||
|
||||
Finally, to start the server, run Dream Daemon and enter the path to your
|
||||
compiled baystation12.dmb file. Make sure to set the port to the one you
|
||||
specified in the config.txt, and set the Security box to 'Trusted'. Then press
|
||||
GO and the server should start up and be ready to join.
|
||||
Finally, to start the server, run Dream Daemon and enter the path to your compiled baystation12.dmb file. Make sure to set the port to the one you specified in the config.txt, and set the Security box to 'Trusted'. Then press GO and the server should start up and be ready to join.
|
||||
|
||||
---
|
||||
|
||||
@@ -60,25 +46,24 @@ GO and the server should start up and be ready to join.
|
||||
To update an existing installation, first back up your /config and /data folders
|
||||
as these store your server configuration, player preferences and banlist.
|
||||
|
||||
Then, extract the new files (preferably into a clean directory, but updating in
|
||||
place should work fine), copy your /config and /data folders back into the new
|
||||
install, overwriting when prompted except if we've specified otherwise, and
|
||||
recompile the game. Once you start the server up again, you should be running
|
||||
the new version.
|
||||
If you used the zip method, you'll need to download the zip file again and unzip it somewhere else, and then copy the /config and /data folders over.
|
||||
|
||||
If you used the git method, you simply need to type this in to git bash:
|
||||
|
||||
git pull
|
||||
|
||||
When this completes, copy over your /data and /config folders again, just in case.
|
||||
|
||||
When you have done this, you'll need to recompile the code, but then it should work fine.
|
||||
|
||||
---
|
||||
|
||||
### SQL Setup
|
||||
|
||||
The SQL backend for the library and stats tracking requires a
|
||||
MySQL server. Your server details go in /config/dbconfig.txt, and the SQL
|
||||
schema is in /SQL/tgstation_schema.sql. More detailed setup instructions are
|
||||
coming soon, for now ask in our IRC channel.
|
||||
The SQL backend for the library and stats tracking requires a MySQL server. Your server details go in /config/dbconfig.txt, and the SQL schema is in /SQL/tgstation_schema.sql. More detailed setup instructions arecoming soon, for now ask in our IRC channel.
|
||||
|
||||
---
|
||||
|
||||
### IRC Bot Setup
|
||||
|
||||
Included in the repo is an IRC bot capable of relaying adminhelps to a specified
|
||||
IRC channel/server (thanks to Skibiliano). Instructions for bot setup are
|
||||
included in the /bot/ folder along with the bot/relay script itself.
|
||||
Included in the repo is an IRC bot capable of relaying adminhelps to a specified IRC channel/server (thanks to Skibiliano). Instructions for bot setup are included in the /bot/ folder along with the bot/relay script itself.
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
//is_blocked_turf(var/turf/T)
|
||||
usr << "\blue You finish placing the [src]." //Git Test
|
||||
|
||||
/obj/item/taperoll/police/afterattack(var/atom/A, mob/user as mob)
|
||||
/obj/item/taperoll/afterattack(var/atom/A, mob/user as mob)
|
||||
if (istype(A, /obj/machinery/door/airlock))
|
||||
var/turf/T = get_turf(A)
|
||||
var/obj/item/tape/P = new tape_type(T.x,T.y,T.z)
|
||||
|
||||
@@ -550,8 +550,16 @@ its easier to just keep the beam vertical.
|
||||
|
||||
/atom/Click(location,control,params)
|
||||
//world << "atom.Click() on [src] by [usr] : src.type is [src.type]"
|
||||
if(!istype(src,/obj/item/weapon/gun))
|
||||
var/acting_bad = 1 //Check for gun targeting code.
|
||||
if (istype(src,/obj/item/weapon/gun)) //Allow people to lower weapon
|
||||
acting_bad = 0
|
||||
if (istype(src, /turf) && istype(usr,/mob/living/carbon/human)) //Allow people to turn around
|
||||
var/mob/living/carbon/human/H = usr
|
||||
if (!H.equipped())
|
||||
acting_bad = 0
|
||||
if(acting_bad)
|
||||
usr.last_target_click = world.time
|
||||
|
||||
if(usr.client.buildmode)
|
||||
build_click(usr, usr.client.buildmode, location, control, params, src)
|
||||
return
|
||||
|
||||
@@ -104,15 +104,15 @@ var/list/radiochannels = list(
|
||||
"Medical" = 1355,
|
||||
"Engineering" = 1357,
|
||||
"Security" = 1359,
|
||||
"Response Team" = 1443,
|
||||
"Deathsquad" = 1441,
|
||||
"Syndicate" = 1213,
|
||||
"Supply" = 1347,
|
||||
)
|
||||
//depenging helpers
|
||||
var/list/DEPT_FREQS = list(1351,1355,1357,1359,1213,1441,1347)
|
||||
var/list/DEPT_FREQS = list(1351,1355,1357,1359,1213, 1443, 1441,1347)
|
||||
var/const/COMM_FREQ = 1353 //command, colored gold in chat window
|
||||
var/const/SYND_FREQ = 1213
|
||||
var/const/ERT_FREQ = 1439
|
||||
|
||||
#define TRANSMISSION_WIRE 0
|
||||
#define TRANSMISSION_RADIO 1
|
||||
|
||||
@@ -135,30 +135,7 @@
|
||||
if(!istype(location)) return//returns if loc is not simulated
|
||||
|
||||
var/datum/gas_mixture/environment = location.return_air()
|
||||
var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume
|
||||
|
||||
var/list/current_settings = TLV["pressure"]
|
||||
var/environment_pressure = environment.return_pressure()
|
||||
var/pressure_dangerlevel = get_danger_level(environment_pressure, current_settings)
|
||||
|
||||
current_settings = TLV["oxygen"]
|
||||
var/oxygen_dangerlevel = get_danger_level(environment.oxygen*partial_pressure, current_settings)
|
||||
|
||||
current_settings = TLV["carbon dioxide"]
|
||||
var/co2_dangerlevel = get_danger_level(environment.carbon_dioxide*partial_pressure, current_settings)
|
||||
|
||||
current_settings = TLV["plasma"]
|
||||
var/plasma_dangerlevel = get_danger_level(environment.toxins*partial_pressure, current_settings)
|
||||
|
||||
current_settings = TLV["other"]
|
||||
var/other_moles = 0.0
|
||||
for(var/datum/gas/G in environment.trace_gases)
|
||||
other_moles+=G.moles
|
||||
var/other_dangerlevel = get_danger_level(other_moles*partial_pressure, current_settings)
|
||||
|
||||
current_settings = TLV["temperature"]
|
||||
var/temperature_dangerlevel = get_danger_level(environment.temperature, current_settings)
|
||||
|
||||
var/temperature_dangerlevel = get_danger_level(environment.temperature, TLV["temperature"])
|
||||
//Handle temperature adjustment here.
|
||||
if(temperature_dangerlevel || regulating_temperature)
|
||||
//If it goes too far, we should adjust ourselves back before stopping.
|
||||
@@ -193,19 +170,14 @@
|
||||
visible_message("\The [src] clicks quietly as it stops [environment.temperature > target_temperature ? "cooling" : "heating"] the room.",\
|
||||
"You hear a click as a faint electronic humming stops.")
|
||||
|
||||
var/old_level = danger_level
|
||||
danger_level = overall_danger_level()
|
||||
|
||||
var/old_danger_level = danger_level
|
||||
danger_level = max(pressure_dangerlevel,
|
||||
oxygen_dangerlevel,
|
||||
co2_dangerlevel,
|
||||
plasma_dangerlevel,
|
||||
other_dangerlevel,
|
||||
temperature_dangerlevel)
|
||||
if (old_level != danger_level)
|
||||
refresh_danger_level()
|
||||
update_icon()
|
||||
|
||||
if (old_danger_level != danger_level)
|
||||
apply_danger_level(danger_level)
|
||||
|
||||
if (mode==AALARM_MODE_CYCLE && environment_pressure<ONE_ATMOSPHERE*0.05)
|
||||
if (mode==AALARM_MODE_CYCLE && environment.return_pressure()<ONE_ATMOSPHERE*0.05)
|
||||
mode=AALARM_MODE_FILL
|
||||
apply_mode()
|
||||
|
||||
@@ -225,6 +197,33 @@
|
||||
updateDialog()
|
||||
return
|
||||
|
||||
proc/overall_danger_level()
|
||||
var/turf/simulated/location = loc
|
||||
if(!istype(location)) return//returns if loc is not simulated
|
||||
|
||||
var/datum/gas_mixture/environment = location.return_air()
|
||||
|
||||
var/partial_pressure = R_IDEAL_GAS_EQUATION*environment.temperature/environment.volume
|
||||
var/environment_pressure = environment.return_pressure()
|
||||
var/other_moles = 0.0
|
||||
for(var/datum/gas/G in environment.trace_gases)
|
||||
other_moles+=G.moles
|
||||
|
||||
var/pressure_dangerlevel = get_danger_level(environment_pressure, TLV["pressure"])
|
||||
var/oxygen_dangerlevel = get_danger_level(environment.oxygen*partial_pressure, TLV["oxygen"])
|
||||
var/co2_dangerlevel = get_danger_level(environment.carbon_dioxide*partial_pressure, TLV["carbon dioxide"])
|
||||
var/plasma_dangerlevel = get_danger_level(environment.toxins*partial_pressure, TLV["plasma"])
|
||||
var/temperature_dangerlevel = get_danger_level(environment.temperature, TLV["temperature"])
|
||||
var/other_dangerlevel = get_danger_level(other_moles*partial_pressure, TLV["other"])
|
||||
|
||||
return max(
|
||||
pressure_dangerlevel,
|
||||
oxygen_dangerlevel,
|
||||
co2_dangerlevel,
|
||||
plasma_dangerlevel,
|
||||
other_dangerlevel,
|
||||
temperature_dangerlevel
|
||||
)
|
||||
|
||||
proc/master_is_operating()
|
||||
return alarm_area.master_air_alarm && !(alarm_area.master_air_alarm.stat & (NOPOWER|BROKEN))
|
||||
@@ -383,6 +382,15 @@
|
||||
|
||||
update_icon()
|
||||
|
||||
proc/refresh_danger_level()
|
||||
var/level = 0
|
||||
for (var/area/A in alarm_area.related)
|
||||
for (var/obj/machinery/alarm/AA in A)
|
||||
if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted)
|
||||
if (AA.danger_level > level)
|
||||
level = AA.danger_level
|
||||
apply_danger_level(level)
|
||||
|
||||
proc/air_doors_close(manual)
|
||||
var/area/A = get_area(src)
|
||||
if(!A.master.air_doors_activated)
|
||||
|
||||
@@ -18,14 +18,6 @@
|
||||
use_power = 0
|
||||
var/release_log = ""
|
||||
|
||||
/obj/machinery/portable_atmospherics/initialize()
|
||||
. = ..()
|
||||
spawn()
|
||||
var/obj/machinery/atmospherics/portables_connector/connector = locate() in loc
|
||||
if(connector)
|
||||
connected_port = connector
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/sleeping_agent
|
||||
name = "Canister: \[N2O\]"
|
||||
icon_state = "redws"
|
||||
|
||||
@@ -129,5 +129,5 @@
|
||||
if (!target)
|
||||
src.target = loc
|
||||
|
||||
/obj/machinery/meter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
return
|
||||
/obj/machinery/meter/turf/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
return
|
||||
|
||||
@@ -19,6 +19,14 @@
|
||||
|
||||
return 1
|
||||
|
||||
initialize()
|
||||
. = ..()
|
||||
spawn()
|
||||
var/obj/machinery/atmospherics/portables_connector/port = locate() in loc
|
||||
if(port)
|
||||
connect(port)
|
||||
update_icon()
|
||||
|
||||
process()
|
||||
if(!connected_port) //only react when pipe_network will ont it do it for you
|
||||
//Allow for reactions
|
||||
@@ -135,4 +143,4 @@
|
||||
user << "\blue Tank is empty!"
|
||||
return
|
||||
|
||||
return
|
||||
return
|
||||
|
||||
@@ -300,6 +300,7 @@
|
||||
if(src.patient && src.path.len == 0 && (get_dist(src,src.patient) > 1))
|
||||
spawn(0)
|
||||
src.path = AStar(src.loc, get_turf(src.patient), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30,id=botcard)
|
||||
if (!path) path = list()
|
||||
if(src.path.len == 0)
|
||||
src.oldpatient = src.patient
|
||||
src.patient = null
|
||||
|
||||
@@ -583,7 +583,7 @@ Auto Patrol: []"},
|
||||
// given an optional turf to avoid
|
||||
/obj/machinery/bot/secbot/proc/calc_path(var/turf/avoid = null)
|
||||
src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid)
|
||||
|
||||
if (!path) path = list()
|
||||
|
||||
// look for a criminal in view of the bot
|
||||
|
||||
|
||||
@@ -148,15 +148,6 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
signal.data["radio"], signal.data["message"],
|
||||
signal.data["name"], signal.data["job"],
|
||||
signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency)
|
||||
|
||||
if(connection.frequency == ERT_FREQ)
|
||||
Broadcast_Message(signal.data["connection"], signal.data["mob"],
|
||||
signal.data["vmask"], signal.data["vmessage"],
|
||||
signal.data["radio"], signal.data["message"],
|
||||
signal.data["name"], signal.data["job"],
|
||||
signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency)
|
||||
|
||||
|
||||
else
|
||||
if(intercept)
|
||||
Broadcast_Message(signal.data["connection"], signal.data["mob"],
|
||||
@@ -354,6 +345,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
// freq_text = "Mining"
|
||||
if(1347)
|
||||
freq_text = "Supply"
|
||||
if(1441)
|
||||
freq_text = "Death Squad"
|
||||
if(1443)
|
||||
freq_text = "Response Team"
|
||||
//There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,11 @@
|
||||
/obj/machinery/telecomms/relay/preset/centcom
|
||||
id = "Centcom Relay"
|
||||
hide = 1
|
||||
toggled = 0
|
||||
toggled = 1
|
||||
//anchored = 1
|
||||
//use_power = 0
|
||||
//idle_power_usage = 0
|
||||
heatgen = 0
|
||||
autolinkers = list("c_relay")
|
||||
|
||||
//HUB
|
||||
|
||||
@@ -51,7 +51,8 @@
|
||||
"/obj/item/device/flashlight",
|
||||
"/obj/item/weapon/cable_coil",
|
||||
"/obj/item/device/t_scanner",
|
||||
"/obj/item/device/analyzer")
|
||||
"/obj/item/device/analyzer",
|
||||
"/obj/item/taperoll/engineering")
|
||||
|
||||
|
||||
/obj/item/weapon/storage/belt/utility/full/New()
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
item_state = "contsolid"
|
||||
w_class = 2.0
|
||||
can_hold = list("/obj/item/weapon/reagent_containers/pill","/obj/item/weapon/dice")
|
||||
can_hold = list("/obj/item/weapon/reagent_containers/pill","/obj/item/weapon/dice","/obj/item/weapon/paper")
|
||||
allow_quick_gather = 1
|
||||
use_to_pickup = 1
|
||||
storage_slots = 14
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
//
|
||||
/datum/event/meteor_shower
|
||||
startWhen = 6
|
||||
startWhen = 5
|
||||
endWhen = 7
|
||||
var/next_meteor = 6
|
||||
var/waves = 1
|
||||
|
||||
@@ -114,6 +114,8 @@ emp_act
|
||||
if(!I || !user) return 0
|
||||
|
||||
var/target_zone = get_zone_with_miss_chance(user.zone_sel.selecting, src)
|
||||
if(user == src) // Attacking yourself can't miss
|
||||
target_zone = user.zone_sel.selecting
|
||||
if(!target_zone)
|
||||
visible_message("\red <B>[user] misses [src] with \the [I]!")
|
||||
return
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
//Round specific stuff like hud updates
|
||||
if(ticker && ticker.mode)
|
||||
switch(ticker.mode.name)
|
||||
if("sandbox")
|
||||
CanBuild()
|
||||
if("revolution")
|
||||
if((mind in ticker.mode.revolutionaries) || (src.mind in ticker.mode:head_revolutionaries))
|
||||
ticker.mode.update_rev_icons_added(src.mind)
|
||||
|
||||
@@ -178,6 +178,7 @@ var/list/ai_list = list()
|
||||
..()
|
||||
statpanel("Status")
|
||||
if (client.statpanel == "Status")
|
||||
stat(null, "Station Time: [worldtime2text()]")
|
||||
if(emergency_shuttle.online && emergency_shuttle.location < 2)
|
||||
var/timeleft = emergency_shuttle.timeleft()
|
||||
if (timeleft)
|
||||
|
||||
@@ -65,6 +65,10 @@
|
||||
Stat()
|
||||
..()
|
||||
|
||||
statpanel("Status")
|
||||
if (client.statpanel == "Status" && ticker)
|
||||
if (ticker.current_state != GAME_STATE_PREGAME)
|
||||
stat(null, "Station Time: [worldtime2text()]")
|
||||
statpanel("Lobby")
|
||||
if(client.statpanel=="Lobby" && ticker)
|
||||
if(ticker.hide_mode)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
icon_state = "mini-uzi"
|
||||
w_class = 3.0
|
||||
max_shells = 16
|
||||
caliber = " .45"
|
||||
caliber = ".45"
|
||||
origin_tech = "combat=5;materials=2;syndicate=8"
|
||||
ammo_type = "/obj/item/ammo_casing/c45"
|
||||
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
user.client.remove_gun_icons()
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gun/equipped(var/mob/user, var/slot)
|
||||
if (slot != slot_l_hand && slot != slot_r_hand)
|
||||
stop_aim()
|
||||
if (user.client)
|
||||
user.client.remove_gun_icons()
|
||||
return ..()
|
||||
|
||||
//Removes lock fro mall targets
|
||||
/obj/item/weapon/gun/proc/stop_aim()
|
||||
if(target)
|
||||
@@ -69,6 +76,7 @@
|
||||
if(!istype(M)) return
|
||||
if(src != M.equipped())
|
||||
stop_aim()
|
||||
return
|
||||
M.last_move_intent = world.time
|
||||
if(load_into_chamber())
|
||||
var/firing_check = in_chamber.check_fire(T,usr) //0 if it cannot hit them, 1 if it is capable of hitting, and 2 if a special check is preventing it from firing.
|
||||
@@ -155,7 +163,7 @@ mob/living/proc/Targeted(var/obj/item/weapon/gun/I) //Self explanitory.
|
||||
targeted_by += I
|
||||
I.lock_time = world.time + 20 //Target has 2 second to realize they're targeted and stop (or target the opponent).
|
||||
src << "((\red <b>Your character is being targeted. They have 2 seconds to stop any click or move actions.</b> \black While targeted, they may \
|
||||
drag and drop items in or into the map, speak, and click on interface buttons. Clicking on the map, their items \
|
||||
drag and drop items in or into the map, speak, and click on interface buttons. Clicking on the map objects (floors and walls are fine), their items \
|
||||
(other than a weapon to de-target), or moving will result in being fired upon. \red The aggressor may also fire manually, \
|
||||
so try not to get on their bad side.\black ))"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user