Skip to content

Commit

Permalink
Add more events
Browse files Browse the repository at this point in the history
  • Loading branch information
thecodewarrior committed Dec 6, 2020
1 parent ffa98d8 commit e1616e1
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 22 deletions.
63 changes: 53 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ Launching and using SwiftSplit is fairly simple, with only three broad steps.
5. Click "Connect to Server" in LiveSplit One and paste that URL
- Note: navigating away from the timer screen may make the server button say it isn't connected any more. This is a
bug. You can check that it's still connected with the "LiveSplit clients" field in SwiftSplit, which should read
"1". If that field reads "0", you need to connect. If it reads "2" or higher then you've connected multiple times
and will need to save your splits and reload LiveSplit One, otherwise each split will count multiple times.
"1". If that field reads "0", you need to connect. If it reads "2" or higher then you will need to save your splits
and reload the LiveSplit One tab, otherwise each split will trigger multiple times.

### Loading the Run
6. Load up your splits in LiveSplit One
Expand Down Expand Up @@ -66,16 +66,59 @@ Here's an example for Old Site Any%:
}
```

The currently defined events are (`<...>` indicates a fill-in parameter):
- `start chapter <n>` - Triggered when the specified chapter number is started
- `reset chapter` - Triggered when the current chapter is reset (either by restarting the chapter or exiting to the map)
- `complete chapter <n>` - Triggered when the specified chapter number is completed
- `<from screen> > <to screen>` - Triggered when transitioning between two screens (you can find the screen IDS by
looking at the `Level: Name:` when connected to Celeste, or by enabling debug and hovering over the screen in the map
editor.
## Events
Events are triggered when SwiftSplit observes a change in the game state, which is checked 10 times every second. A
single state change frequently causes multiple events, generally with differing levels of specificity.

Note that the *exact* text is important. Spaces and capitalization have to match, with a couple additions:
Note that the *exact* text of an event is important. Spaces and capitalization have to match, with a couple additions:
- Inserting an exclamation point (`!`) at the beginning of an event will cause that event to not trigger a split. This
can be useful when your route passes between two screens multiple times but you only want one split.
- Anything after a ` ##` (*exactly* one space and two pound signs) will be trimmed off. This can be useful for
explaining events.

SwiftSplit has an "Event Stream" panel that displays events as they are triggered, which can be useful when creating
route files. (You can copy the text out of the panel to paste directly into the route file too).

### Chapter start/end events
- `reset chapter` - Triggered when any chapter is reset (either by restarting the chapter or exiting to the map)
- `start chapter <n>` - Triggered when chapter `<n>` is started
- `reset chapter <n>` - Triggered when chapter `<n>` is reset
- `complete chapter <n>` - Triggered when chapter `<n>` is completed
- **A-side specific:**
- `start a-side <n>` - Triggered when chapter `<n>`'s A-side is started
- `reset a-side <n>` - Triggered when chapter `<n>`'s A-side is reset
- `complete a-side <n>` - Triggered when chapter `<n>`'s A-side is completed
- **B-side specific:**
- `start b-side <n>` - Triggered when chapter `<n>`'s B-side is started
- `reset b-side <n>` - Triggered when chapter `<n>`'s B-side is reset
- `complete b-side <n>` - Triggered when chapter `<n>`'s B-side is completed
- **C-side specific:**
- `start c-side <n>` - Triggered when chapter `<n>`'s C-side is started
- `reset c-side <n>` - Triggered when chapter `<n>`'s C-side is reset
- `complete c-side <n>` - Triggered when chapter `<n>`'s C-side is completed

### Screen transition event
- `<from screen> > <to screen>` - Triggered when transitioning between two screens (you can find the screen IDs by
enabling debug and hovering over the screen in the map editor.)

### Collectable events
- **Cassettes:**
- `cassette` - Triggered when any cassette is collected
- `chapter <n> cassette` - Triggered when the cassette in the specified chapter is collected
- `<n> total cassettes` - Triggered when a cassette is collected. `<n>` is the total number of cassettes collected in
the current file
- **Heart Gems:**
- `heart` - Triggered when any heart gem is collected
- `chapter <n> heart` - Triggered when the heart gem in the specified chapter is collected
- `<n> total hearts` - Triggered when a heart gem is collected. `<n>` is the total number of heart gems collected in
the current file
- **Strawberries:**
- `strawberry` - Triggered when any strawberry is collected
- `<n> chapter strawberries` - Triggered when a total of `<n>` strawberries are collected in a chapter
- `<n> file strawberries` - Triggered when a total of `<n>` strawberries are collected in the file

### Some nuances regarding resets:

