1
0
Fork 0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2024-11-20 00:46:34 +00:00

Convert line separators from CRLF to LF (#499)

This commit is contained in:
Austin Traver 2023-02-26 12:14:03 -08:00 committed by GitHub
parent e0fec0039e
commit c3a36e78e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 1605 additions and 1605 deletions

View file

@ -1,149 +1,149 @@
name: Rust name: Rust
on: on:
push: push:
branches: [ main ] branches: [ main ]
pull_request: pull_request:
branches: [ main ] branches: [ main ]
workflow_dispatch: workflow_dispatch:
jobs: jobs:
checker: checker:
name: Check, Clippy, Tests name: Check, Clippy, Tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install minimal nightly rust - name: Install minimal nightly rust
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
profile: minimal profile: minimal
toolchain: nightly toolchain: nightly
components: rustfmt, clippy components: rustfmt, clippy
default: true default: true
target: x86_64-unknown-linux-gnu target: x86_64-unknown-linux-gnu
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
name: Rust Cache name: Rust Cache
with: with:
prefix-key: "checker" prefix-key: "checker"
- name: Clippy - name: Clippy
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
continue-on-error: false continue-on-error: false
with: with:
command: clippy command: clippy
args: --all-targets --all-features --target=x86_64-unknown-linux-gnu -- -D warnings args: --all-targets --all-features --target=x86_64-unknown-linux-gnu -- -D warnings
- name: TUI Test - name: TUI Test
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
continue-on-error: false continue-on-error: false
with: with:
working-directory: training_mod_tui working-directory: training_mod_tui
plugin: plugin:
name: Plugin NRO name: Plugin NRO
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: jugeeya/cargo-skyline:3.2.0-no-dkp image: jugeeya/cargo-skyline:3.2.0-no-dkp
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
name: Rust Cache name: Rust Cache
with: with:
prefix-key: "plugin" prefix-key: "plugin"
- name: Build release NRO - name: Build release NRO
id: build_release id: build_release
run: cargo-skyline skyline build --release run: cargo-skyline skyline build --release
env: env:
HOME: /root HOME: /root
- name: Upload plugin artifact - name: Upload plugin artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: plugin name: plugin
path: target/aarch64-skyline-switch/release/libtraining_modpack.nro path: target/aarch64-skyline-switch/release/libtraining_modpack.nro
plugin_outside_training_mode: plugin_outside_training_mode:
name: Plugin NRO (Outside Training Mode) name: Plugin NRO (Outside Training Mode)
if: github.ref == 'refs/heads/main' if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: jugeeya/cargo-skyline:3.2.0-no-dkp image: jugeeya/cargo-skyline:3.2.0-no-dkp
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
name: Rust Cache name: Rust Cache
with: with:
prefix-key: "plugin" prefix-key: "plugin"
- name: Build outside_training_mode NRO - name: Build outside_training_mode NRO
run: | run: |
cargo-skyline skyline build --release --features outside_training_mode cargo-skyline skyline build --release --features outside_training_mode
env: env:
HOME: /root HOME: /root
- name: Upload plugin (outside training mode) artifact - name: Upload plugin (outside training mode) artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: plugin_outside_training_mode name: plugin_outside_training_mode
path: target/aarch64-skyline-switch/release/libtraining_modpack.nro path: target/aarch64-skyline-switch/release/libtraining_modpack.nro
upload: upload:
name: Upload Beta Release name: Upload Beta Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' if: github.ref == 'refs/heads/main'
needs: needs:
- plugin - plugin
steps: steps:
- name: Download all artifacts - name: Download all artifacts
uses: actions/download-artifact@v2 uses: actions/download-artifact@v2
- name: Prepare zip - name: Prepare zip
id: prepare_zip id: prepare_zip
env: env:
SMASH_PLUGIN_DIR: atmosphere/contents/01006A800016E000/romfs/skyline/plugins SMASH_PLUGIN_DIR: atmosphere/contents/01006A800016E000/romfs/skyline/plugins
run: | run: |
mkdir -p ${{env.SMASH_PLUGIN_DIR}} mkdir -p ${{env.SMASH_PLUGIN_DIR}}
cp plugin/libtraining_modpack.nro ${{env.SMASH_PLUGIN_DIR}}/libtraining_modpack.nro cp plugin/libtraining_modpack.nro ${{env.SMASH_PLUGIN_DIR}}/libtraining_modpack.nro
wget https://github.com/ultimate-research/params-hook-plugin/releases/download/v13.0.1/libparam_hook.nro wget https://github.com/ultimate-research/params-hook-plugin/releases/download/v13.0.1/libparam_hook.nro
wget https://github.com/ultimate-research/nro-hook-plugin/releases/download/v0.4.0/libnro_hook.nro wget https://github.com/ultimate-research/nro-hook-plugin/releases/download/v0.4.0/libnro_hook.nro
wget https://github.com/jugeeya/nn-hid-hook/releases/download/beta/libnn_hid_hook.nro wget https://github.com/jugeeya/nn-hid-hook/releases/download/beta/libnn_hid_hook.nro
cp libparam_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libparam_hook.nro cp libparam_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libparam_hook.nro
cp libnro_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libnro_hook.nro cp libnro_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libnro_hook.nro
cp libnn_hid_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libnn_hid_hook.nro cp libnn_hid_hook.nro ${{env.SMASH_PLUGIN_DIR}}/libnn_hid_hook.nro
zip -r training_modpack_beta.zip atmosphere zip -r training_modpack_beta.zip atmosphere
- name: Delete Release - name: Delete Release
uses: dev-drprasad/delete-tag-and-release@v0.2.0 uses: dev-drprasad/delete-tag-and-release@v0.2.0
with: with:
tag_name: beta tag_name: beta
delete_release: true delete_release: true
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Update Release - name: Update Release
uses: meeDamian/github-release@2.0 uses: meeDamian/github-release@2.0
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
prerelease: true prerelease: true
allow_override: true allow_override: true
gzip: false gzip: false
tag: beta tag: beta
commitish: main commitish: main
name: beta name: beta
body: > body: >
Beta built off of the latest code in the repository. Beta built off of the latest code in the repository.
# Changelog # Changelog
You can find the changelog here: https://github.com/jugeeya/UltimateTrainingModpack#beta-changelog You can find the changelog here: https://github.com/jugeeya/UltimateTrainingModpack#beta-changelog
## Installation ## Installation
*For fuller instructions, please join the [Discord](https://discord.gg/xUZWJ5BWe7) and visit the #setup-and-download channel.* *For fuller instructions, please join the [Discord](https://discord.gg/xUZWJ5BWe7) and visit the #setup-and-download channel.*
- (*Console only*) Install Atmosphere to your hacked Switch. One great guide can be found at https://switch.homebrew.guide/ - (*Console only*) Install Atmosphere to your hacked Switch. One great guide can be found at https://switch.homebrew.guide/
- Place the **contents** of the `training_modpack_beta.zip` on the root of your SD card. This means that you first unzip the file, then place its folder on the SD card root. The `atmosphere` folder should be **merged** onto the root of your SD card. - Place the **contents** of the `training_modpack_beta.zip` on the root of your SD card. This means that you first unzip the file, then place its folder on the SD card root. The `atmosphere` folder should be **merged** onto the root of your SD card.
- *For Ryujinx*: Paste the `contents` folder inside `atmosphere` into `%AppData%/Ryujinx/mods/` - *For Ryujinx*: Paste the `contents` folder inside `atmosphere` into `%AppData%/Ryujinx/mods/`
- Download Skyline: https://github.com/skyline-dev/skyline/releases. Place the `exefs` folder from the zip into `atmosphere/contents/01006A800016E000` on your SD card. - Download Skyline: https://github.com/skyline-dev/skyline/releases. Place the `exefs` folder from the zip into `atmosphere/contents/01006A800016E000` on your SD card.
- *For Ryujinx*: Paste these files in `%AppData%/Ryujinx/mods/contents/01006a800016e000` - *For Ryujinx*: Paste these files in `%AppData%/Ryujinx/mods/contents/01006a800016e000`
files: > files: >
training_modpack_beta.zip training_modpack_beta.zip
- name: Upload zip as artifact - name: Upload zip as artifact
uses: actions/upload-artifact@v1 uses: actions/upload-artifact@v1
with: with:
name: full_build name: full_build
path: training_modpack_beta.zip path: training_modpack_beta.zip

View file

@ -1,2 +1,2 @@
pub use training_mod_consts::*; pub use training_mod_consts::*;

View file

@ -1,242 +1,242 @@
use std::ops::Neg; use std::ops::Neg;
use smash::app; use smash::app;
use smash::phx::{Hash40, Vector3f}; use smash::phx::{Hash40, Vector3f};
pub const RAYGUN_LENGTH: f32 = 8.0; pub const RAYGUN_LENGTH: f32 = 8.0;
pub const RAYGUN_HEIGHT: f32 = 6.0; pub const RAYGUN_HEIGHT: f32 = 6.0;
pub const RAYGUN_HORIZ_OFFSET: f32 = 2.0; pub const RAYGUN_HORIZ_OFFSET: f32 = 2.0;
/* /*
segment data list : {Z, Y, X, ZRot, Size} segment data list : {Z, Y, X, ZRot, Size}
segment labels : segment labels :
_ _
|_| from top to top left, clockwise: a->f + g mid + \|/ from top mid to top left, clockwise: h->m + --two half g's: n, o |_| from top to top left, clockwise: a->f + g mid + \|/ from top mid to top left, clockwise: h->m + --two half g's: n, o
|_| /|\ |_| /|\
*/ */
pub static SEGMENT_DICT: [[f32; 5]; 15] = [ pub static SEGMENT_DICT: [[f32; 5]; 15] = [
[0.0, RAYGUN_HEIGHT * 2.0, 0.0, 0.0, 0.25], // a [0.0, RAYGUN_HEIGHT * 2.0, 0.0, 0.0, 0.25], // a
[0.0, RAYGUN_HEIGHT, RAYGUN_LENGTH, 90.0, 0.25], // b [0.0, RAYGUN_HEIGHT, RAYGUN_LENGTH, 90.0, 0.25], // b
[0.0, 0.0, RAYGUN_LENGTH, 90.0, 0.25], // c [0.0, 0.0, RAYGUN_LENGTH, 90.0, 0.25], // c
[0.0, 0.0, 0.0, 0.0, 0.25], // d [0.0, 0.0, 0.0, 0.0, 0.25], // d
[0.0, 0.0, 0.0, 90.0, 0.25], // e [0.0, 0.0, 0.0, 90.0, 0.25], // e
[0.0, RAYGUN_HEIGHT, 0.0, 90.0, 0.25], // f [0.0, RAYGUN_HEIGHT, 0.0, 90.0, 0.25], // f
[0.0, RAYGUN_HEIGHT, 0.0, 0.0, 0.25], // g mid [0.0, RAYGUN_HEIGHT, 0.0, 0.0, 0.25], // g mid
[0.0, RAYGUN_HEIGHT, RAYGUN_LENGTH / 2.0, 90.0, 0.25], // h [0.0, RAYGUN_HEIGHT, RAYGUN_LENGTH / 2.0, 90.0, 0.25], // h
[0.0, RAYGUN_HEIGHT, RAYGUN_LENGTH / 2.0, 52.0, 0.2], // i [0.0, RAYGUN_HEIGHT, RAYGUN_LENGTH / 2.0, 52.0, 0.2], // i
[0.0, RAYGUN_HEIGHT, RAYGUN_LENGTH / 2.0, -52.0, 0.2], // j [0.0, RAYGUN_HEIGHT, RAYGUN_LENGTH / 2.0, -52.0, 0.2], // j
[0.0, 0.0, RAYGUN_LENGTH / 2.0, 90.0, 0.25], // k [0.0, 0.0, RAYGUN_LENGTH / 2.0, 90.0, 0.25], // k
[ [
0.0, 0.0,
RAYGUN_HEIGHT / 2.0, RAYGUN_HEIGHT / 2.0,
RAYGUN_LENGTH * 3.0 / 16.0, RAYGUN_LENGTH * 3.0 / 16.0,
52.0, 52.0,
0.2, 0.2,
], // l ], // l
[ [
0.0, 0.0,
RAYGUN_HEIGHT * 3.0 / 2.0, RAYGUN_HEIGHT * 3.0 / 2.0,
RAYGUN_LENGTH * 3.0 / 16.0, RAYGUN_LENGTH * 3.0 / 16.0,
-52.0, -52.0,
0.2, 0.2,
], // m ], // m
[0.0, RAYGUN_HEIGHT, 0.0, 0.0, 0.15], // n [0.0, RAYGUN_HEIGHT, 0.0, 0.0, 0.15], // n
[0.0, RAYGUN_HEIGHT, RAYGUN_LENGTH / 2.0, 0.0, 0.15], // o [0.0, RAYGUN_HEIGHT, RAYGUN_LENGTH / 2.0, 0.0, 0.15], // o
]; ];
/* /*
Segments making up each character, each index corresponding to: Segments making up each character, each index corresponding to:
'A' through 'Z', '0' through '9', ' ', '-', '+', '#' (where '#' is all segments) 'A' through 'Z', '0' through '9', ' ', '-', '+', '#' (where '#' is all segments)
*/ */
pub static ALPHABET: [&str; 40] = [ pub static ALPHABET: [&str; 40] = [
"abcefg", "abcefg",
"adefijn", "adefijn",
"adef", "adef",
"eflm", "eflm",
"adefn", "adefn",
"aefn", "aefn",
"acdefo", "acdefo",
"bcefg", "bcefg",
"adhk", "adhk",
"bcd", "bcd",
"efnij", "efnij",
"def", "def",
"bcefim", "bcefim",
"bcefjm", "bcefjm",
"abcdef", "abcdef",
"abefg", "abefg",
"abcdefj", "abcdefj",
"aefijn", "aefijn",
"acdfg", "acdfg",
"ahk", "ahk",
"bcdef", "bcdef",
"efil", "efil",
"bcefjl", "bcefjl",
"ijlm", "ijlm",
"ikm", "ikm",
"adil", "adil",
"abcdef", "abcdef",
"ef", "ef",
"abdeg", "abdeg",
"abcdg", "abcdg",
"bcfg", "bcfg",
"acdfg", "acdfg",
"acdefg", "acdefg",
"abc", "abc",
"abcdefg", "abcdefg",
"abcdfg", "abcdfg",
"", "",
"g", "g",
"ghk", "ghk",
"abcdefhijklmno", "abcdefhijklmno",
]; ];
// Each index is a segment's corresponding flipped segment, for when facing left // Each index is a segment's corresponding flipped segment, for when facing left
pub static SEGMENT_REV: [char; 15] = [ pub static SEGMENT_REV: [char; 15] = [
'a', 'f', 'e', 'd', 'c', 'b', 'g', 'h', 'm', 'l', 'k', 'j', 'i', 'o', 'n', 'a', 'f', 'e', 'd', 'c', 'b', 'g', 'h', 'm', 'l', 'k', 'j', 'i', 'o', 'n',
]; ];
fn show_segment( fn show_segment(
module_accessor: &mut app::BattleObjectModuleAccessor, module_accessor: &mut app::BattleObjectModuleAccessor,
z: f32, z: f32,
y: f32, y: f32,
x: f32, x: f32,
zrot: f32, zrot: f32,
size: f32, size: f32,
) { ) {
let pos = Vector3f { x, y, z }; let pos = Vector3f { x, y, z };
let rot = Vector3f { let rot = Vector3f {
x: 0.0, x: 0.0,
y: 90.0, y: 90.0,
z: zrot, z: zrot,
}; };
let random = Vector3f { let random = Vector3f {
x: 0.0, x: 0.0,
y: 0.0, y: 0.0,
z: 0.0, z: 0.0,
}; };
unsafe { unsafe {
app::lua_bind::EffectModule::req_on_joint( app::lua_bind::EffectModule::req_on_joint(
module_accessor, module_accessor,
Hash40::new("sys_raygun_bullet"), Hash40::new("sys_raygun_bullet"),
Hash40::new("top"), Hash40::new("top"),
&pos, &pos,
&rot, &rot,
size, size,
&random, &random,
&random, &random,
false, false,
0, 0,
0, 0,
0, 0,
); );
} }
} }
fn alphabet_index(to_print: char) -> i32 { fn alphabet_index(to_print: char) -> i32 {
match to_print { match to_print {
'A'..='Z' => to_print as i32 - 'A' as i32, 'A'..='Z' => to_print as i32 - 'A' as i32,
'0'..='9' => to_print as i32 - '0' as i32 + 'Z' as i32 - 'A' as i32 + 1, '0'..='9' => to_print as i32 - '0' as i32 + 'Z' as i32 - 'A' as i32 + 1,
' ' => 36, ' ' => 36,
'-' => 37, '-' => 37,
'+' => 38, '+' => 38,
'#' => 39, '#' => 39,
_ => -1, _ => -1,
} }
} }
fn print_char( fn print_char(
module_accessor: &mut app::BattleObjectModuleAccessor, module_accessor: &mut app::BattleObjectModuleAccessor,
to_print: char, to_print: char,
line_num: i32, line_num: i32,
horiz_offset: f32, horiz_offset: f32,
facing_left: i32, facing_left: i32,
) { ) {
let is_facing_left = facing_left == -1; let is_facing_left = facing_left == -1;
let x_direction = facing_left as f32; let x_direction = facing_left as f32;
let alph_index = alphabet_index(to_print); let alph_index = alphabet_index(to_print);
if !(0..40).contains(&alph_index) { if !(0..40).contains(&alph_index) {
return; return;
} }
let segment_str = ALPHABET[alph_index as usize]; let segment_str = ALPHABET[alph_index as usize];
let line_offset = 40.0 - ((line_num as f32) * 16.0); let line_offset = 40.0 - ((line_num as f32) * 16.0);
for segment_char in segment_str.chars() { for segment_char in segment_str.chars() {
let mut index = segment_char as i32 - 'a' as i32; let mut index = segment_char as i32 - 'a' as i32;
if is_facing_left { if is_facing_left {
index = SEGMENT_REV[index as usize] as i32 - 'a' as i32; index = SEGMENT_REV[index as usize] as i32 - 'a' as i32;
} }
let segment = SEGMENT_DICT[index as usize]; let segment = SEGMENT_DICT[index as usize];
const SIZE_MULT: f32 = 0.5; const SIZE_MULT: f32 = 0.5;
let x = ((segment[2] + horiz_offset) * SIZE_MULT) + (x_direction * 5.0); let x = ((segment[2] + horiz_offset) * SIZE_MULT) + (x_direction * 5.0);
let y = ((segment[1] + line_offset) * SIZE_MULT) + 5.0; let y = ((segment[1] + line_offset) * SIZE_MULT) + 5.0;
let z = segment[0] * SIZE_MULT; let z = segment[0] * SIZE_MULT;
let zrot = segment[3]; let zrot = segment[3];
let zrot = if is_facing_left { zrot.neg() } else { zrot }; let zrot = if is_facing_left { zrot.neg() } else { zrot };
let size = segment[4] * SIZE_MULT; let size = segment[4] * SIZE_MULT;
show_segment(module_accessor, z, y, x, zrot, size); show_segment(module_accessor, z, y, x, zrot, size);
} }
} }
pub fn print_string(module_accessor: &mut app::BattleObjectModuleAccessor, to_write: &str) { pub fn print_string(module_accessor: &mut app::BattleObjectModuleAccessor, to_write: &str) {
// Delete any previous strings // Delete any previous strings
unsafe { unsafe {
app::lua_bind::EffectModule::kill_kind( app::lua_bind::EffectModule::kill_kind(
module_accessor, module_accessor,
Hash40::new("sys_raygun_bullet"), Hash40::new("sys_raygun_bullet"),
false, false,
true, true,
); );
} }
let mut line_num = 0; let mut line_num = 0;
let mut horiz_offset = 0.0; let mut horiz_offset = 0.0;
let mut char_num = 0; let mut char_num = 0;
let facing_left = unsafe { app::lua_bind::PostureModule::lr(module_accessor) as i32 }; let facing_left = unsafe { app::lua_bind::PostureModule::lr(module_accessor) as i32 };
let facing_direction = facing_left as f32; let facing_direction = facing_left as f32;
if to_write.len() <= 8 && !to_write.contains('\n') { if to_write.len() <= 8 && !to_write.contains('\n') {
line_num = 1; line_num = 1;
} }
for curr_char in to_write.chars() { for curr_char in to_write.chars() {
if curr_char == '\n' { if curr_char == '\n' {
horiz_offset = 0.0; horiz_offset = 0.0;
char_num = 0; char_num = 0;
line_num += 1; line_num += 1;
continue; continue;
} }
print_char( print_char(
module_accessor, module_accessor,
curr_char.to_uppercase().collect::<Vec<_>>()[0], curr_char.to_uppercase().collect::<Vec<_>>()[0],
line_num, line_num,
horiz_offset, horiz_offset,
facing_left, facing_left,
); );
char_num += 1; char_num += 1;
// short characters // short characters
if curr_char == 'D' || curr_char == '1' { if curr_char == 'D' || curr_char == '1' {
horiz_offset += facing_direction * (RAYGUN_LENGTH / 2.0 + 3.0); horiz_offset += facing_direction * (RAYGUN_LENGTH / 2.0 + 3.0);
} else { } else {
horiz_offset += facing_direction * (RAYGUN_LENGTH + 3.0); horiz_offset += facing_direction * (RAYGUN_LENGTH + 3.0);
} }
if char_num > 8 { if char_num > 8 {
horiz_offset = 0.0; horiz_offset = 0.0;
char_num = 0; char_num = 0;
line_num += 1; line_num += 1;
} }
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -1,50 +1,50 @@
use smash::app::{self, lua_bind::*}; use smash::app::{self, lua_bind::*};
use smash::lib::lua_const::*; use smash::lib::lua_const::*;
use crate::common::*; use crate::common::*;
use crate::training::frame_counter; use crate::training::frame_counter;
use crate::training::ledge; use crate::training::ledge;
use crate::training::mash; use crate::training::mash;
use crate::training::sdi; use crate::training::sdi;
use crate::training::shield_tilt; use crate::training::shield_tilt;
use crate::training::throw; use crate::training::throw;
pub fn check_reset(module_accessor: &mut app::BattleObjectModuleAccessor) { pub fn check_reset(module_accessor: &mut app::BattleObjectModuleAccessor) {
if !is_operation_cpu(module_accessor) { if !is_operation_cpu(module_accessor) {
return; return;
} }
if !should_reset(module_accessor) { if !should_reset(module_accessor) {
return; return;
} }
on_reset(); on_reset();
} }
fn should_reset(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool { fn should_reset(module_accessor: &mut app::BattleObjectModuleAccessor) -> bool {
if !is_idle(module_accessor) { if !is_idle(module_accessor) {
return false; return false;
} }
let prev_status; let prev_status;
unsafe { unsafe {
prev_status = StatusModule::prev_status_kind(module_accessor, 0); prev_status = StatusModule::prev_status_kind(module_accessor, 0);
} }
// Only reset automatically on training mode reset // Only reset automatically on training mode reset
if prev_status != *FIGHTER_STATUS_KIND_NONE { if prev_status != *FIGHTER_STATUS_KIND_NONE {
return false; return false;
} }
true true
} }
pub fn on_reset() { pub fn on_reset() {
mash::full_reset(); mash::full_reset();
sdi::roll_direction(); sdi::roll_direction();
frame_counter::reset_all(); frame_counter::reset_all();
ledge::reset_ledge_delay(); ledge::reset_ledge_delay();
throw::reset_throw_delay(); throw::reset_throw_delay();
shield_tilt::roll_direction(); shield_tilt::roll_direction();
} }

View file

@ -1,155 +1,155 @@
use smash::app::{self, lua_bind::*}; use smash::app::{self, lua_bind::*};
use smash::lib::lua_const::*; use smash::lib::lua_const::*;
use crate::common::*; use crate::common::*;
use crate::common::consts::*; use crate::common::consts::*;
use crate::training::frame_counter; use crate::training::frame_counter;
use crate::training::mash; use crate::training::mash;
const NOT_SET: u32 = 9001; const NOT_SET: u32 = 9001;
static mut THROW_DELAY: u32 = NOT_SET; static mut THROW_DELAY: u32 = NOT_SET;
static mut THROW_DELAY_COUNTER: usize = 0; static mut THROW_DELAY_COUNTER: usize = 0;
static mut THROW_CASE: ThrowOption = ThrowOption::empty(); static mut THROW_CASE: ThrowOption = ThrowOption::empty();
static mut PUMMEL_DELAY: u32 = NOT_SET; static mut PUMMEL_DELAY: u32 = NOT_SET;
static mut PUMMEL_DELAY_COUNTER: usize = 0; static mut PUMMEL_DELAY_COUNTER: usize = 0;
pub fn init() { pub fn init() {
unsafe { unsafe {
THROW_DELAY_COUNTER = frame_counter::register_counter(); THROW_DELAY_COUNTER = frame_counter::register_counter();
PUMMEL_DELAY_COUNTER = frame_counter::register_counter(); PUMMEL_DELAY_COUNTER = frame_counter::register_counter();
} }
} }
// Rolling Throw Delays and Pummel Delays separately // Rolling Throw Delays and Pummel Delays separately
pub fn reset_throw_delay() { pub fn reset_throw_delay() {
unsafe { unsafe {
if THROW_DELAY != NOT_SET { if THROW_DELAY != NOT_SET {
THROW_DELAY = NOT_SET; THROW_DELAY = NOT_SET;
frame_counter::full_reset(THROW_DELAY_COUNTER); frame_counter::full_reset(THROW_DELAY_COUNTER);
} }
} }
} }
pub fn reset_pummel_delay() { pub fn reset_pummel_delay() {
unsafe { unsafe {
if PUMMEL_DELAY != NOT_SET { if PUMMEL_DELAY != NOT_SET {
PUMMEL_DELAY = NOT_SET; PUMMEL_DELAY = NOT_SET;
frame_counter::full_reset(PUMMEL_DELAY_COUNTER); frame_counter::full_reset(PUMMEL_DELAY_COUNTER);
} }
} }
} }
pub fn reset_throw_case() { pub fn reset_throw_case() {
unsafe { unsafe {
if THROW_CASE != ThrowOption::empty() { if THROW_CASE != ThrowOption::empty() {
// Don't roll another throw option if one is already selected // Don't roll another throw option if one is already selected
THROW_CASE = ThrowOption::empty(); THROW_CASE = ThrowOption::empty();
} }
} }
} }
fn roll_throw_delay() { fn roll_throw_delay() {
unsafe { unsafe {
if THROW_DELAY != NOT_SET { if THROW_DELAY != NOT_SET {
// Don't roll another throw delay if one is already selected // Don't roll another throw delay if one is already selected
return; return;
} }
THROW_DELAY = MENU.throw_delay.get_random().into_meddelay(); THROW_DELAY = MENU.throw_delay.get_random().into_meddelay();
} }
} }
fn roll_pummel_delay() { fn roll_pummel_delay() {
unsafe { unsafe {
if PUMMEL_DELAY != NOT_SET { if PUMMEL_DELAY != NOT_SET {
// Don't roll another pummel delay if one is already selected // Don't roll another pummel delay if one is already selected
return; return;
} }
PUMMEL_DELAY = MENU.pummel_delay.get_random().into_meddelay(); PUMMEL_DELAY = MENU.pummel_delay.get_random().into_meddelay();
} }
} }
fn roll_throw_case() { fn roll_throw_case() {
unsafe { unsafe {
// Don't re-roll if there is already a throw option selected // Don't re-roll if there is already a throw option selected
if THROW_CASE != ThrowOption::empty() { if THROW_CASE != ThrowOption::empty() {
return; return;
} }
THROW_CASE = MENU.throw_state.get_random(); THROW_CASE = MENU.throw_state.get_random();
} }
} }
pub unsafe fn get_command_flag_throw_direction( pub unsafe fn get_command_flag_throw_direction(
module_accessor: &mut app::BattleObjectModuleAccessor, module_accessor: &mut app::BattleObjectModuleAccessor,
) -> i32 { ) -> i32 {
if !is_operation_cpu(module_accessor) { if !is_operation_cpu(module_accessor) {
return 0; return 0;
} }
if StatusModule::status_kind(module_accessor) != *FIGHTER_STATUS_KIND_CATCH_WAIT if StatusModule::status_kind(module_accessor) != *FIGHTER_STATUS_KIND_CATCH_WAIT
&& StatusModule::status_kind(module_accessor) != *FIGHTER_STATUS_KIND_CATCH_PULL && StatusModule::status_kind(module_accessor) != *FIGHTER_STATUS_KIND_CATCH_PULL
&& StatusModule::status_kind(module_accessor) != *FIGHTER_STATUS_KIND_CATCH_ATTACK && StatusModule::status_kind(module_accessor) != *FIGHTER_STATUS_KIND_CATCH_ATTACK
{ {
// No longer holding character, so re-roll the throw case and reset the delay counter for next time // No longer holding character, so re-roll the throw case and reset the delay counter for next time
reset_throw_case(); reset_throw_case();
reset_throw_delay(); reset_throw_delay();
reset_pummel_delay(); reset_pummel_delay();
return 0; return 0;
} }
if !WorkModule::is_enable_transition_term( if !WorkModule::is_enable_transition_term(
// If you can't throw right now, don't bother // If you can't throw right now, don't bother
module_accessor, module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_THROW_HI, *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_THROW_HI,
) { ) {
return 0; return 0;
} }
roll_throw_delay(); roll_throw_delay();
roll_throw_case(); roll_throw_case();
roll_pummel_delay(); roll_pummel_delay();
if THROW_CASE == ThrowOption::NONE { if THROW_CASE == ThrowOption::NONE {
// Do nothing, but don't reroll the throw case. // Do nothing, but don't reroll the throw case.
return 0; return 0;
} }
if frame_counter::should_delay(THROW_DELAY, THROW_DELAY_COUNTER) { if frame_counter::should_delay(THROW_DELAY, THROW_DELAY_COUNTER) {
// Not yet time to perform the throw action // Not yet time to perform the throw action
if frame_counter::should_delay(PUMMEL_DELAY, PUMMEL_DELAY_COUNTER) { if frame_counter::should_delay(PUMMEL_DELAY, PUMMEL_DELAY_COUNTER) {
// And not yet time to pummel either, so don't do anything // And not yet time to pummel either, so don't do anything
return 0; return 0;
} }
// If no pummel delay is selected (default), then don't pummel // If no pummel delay is selected (default), then don't pummel
if MENU.pummel_delay == MedDelay::empty() { if MENU.pummel_delay == MedDelay::empty() {
return 0; return 0;
} }
// (this conditional would need to be changed to speed up pummelling) // (this conditional would need to be changed to speed up pummelling)
if StatusModule::status_kind(module_accessor) == *FIGHTER_STATUS_KIND_CATCH_WAIT { if StatusModule::status_kind(module_accessor) == *FIGHTER_STATUS_KIND_CATCH_WAIT {
let status = *FIGHTER_STATUS_KIND_CATCH_ATTACK; //.unwrap_or(0); let status = *FIGHTER_STATUS_KIND_CATCH_ATTACK; //.unwrap_or(0);
StatusModule::change_status_request_from_script(module_accessor, status, true); StatusModule::change_status_request_from_script(module_accessor, status, true);
} }
return 0; return 0;
} }
// If you can uthrow, then throw (since all throws should be possible at the same times) // If you can uthrow, then throw (since all throws should be possible at the same times)
if WorkModule::is_enable_transition_term( if WorkModule::is_enable_transition_term(
module_accessor, module_accessor,
*FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_THROW_HI, *FIGHTER_STATUS_TRANSITION_TERM_ID_CONT_THROW_HI,
) { ) {
let cmd = THROW_CASE.into_cmd().unwrap_or(0); let cmd = THROW_CASE.into_cmd().unwrap_or(0);
mash::buffer_menu_mash(); mash::buffer_menu_mash();
return cmd; return cmd;
} }
0 0
} }

View file

@ -1,22 +1,22 @@
[package] [package]
name = "training_mod_consts" name = "training_mod_consts"
version = "0.1.0" version = "0.1.0"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
bitflags = "1.2.1" bitflags = "1.2.1"
strum = "0.21.0" strum = "0.21.0"
strum_macros = "0.21.0" strum_macros = "0.21.0"
num = "0.4.0" num = "0.4.0"
num-derive = "0.3" num-derive = "0.3"
num-traits = "0.2" num-traits = "0.2"
paste = "1.0" paste = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_repr = "0.1.8" serde_repr = "0.1.8"
serde_json = "1" serde_json = "1"
bitflags_serde_shim = "0.2" bitflags_serde_shim = "0.2"
skyline_smash = { git = "https://github.com/ultimate-research/skyline-smash.git", optional = true } skyline_smash = { git = "https://github.com/ultimate-research/skyline-smash.git", optional = true }
[features] [features]
default = ["smash"] default = ["smash"]
smash = ["skyline_smash"] smash = ["skyline_smash"]

View file

@ -1,12 +1,12 @@
[package] [package]
name = "training_mod_metrics" name = "training_mod_metrics"
version = "0.1.0" version = "0.1.0"
edition = "2018" edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
datafusion = "5.0.0" datafusion = "5.0.0"
tokio = "1.11.0" tokio = "1.11.0"
plotters = "0.3.1" plotters = "0.3.1"
chrono = "0.4.19" chrono = "0.4.19"

View file

@ -1,144 +1,144 @@
use datafusion::prelude::*; use datafusion::prelude::*;
use datafusion::arrow::record_batch::RecordBatch; use datafusion::arrow::record_batch::RecordBatch;
use datafusion::datasource::json::NdJsonFile; use datafusion::datasource::json::NdJsonFile;
use datafusion::physical_plan::json::NdJsonReadOptions; use datafusion::physical_plan::json::NdJsonReadOptions;
use datafusion::arrow::datatypes::{Schema, Field, DataType}; use datafusion::arrow::datatypes::{Schema, Field, DataType};
use std::sync::Arc; use std::sync::Arc;
// export.json is relative to /event/ // export.json is relative to /event/
// cat export.json | jq -c '.SMASH_OPEN.device[][][]' > smash_open.json // cat export.json | jq -c '.SMASH_OPEN.device[][][]' > smash_open.json
#[derive(Debug)] #[derive(Debug)]
struct Event { struct Event {
device_id: String, device_id: String,
event_name: String, event_name: String,
event_time: i64, event_time: i64,
menu_settings: String, menu_settings: String,
mod_version: String, mod_version: String,
session_id: String, session_id: String,
smash_version: String, smash_version: String,
user_id: String user_id: String
} }
use chrono::{DateTime, NaiveDateTime, Utc}; use chrono::{DateTime, NaiveDateTime, Utc};
fn timestamp_secs_to_datetime(ts: i64) -> DateTime<Utc> { fn timestamp_secs_to_datetime(ts: i64) -> DateTime<Utc> {
DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(ts, 0), Utc) DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(ts, 0), Utc)
} }
use plotters::prelude::*; use plotters::prelude::*;
const OUT_FILE_NAME: &'static str = "boxplot.svg"; const OUT_FILE_NAME: &'static str = "boxplot.svg";
fn draw_chart(results: Vec<RecordBatch>) -> Result<(), Box<dyn std::error::Error>> { fn draw_chart(results: Vec<RecordBatch>) -> Result<(), Box<dyn std::error::Error>> {
let num_devices_idx = results[0].schema().column_with_name("num_devices").unwrap().0; let num_devices_idx = results[0].schema().column_with_name("num_devices").unwrap().0;
let num_sessions_idx = results[0].schema().column_with_name("num_sessions").unwrap().0; let num_sessions_idx = results[0].schema().column_with_name("num_sessions").unwrap().0;
let timestamps_idx = results[0].schema().column_with_name("date").unwrap().0; let timestamps_idx = results[0].schema().column_with_name("date").unwrap().0;
let num_devices = results[0].column(num_devices_idx).as_any() let num_devices = results[0].column(num_devices_idx).as_any()
.downcast_ref::<datafusion::arrow::array::UInt64Array>() .downcast_ref::<datafusion::arrow::array::UInt64Array>()
.expect("Failed to downcast").values(); .expect("Failed to downcast").values();
let num_sessions = results[0].column(num_sessions_idx).as_any() let num_sessions = results[0].column(num_sessions_idx).as_any()
.downcast_ref::<datafusion::arrow::array::UInt64Array>() .downcast_ref::<datafusion::arrow::array::UInt64Array>()
.expect("Failed to downcast").values(); .expect("Failed to downcast").values();
let timestamp_millis = results[0].column(timestamps_idx).as_any() let timestamp_millis = results[0].column(timestamps_idx).as_any()
.downcast_ref::<datafusion::arrow::array::TimestampMillisecondArray>() .downcast_ref::<datafusion::arrow::array::TimestampMillisecondArray>()
.expect("Failed to downcast").values(); .expect("Failed to downcast").values();
let device_data_points = num_devices.iter() let device_data_points = num_devices.iter()
.enumerate().map(|(i, x)| (timestamp_secs_to_datetime(timestamp_millis[i] / 1000), *x)); .enumerate().map(|(i, x)| (timestamp_secs_to_datetime(timestamp_millis[i] / 1000), *x));
let session_data_points = num_sessions.iter() let session_data_points = num_sessions.iter()
.enumerate().map(|(i, x)| (timestamp_secs_to_datetime(timestamp_millis[i] / 1000), *x)); .enumerate().map(|(i, x)| (timestamp_secs_to_datetime(timestamp_millis[i] / 1000), *x));
let root = SVGBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); let root = SVGBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area();
root.fill(&WHITE)?; root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root) let mut chart = ChartBuilder::on(&root)
.caption("Users and Sessions by Date", ("sans-serif", 50).into_font()) .caption("Users and Sessions by Date", ("sans-serif", 50).into_font())
.margin(5) .margin(5)
.x_label_area_size(30) .x_label_area_size(30)
.y_label_area_size(30) .y_label_area_size(30)
.build_cartesian_2d( .build_cartesian_2d(
(timestamp_secs_to_datetime(timestamp_millis[0] / 1000))..(timestamp_secs_to_datetime(*timestamp_millis.last().unwrap() / 1000)), (timestamp_secs_to_datetime(timestamp_millis[0] / 1000))..(timestamp_secs_to_datetime(*timestamp_millis.last().unwrap() / 1000)),
0..*num_sessions.iter().max().unwrap())?; 0..*num_sessions.iter().max().unwrap())?;
chart.configure_mesh().draw()?; chart.configure_mesh().draw()?;
chart chart
.draw_series(LineSeries::new( .draw_series(LineSeries::new(
device_data_points, device_data_points,
&RED, &RED,
))? ))?
.label("Unique Devices") .label("Unique Devices")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED)); .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
chart chart
.draw_series(LineSeries::new( .draw_series(LineSeries::new(
session_data_points, session_data_points,
&BLUE, &BLUE,
))? ))?
.label("Unique Sessions") .label("Unique Sessions")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE)); .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE));
chart chart
.configure_series_labels() .configure_series_labels()
.background_style(&WHITE.mix(0.8)) .background_style(&WHITE.mix(0.8))
.border_style(&BLACK) .border_style(&BLACK)
.draw()?; .draw()?;
Ok(()) Ok(())
} }
#[tokio::main] #[tokio::main]
async fn main() -> datafusion::error::Result<()> { async fn main() -> datafusion::error::Result<()> {
// let smash_open_table = NdJsonFile::try_new( // let smash_open_table = NdJsonFile::try_new(
// "smash_open.json", // "smash_open.json",
// NdJsonReadOptions{ // NdJsonReadOptions{
// schema: None, // schema: None,
// schema_infer_max_records: 1, // schema_infer_max_records: 1,
// file_extension: ".json", // file_extension: ".json",
// } // }
// ).unwrap(); // ).unwrap();
let menu_open_table = NdJsonFile::try_new( let menu_open_table = NdJsonFile::try_new(
"menu_open.json", "menu_open.json",
NdJsonReadOptions{ NdJsonReadOptions{
schema: Some(Arc::new(Schema::new(vec![ schema: Some(Arc::new(Schema::new(vec![
Field::new("device_id", DataType::Utf8, false), Field::new("device_id", DataType::Utf8, false),
Field::new("event_name", DataType::Utf8, false), Field::new("event_name", DataType::Utf8, false),
Field::new("event_time", DataType::Int64, false), Field::new("event_time", DataType::Int64, false),
Field::new("menu_settings", DataType::Utf8, false), Field::new("menu_settings", DataType::Utf8, false),
Field::new("session_id", DataType::Utf8, false), Field::new("session_id", DataType::Utf8, false),
Field::new("smash_version", DataType::Utf8, false), Field::new("smash_version", DataType::Utf8, false),
Field::new("mod_version", DataType::Utf8, false), Field::new("mod_version", DataType::Utf8, false),
Field::new("user_id", DataType::Utf8, false), Field::new("user_id", DataType::Utf8, false),
]))), ]))),
schema_infer_max_records: 0, schema_infer_max_records: 0,
file_extension: ".json", file_extension: ".json",
} }
).unwrap(); ).unwrap();
// // declare a new context. In spark API, this corresponds to a new spark SQLsession // // declare a new context. In spark API, this corresponds to a new spark SQLsession
let mut ctx = ExecutionContext::new(); let mut ctx = ExecutionContext::new();
// ctx.register_table("smash_open", Arc::new(smash_open_table))?; // ctx.register_table("smash_open", Arc::new(smash_open_table))?;
ctx.register_table("menu_open", Arc::new(menu_open_table))?; ctx.register_table("menu_open", Arc::new(menu_open_table))?;
// create a plan to run a SQL query // create a plan to run a SQL query
let df = ctx.sql( let df = ctx.sql(
"SELECT "SELECT
COUNT(DISTINCT device_id) num_devices, COUNT(DISTINCT device_id) num_devices,
COUNT(DISTINCT session_id) num_sessions, COUNT(DISTINCT session_id) num_sessions,
COUNT(*) num_events, COUNT(*) num_events,
TO_TIMESTAMP_MILLIS(DATE_TRUNC('day', CAST(event_time * 1000000 AS timestamp))) AS date FROM menu_open TO_TIMESTAMP_MILLIS(DATE_TRUNC('day', CAST(event_time * 1000000 AS timestamp))) AS date FROM menu_open
WHERE WHERE
-- after 09/01/2021 -- after 09/01/2021
event_time > 1630454400000 event_time > 1630454400000
-- before today -- before today
AND CAST(event_time * 1000000 AS timestamp) < NOW() AND CAST(event_time * 1000000 AS timestamp) < NOW()
GROUP BY date ORDER BY date" GROUP BY date ORDER BY date"
)?; )?;
let results: Vec<RecordBatch> = df.collect().await?; let results: Vec<RecordBatch> = df.collect().await?;
// use datafusion::arrow::util::pretty::pretty_format_batches; // use datafusion::arrow::util::pretty::pretty_format_batches;
// println!("{}", pretty_format_batches(&results)?); // println!("{}", pretty_format_batches(&results)?);
draw_chart(results).unwrap(); draw_chart(results).unwrap();
Ok(()) Ok(())
} }

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module type="RUST_MODULE" version="4"> <module type="RUST_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true"> <component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output /> <exclude-output />
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
</module> </module>