Merge branch 'master' of ssh://mnml.gg:40022/~/mnml
This commit is contained in:
commit
b8abd7f973
10
WORKLOG.md
10
WORKLOG.md
@ -46,9 +46,8 @@
|
|||||||
* eth adapter
|
* eth adapter
|
||||||
* pay for rerolls
|
* pay for rerolls
|
||||||
|
|
||||||
* remove test variants of skills
|
* warden
|
||||||
|
* set upkeep_at timestamp for games and instances
|
||||||
* itemise all skills and warn on some
|
|
||||||
|
|
||||||
## SOON
|
## SOON
|
||||||
|
|
||||||
@ -63,6 +62,11 @@
|
|||||||
* skills
|
* skills
|
||||||
* private fields for opponents
|
* private fields for opponents
|
||||||
|
|
||||||
|
* matchmaking
|
||||||
|
* elo
|
||||||
|
* password on MM game to prevent direct joins
|
||||||
|
|
||||||
|
|
||||||
* flavour text
|
* flavour text
|
||||||
* chat wheel trash talk
|
* chat wheel trash talk
|
||||||
* KO animations and trash talk
|
* KO animations and trash talk
|
||||||
|
|||||||
@ -18,14 +18,5 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
</body>
|
</body>
|
||||||
<!-- <script>
|
<script src="./index.js"></script>
|
||||||
// Check that service workers are registered
|
|
||||||
if ('serviceWorker' in navigator) {
|
|
||||||
// Use the window load event to keep the page load performant
|
|
||||||
window.addEventListener('load', () => {
|
|
||||||
navigator.serviceWorker.register('./service.worker.js');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
--> <script src="./index.js"></script>
|
|
||||||
</html>
|
</html>
|
||||||
@ -83,7 +83,7 @@ function GamePanel(props) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const zero = Date.parse(game.phase_end) - (1000 * 60);
|
const zero = Date.parse(game.phase_start);
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const end = Date.parse(game.phase_end);
|
const end = Date.parse(game.phase_end);
|
||||||
const timerPct = ((now - zero) / (end - zero) * 100);
|
const timerPct = ((now - zero) / (end - zero) * 100);
|
||||||
|
|||||||
@ -117,7 +117,9 @@ function InfoComponent(args) {
|
|||||||
|
|
||||||
function Combos() {
|
function Combos() {
|
||||||
if (!player) return false;
|
if (!player) return false;
|
||||||
if (!(combiner.every(u => u === null))) {
|
|
||||||
|
// show recipe for what's in combiner
|
||||||
|
if (combiner.some(u => u !== null)) {
|
||||||
const filteredCombos = itemInfo.combos
|
const filteredCombos = itemInfo.combos
|
||||||
.filter(combo => combiner.every(u => u === null
|
.filter(combo => combiner.every(u => u === null
|
||||||
|| combo.components.includes(player.vbox.bound[u])));
|
|| combo.components.includes(player.vbox.bound[u])));
|
||||||
@ -136,6 +138,7 @@ function InfoComponent(args) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!info) return false;
|
||||||
const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info));
|
const vboxCombos = itemInfo.combos.filter(c => c.components.includes(info));
|
||||||
if (vboxCombos.length > 6) return false;
|
if (vboxCombos.length > 6) return false;
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -64,7 +64,7 @@ function Instance(args) {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
// TIMER
|
// TIMER
|
||||||
const zero = Date.parse(instance.phase_end) - (1000 * 120);
|
const zero = Date.parse(instance.phase_start);
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const end = Date.parse(instance.phase_end);
|
const end = Date.parse(instance.phase_end);
|
||||||
const timerPct = ((now - zero) / (end - zero) * 100);
|
const timerPct = ((now - zero) / (end - zero) * 100);
|
||||||
|
|||||||
@ -64,8 +64,6 @@ function Equipment(props) {
|
|||||||
const isSkill = fullInfo && fullInfo.skill;
|
const isSkill = fullInfo && fullInfo.skill;
|
||||||
const isSpec = fullInfo && fullInfo.spec;
|
const isSpec = fullInfo && fullInfo.spec;
|
||||||
|
|
||||||
console.log('isSkill', isSkill, fullInfo);
|
|
||||||
|
|
||||||
function skillClick(e, i) {
|
function skillClick(e, i) {
|
||||||
if (itemUnequip && activeConstruct) return false;
|
if (itemUnequip && activeConstruct) return false;
|
||||||
// const value = vbox.bound[i];
|
// const value = vbox.bound[i];
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
TIMES: {
|
TIMES: {
|
||||||
RESOLUTION_TIME_MS: 1000,
|
|
||||||
START_SKILL: 700,
|
START_SKILL: 700,
|
||||||
END_SKILL: 700,
|
END_SKILL: 700,
|
||||||
POST_SKILL: 1000,
|
POST_SKILL: 1000,
|
||||||
|
|||||||
@ -162,13 +162,14 @@ impl Game {
|
|||||||
return self.finish();
|
return self.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.skill_phase_start()
|
self.skill_phase_start(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skill_phase_start(mut self) -> Game {
|
fn skill_phase_start(mut self, num_resolutions: usize) -> Game {
|
||||||
|
let phase_add_time_ms = 60000 + num_resolutions * 2500;
|
||||||
self.phase_start = Utc::now();
|
self.phase_start = Utc::now();
|
||||||
self.phase_end = Utc::now()
|
self.phase_end = Utc::now()
|
||||||
.checked_add_signed(Duration::seconds(60))
|
.checked_add_signed(Duration::milliseconds(phase_add_time_ms as i64))
|
||||||
.expect("could not set phase end");
|
.expect("could not set phase end");
|
||||||
|
|
||||||
for player in self.players.iter_mut() {
|
for player in self.players.iter_mut() {
|
||||||
@ -426,12 +427,14 @@ impl Game {
|
|||||||
// temp vec of this round's resolving skills
|
// temp vec of this round's resolving skills
|
||||||
// because need to check cooldown use before pushing them into the complete list
|
// because need to check cooldown use before pushing them into the complete list
|
||||||
let mut casts = vec![];
|
let mut casts = vec![];
|
||||||
|
let mut turn_events = 0;
|
||||||
|
|
||||||
while let Some(cast) = self.stack.pop() {
|
while let Some(cast) = self.stack.pop() {
|
||||||
// info!("{:} casts ", cast);
|
// info!("{:} casts ", cast);
|
||||||
|
|
||||||
let mut resolutions = resolution_steps(&cast, &mut self);
|
let mut resolutions = resolution_steps(&cast, &mut self);
|
||||||
resolutions.reverse();
|
resolutions.reverse();
|
||||||
|
turn_events += resolutions.len();
|
||||||
while let Some(resolution) = resolutions.pop() {
|
while let Some(resolution) = resolutions.pop() {
|
||||||
self.log_resolution(cast.speed, &resolution);
|
self.log_resolution(cast.speed, &resolution);
|
||||||
// the results go into the resolutions
|
// the results go into the resolutions
|
||||||
@ -455,7 +458,7 @@ impl Game {
|
|||||||
return self.finish()
|
return self.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.skill_phase_start()
|
self.skill_phase_start(turn_events)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn progress_durations(&mut self, resolved: &Vec<Cast>) -> &mut Game {
|
fn progress_durations(&mut self, resolved: &Vec<Cast>) -> &mut Game {
|
||||||
|
|||||||
@ -30,6 +30,12 @@ enum InstancePhase {
|
|||||||
Finished,
|
Finished,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
|
||||||
|
enum Format {
|
||||||
|
Standard,
|
||||||
|
RoundRobin,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||||
struct Round {
|
struct Round {
|
||||||
player_ids: Vec<Uuid>,
|
player_ids: Vec<Uuid>,
|
||||||
@ -40,15 +46,21 @@ struct Round {
|
|||||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
id: Uuid,
|
id: Uuid,
|
||||||
|
pub name: String,
|
||||||
|
|
||||||
players: Vec<Player>,
|
players: Vec<Player>,
|
||||||
phase: InstancePhase,
|
|
||||||
rounds: Vec<Vec<Round>>,
|
rounds: Vec<Vec<Round>>,
|
||||||
|
|
||||||
open: bool,
|
open: bool,
|
||||||
max_players: usize,
|
max_players: usize,
|
||||||
max_rounds: usize,
|
max_rounds: usize,
|
||||||
password: Option<String>,
|
password: Option<String>,
|
||||||
pub name: String,
|
|
||||||
|
phase: InstancePhase,
|
||||||
phase_end: DateTime<Utc>,
|
phase_end: DateTime<Utc>,
|
||||||
|
phase_start: DateTime<Utc>,
|
||||||
|
|
||||||
|
format: Format,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
@ -64,6 +76,9 @@ impl Instance {
|
|||||||
name: String::new(),
|
name: String::new(),
|
||||||
password: None,
|
password: None,
|
||||||
phase_end: Utc::now(),
|
phase_end: Utc::now(),
|
||||||
|
phase_start: Utc::now(),
|
||||||
|
|
||||||
|
format: Format::RoundRobin,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +93,10 @@ impl Instance {
|
|||||||
max_rounds: 1,
|
max_rounds: 1,
|
||||||
name: "Global Matchmaking".to_string(),
|
name: "Global Matchmaking".to_string(),
|
||||||
password: None,
|
password: None,
|
||||||
|
phase_start: Utc::now(),
|
||||||
phase_end: Utc::now(),
|
phase_end: Utc::now(),
|
||||||
|
|
||||||
|
format: Format::Standard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,12 +149,8 @@ impl Instance {
|
|||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_max_rounds(mut self, rounds: usize) -> Result<Instance, Error> {
|
fn set_format(mut self, format: Format) -> Result<Instance, Error> {
|
||||||
if rounds == 0 {
|
self.format = format;
|
||||||
return Err(err_msg("max rounds must be nonzero"));
|
|
||||||
}
|
|
||||||
|
|
||||||
self.max_rounds = rounds;
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,16 +287,17 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn next_round(&mut self) -> &mut Instance {
|
fn next_round(&mut self) -> &mut Instance {
|
||||||
self.phase = InstancePhase::InProgress;
|
if self.win_condition() {
|
||||||
self.phase_end = Utc::now()
|
|
||||||
.checked_add_signed(Duration::seconds(15000))
|
|
||||||
.expect("could not set phase end");
|
|
||||||
|
|
||||||
|
|
||||||
if self.rounds.len() >= self.max_rounds {
|
|
||||||
return self.finish();
|
return self.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.phase = InstancePhase::InProgress;
|
||||||
|
self.phase_start = Utc::now();
|
||||||
|
self.phase_end = Utc::now()
|
||||||
|
.checked_add_signed(Duration::seconds(120))
|
||||||
|
.expect("could not set phase end");
|
||||||
|
|
||||||
|
|
||||||
self.players.iter_mut().for_each(|p| {
|
self.players.iter_mut().for_each(|p| {
|
||||||
p.set_ready(false);
|
p.set_ready(false);
|
||||||
p.vbox.fill();
|
p.vbox.fill();
|
||||||
@ -294,6 +309,13 @@ impl Instance {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn win_condition(&self) -> bool {
|
||||||
|
match self.format {
|
||||||
|
Format::Standard => self.players.iter().any(|p| p.score.wins > 2),
|
||||||
|
Format::RoundRobin => self.rounds.len() == self.players.len() / 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn finish(&mut self) -> &mut Instance {
|
fn finish(&mut self) -> &mut Instance {
|
||||||
self.phase = InstancePhase::Finished;
|
self.phase = InstancePhase::Finished;
|
||||||
self
|
self
|
||||||
@ -732,7 +754,7 @@ mod tests {
|
|||||||
fn instance_pve_test() {
|
fn instance_pve_test() {
|
||||||
let mut instance = Instance::new()
|
let mut instance = Instance::new()
|
||||||
.set_max_players(16).expect("unable to set max players")
|
.set_max_players(16).expect("unable to set max players")
|
||||||
.set_max_rounds(2).expect("max rounds failure")
|
.set_format(Format::RoundRobin).expect("format failure")
|
||||||
.add_bots();
|
.add_bots();
|
||||||
|
|
||||||
let player_account = Uuid::new_v4();
|
let player_account = Uuid::new_v4();
|
||||||
@ -747,12 +769,12 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(instance.phase, InstancePhase::Finished);
|
assert_eq!(instance.phase, InstancePhase::Finished);
|
||||||
assert_eq!(instance.rounds[0].len(), 8);
|
assert_eq!(instance.rounds[0].len(), 8);
|
||||||
assert_eq!(instance.rounds.len(), 2);
|
assert_eq!(instance.rounds.len(), 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn instance_bot_vbox_test() {
|
fn instance_bot_vbox_test() {
|
||||||
let instance = Instance::new();
|
let _instance = Instance::new();
|
||||||
let player_account = Uuid::new_v4();
|
let player_account = Uuid::new_v4();
|
||||||
let constructs = instance_mobs(player_account);
|
let constructs = instance_mobs(player_account);
|
||||||
let _player = Player::new(player_account, &"test".to_string(), constructs).set_bot(true);
|
let _player = Player::new(player_account, &"test".to_string(), constructs).set_bot(true);
|
||||||
@ -802,8 +824,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn instance_upkeep_test() {
|
fn instance_upkeep_test() {
|
||||||
let mut instance = Instance::new()
|
let mut instance = Instance::new()
|
||||||
.set_max_players(2)
|
.set_max_players(2).expect("could not create instance")
|
||||||
.expect("could not create instance");
|
.set_format(Format::Standard).expect("format err");
|
||||||
|
|
||||||
let player_account = Uuid::new_v4();
|
let player_account = Uuid::new_v4();
|
||||||
let constructs = instance_mobs(player_account);
|
let constructs = instance_mobs(player_account);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user