If the next expected event in the route is the same as the reset event, the route will take precedence and the run
won't be reset. However, if the first event in the route is then detected (though again route takes precedence), the
run will reset and start over.
6 changes: 4 additions & 2 deletions SwiftSplit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -386,14 +386,15 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = V2EPDFA9PV;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = SwiftSplit/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.thecodewarrior.SwiftSplit;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "SwiftSplit/SwiftSplit-Bridging-Header.h";
Expand All @@ -412,14 +413,15 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = V2EPDFA9PV;
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = SwiftSplit/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.thecodewarrior.SwiftSplit;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "SwiftSplit/SwiftSplit-Bridging-Header.h";
Expand Down
26 changes: 21 additions & 5 deletions SwiftSplit/CelesteScanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,12 @@ class CelesteScanner {
10b212968c7f0000 00000000 00000000 b83c632d01000000 f1aaaa1f f1bbbb1f 01010100 00000000 - placeholders
--------######## -------- ######## --------######## -------- ######## -------- ########
0 4 8 12 16 20 24 28 32 36
10e28b84a07f0000 00000000 00000000 b009150f01000000 ffffffff ffffffff 00000000 00000000 - AUTOSPLIT save state
10e28b84a07f0000 00000000 00000000 b009150f01000000 ffffffff ffffffff 00000000 00000000 - Fresh launch state
11ffeeddccbbaa11 f1cccc1f 01010000 11addeefbeadde11 f1dddd1f f1eeee1f f1ffff1f 00000000 - placeholders
--------######## -------- ######## --------######## -------- ######## -------- ########
40 44 48 52 56 60 64 68 72 76
0000000000000000 00000000 00000000 11addeefbeadde11 00000000 00000000 00000000 00000000 - AUTOSPLIT save state
0000000000000000 00000000 00000000 0000000000000000 00000000 00000000 00000000 00000000 - Fresh launch state
```
*/
struct AutoSplitterData: Equatable {
Expand Down Expand Up @@ -243,14 +243,21 @@ struct AutoSplitterData: Equatable {
}
}

enum ChapterMode {
case Normal
case BSide
case CSide
case Other(value: Int)
}

/**
A swift representation of the C# AutoSplitterInfo
*/
class AutoSplitterInfo {
let data: AutoSplitterData

let chapter: Int
let mode: Int
let mode: ChapterMode
let level: String
let timerActive: Bool
let chapterStarted: Bool
Expand All @@ -268,7 +275,7 @@ class AutoSplitterInfo {
self.data = AutoSplitterData()

self.chapter = 0
self.mode = 0
self.mode = .Normal
self.level = ""
self.timerActive = false
self.chapterStarted = false
Expand All @@ -287,7 +294,16 @@ class AutoSplitterInfo {
self.data = data

self.chapter = Int(data.chapter)
self.mode = Int(data.mode)
switch data.mode {
case 0:
self.mode = .Normal
case 1:
self.mode = .BSide
case 2:
self.mode = .CSide
default:
self.mode = .Other(value: Int(data.mode))
}
self.level = try AutoSplitterData.parseCSharpString(at: data.levelPointer, target: target)
self.timerActive = data.timerActive != 0
self.chapterStarted = data.chapterStarted != 0
Expand Down
42 changes: 39 additions & 3 deletions SwiftSplit/CelesteSplitter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,54 @@ class CelesteSplitter {

func getEvents(from old: AutoSplitterInfo, to new: AutoSplitterInfo) -> [String] {
var events: [String] = []
if new.level != old.level && old.level != "" && new.level != "" {
events.append("\(old.level) > \(new.level)")
}

// if we don't check `new.chapterComplete`, the summit credits trigger the autosplitter
if new.chapterStarted && !old.chapterStarted && !new.chapterComplete {
events.append("start chapter \(new.chapter)")
switch new.mode {
case .Normal: events.append("start a-side \(new.chapter)")
case .BSide: events.append("start b-side \(new.chapter)")
case .CSide: events.append("start c-side \(new.chapter)")
default: break
}
}
if !new.chapterStarted && old.chapterStarted && !old.chapterComplete {
events.append("reset chapter")
events.append("reset chapter \(old.chapter)")
switch new.mode {
case .Normal: events.append("reset a-side \(old.chapter)")
case .BSide: events.append("reset b-side \(old.chapter)")
case .CSide: events.append("reset c-side \(old.chapter)")
default: break
}
}
if new.chapterComplete && !old.chapterComplete {
events.append("complete chapter \(old.chapter)")
switch new.mode {
case .Normal: events.append("complete a-side \(old.chapter)")
case .BSide: events.append("complete b-side \(old.chapter)")
case .CSide: events.append("complete c-side \(old.chapter)")
default: break
}
}

if new.level != old.level && old.level != "" && new.level != "" {
events.append("\(old.level) > \(new.level)")
}
if new.chapterCassette && !old.chapterCassette {
events.append("cassette")
events.append("chapter \(new.chapter) cassette")
events.append("\(new.fileCassettes) total cassettes")
}
if new.chapterHeart && !old.chapterHeart {
events.append("heart")
events.append("chapter \(new.chapter) heart")
events.append("\(new.fileHearts) total hearts")
}
if new.chapterStrawberries > old.chapterStrawberries {
events.append("strawberry")
events.append("\(new.chapterStrawberries) chapter strawberries")
events.append("\(new.fileStrawberries) file strawberries")
}
return events
}
Expand Down
2 changes: 1 addition & 1 deletion SwiftSplit/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>1</string>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
Expand Down
4 changes: 3 additions & 1 deletion SwiftSplit/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ class ViewController: NSViewController, RouteBoxDelegate {

gameTimeLabel.stringValue = timeString

nextEventLabel.stringValue = splitter.routeIndex < routeConfig.route.count ? "\"\(routeConfig.route[splitter.routeIndex])\"" : "<none>"
nextEventLabel.stringValue = splitter.routeIndex < routeConfig.route.count ?
"\"\(routeConfig.route[splitter.routeIndex])\" (\(splitter.routeIndex + 1)/\(routeConfig.route.count))"
: "<none>"
}

func openRouteFile(url: URL) {
Expand Down

0 comments on commit e1616e1

Please sign in to comment.