-
Notifications
You must be signed in to change notification settings - Fork 522
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# About the pull request Tears out CM's autofire system and replaces it with TGMC's. Shouldn't affect anything on the front-end beyond an unreported bug, and maybe making lag a bit better. tgstation/TerraGov-Marine-Corps#6064 tgstation/TerraGov-Marine-Corps#6164 ## Regexes used: ### Fire delay F: `([^/])fire_delay = ([A-Z_1-90. *+-]+)` R: `$1set_fire_delay($2)` ### Burst delay F: `([^/])burst_delay = ([A-Z_1-90. *+-]+)` R: `$1set_burst_delay($2)` ### Burst amount F: `([^/])burst_amount = ([A-Z_1-90. *+-]+)` R: `$1set_burst_amount($2)` # Explain why it's good for the game Autofire becoming less terrible is one of the things necessary to be able to add autofire to more guns. # Changelog :cl: BraveMole, Zonespace fix: Smartgunners can no longer shoot their smartgun while aghosted balance: The Uzi and Mac-15 now have full-auto /:cl: --------- Co-authored-by: John Doe <[email protected]> Co-authored-by: harryob <[email protected]>
- Loading branch information
1 parent
0234c7d
commit ceac219
Showing
34 changed files
with
1,018 additions
and
674 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// Controls how many buckets should be kept, each representing a tick. Max is ten seconds, to have better perf. | ||
#define AUTOFIRE_BUCKET_LEN (world.fps * 10) | ||
/// Helper for getting the correct bucket | ||
#define AUTOFIRE_BUCKET_POS(next_fire) (((round((next_fire - SSautomatedfire.head_offset) / world.tick_lag) + 1) % AUTOFIRE_BUCKET_LEN) || AUTOFIRE_BUCKET_LEN) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/** | ||
* # Autofire Subsystem | ||
* | ||
* Maintains a timer-like system to handle autofiring. Much of this code is modeled | ||
* after or adapted from TGMC's runechat subsytem. | ||
* | ||
* Note that this has the same structure for storing and queueing shooter component as the timer subsystem does | ||
* for handling timers: the bucket_list is a list of autofire component, each of which are the head | ||
* of a linked list. Any given index in bucket_list could be null, representing an empty bucket. | ||
* | ||
* Doesn't support any event scheduled for more than 100 ticks in the future, as it has no secondary queue by design | ||
*/ | ||
SUBSYSTEM_DEF(automatedfire) | ||
name = "Automated fire" | ||
flags = SS_TICKER | SS_NO_INIT | ||
wait = 1 | ||
priority = SS_PRIORITY_AUTOFIRE | ||
|
||
/// world.time of the first entry in the bucket list, effectively the 'start time' of the current buckets | ||
var/head_offset = 0 | ||
/// Index of the first non-empty bucket | ||
var/practical_offset = 1 | ||
///How many buckets for every frame of world.fps | ||
var/bucket_resolution = 0 | ||
/// How many shooter are in the buckets | ||
var/shooter_count = 0 | ||
/// List of buckets, each bucket holds every shooter that has to shoot this byond tick | ||
var/list/bucket_list = list() | ||
/// Reference to the next shooter before we clean shooter.next | ||
var/datum/component/automatedfire/next_shooter | ||
|
||
/datum/controller/subsystem/automatedfire/PreInit() | ||
bucket_list.len = AUTOFIRE_BUCKET_LEN | ||
head_offset = world.time | ||
bucket_resolution = world.tick_lag | ||
|
||
/datum/controller/subsystem/automatedfire/stat_entry(msg = "ActShooters: [shooter_count]") | ||
return ..() | ||
|
||
/datum/controller/subsystem/automatedfire/fire(resumed = FALSE) | ||
// Check for when we need to loop the buckets, this occurs when | ||
// the head_offset is approaching AUTOFIRE_BUCKET_LEN ticks in the past | ||
if (practical_offset > AUTOFIRE_BUCKET_LEN) | ||
head_offset += TICKS2DS(AUTOFIRE_BUCKET_LEN) | ||
practical_offset = 1 | ||
resumed = FALSE | ||
|
||
// Check for when we have to reset buckets, typically from auto-reset | ||
if ((length(bucket_list) != AUTOFIRE_BUCKET_LEN) || (world.tick_lag != bucket_resolution)) | ||
reset_buckets() | ||
bucket_list = src.bucket_list | ||
resumed = FALSE | ||
|
||
// Store a reference to the 'working' shooter so that we can resume if the MC | ||
// has us stop mid-way through processing | ||
var/static/datum/component/automatedfire/shooter | ||
if (!resumed) | ||
shooter = null | ||
|
||
// Iterate through each bucket starting from the practical offset | ||
while (practical_offset <= AUTOFIRE_BUCKET_LEN && head_offset + ((practical_offset - 1) * world.tick_lag) <= world.time) | ||
if(!shooter) | ||
shooter = bucket_list[practical_offset] | ||
bucket_list[practical_offset] = null | ||
|
||
while (shooter) | ||
next_shooter = shooter.next | ||
INVOKE_ASYNC(shooter, TYPE_PROC_REF(/datum/component/automatedfire, process_shot)) | ||
|
||
SSautomatedfire.shooter_count-- | ||
shooter = next_shooter | ||
if (MC_TICK_CHECK) | ||
return | ||
|
||
// Move to the next bucket | ||
practical_offset++ | ||
|
||
/datum/controller/subsystem/automatedfire/Recover() | ||
bucket_list |= SSautomatedfire.bucket_list | ||
|
||
///In the event of a change of world.tick_lag, we refresh the size of the bucket and the bucket resolution | ||
/datum/controller/subsystem/automatedfire/proc/reset_buckets() | ||
bucket_list.len = AUTOFIRE_BUCKET_LEN | ||
head_offset = world.time | ||
bucket_resolution = world.tick_lag |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/datum/component/automatedfire | ||
///The owner of this component | ||
var/atom/shooter | ||
/// Contains the scheduled fire time, used for scheduling EOL | ||
var/next_fire | ||
/// Contains the reference to the next component in the bucket, used by autofire subsystem | ||
var/datum/component/automatedfire/next | ||
/// Contains the reference to the previous component in the bucket, used by autofire subsystem | ||
var/datum/component/automatedfire/prev | ||
|
||
|
||
/// schedule the shooter into the system, inserting it into the next fire queue | ||
/datum/component/automatedfire/proc/schedule_shot() | ||
//We move to another bucket, so we clean the reference from the former linked list | ||
next = null | ||
prev = null | ||
var/list/bucket_list = SSautomatedfire.bucket_list | ||
|
||
// Ensure the next_fire time is properly bound to avoid missing a scheduled event | ||
next_fire = max(CEILING(next_fire, world.tick_lag), world.time + world.tick_lag) | ||
|
||
// Get bucket position and a local reference to the datum var, it's faster to access this way | ||
var/bucket_pos = AUTOFIRE_BUCKET_POS(next_fire) | ||
|
||
// Get the bucket head for that bucket, increment the bucket count | ||
var/datum/component/automatedfire/bucket_head = bucket_list[bucket_pos] | ||
SSautomatedfire.shooter_count++ | ||
|
||
// If there is no existing head of this bucket, we can set this shooter to be that head | ||
if (!bucket_head) | ||
bucket_list[bucket_pos] = src | ||
return | ||
|
||
// Otherwise it's a simple insertion into the double-linked list | ||
if (bucket_head.next) | ||
next = bucket_head.next | ||
next.prev = src | ||
|
||
bucket_head.next = src | ||
prev = bucket_head | ||
|
||
//Something went wrong, probably a lag spike or something. To prevent infinite loops, we reschedule it to a another next fire | ||
if(prev == src) | ||
next_fire += 1 | ||
schedule_shot() | ||
|
||
///Handle the firing of the autofire component | ||
/datum/component/automatedfire/proc/process_shot() | ||
return |
Oops, something went wrong.