mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-10-19 07:03:16 +00:00
add perma death option, make cessation nicer, fix spectator shields and cursors not appearing sometimes, make default settings transfer nicer
This commit is contained in:
parent
79e8f73d63
commit
2fc0e76f2c
10 changed files with 331 additions and 131 deletions
|
@ -99,6 +99,7 @@ local_health_desc_2 = There is a respawn mechanic.
|
||||||
Health-percent-lost-on-reviving = HP percent lost on reviving
|
Health-percent-lost-on-reviving = HP percent lost on reviving
|
||||||
global_hp_loss = Lose HP globally
|
global_hp_loss = Lose HP globally
|
||||||
no_material_damage = No material damage
|
no_material_damage = No material damage
|
||||||
|
perma_death = Perma death
|
||||||
shared_health_desc_1 = Health is shared, but scales with player count.
|
shared_health_desc_1 = Health is shared, but scales with player count.
|
||||||
shared_health_desc_2 = Percentage-based damage and full heals are adjusted.
|
shared_health_desc_2 = Percentage-based damage and full heals are adjusted.
|
||||||
shared_health_desc_3 = The original mode.
|
shared_health_desc_3 = The original mode.
|
||||||
|
|
|
@ -63,15 +63,39 @@ pub(crate) enum GameMode {
|
||||||
// MestariMina, // TODO later
|
// MestariMina, // TODO later
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Decode, Encode, Clone, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Decode, Encode, Clone, Serialize, Deserialize, PartialEq, Default)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct GameSettings {
|
pub struct GameSettings {
|
||||||
seed: u64,
|
seed: u64,
|
||||||
|
debug_mode: Option<bool>,
|
||||||
|
world_sync_version: Option<u32>,
|
||||||
|
player_tether: Option<bool>,
|
||||||
|
tether_length: Option<u32>,
|
||||||
|
use_constant_seed: bool,
|
||||||
|
item_dedup: Option<bool>,
|
||||||
|
enemy_hp_mult: Option<f32>,
|
||||||
|
world_sync_interval: Option<u32>,
|
||||||
|
game_mode: Option<GameMode>,
|
||||||
|
friendly_fire: Option<bool>,
|
||||||
|
friendly_fire_team: Option<i32>,
|
||||||
|
chunk_target: Option<u32>,
|
||||||
|
enemy_sync_interval: Option<u32>,
|
||||||
|
randomize_perks: Option<bool>,
|
||||||
|
progress: Vec<String>,
|
||||||
|
max_players: Option<u32>,
|
||||||
|
health_per_player: Option<u32>,
|
||||||
|
health_lost_on_revive: Option<u32>,
|
||||||
|
no_material_damage: Option<bool>,
|
||||||
|
global_hp_loss: Option<bool>,
|
||||||
|
perk_ban_list: Option<String>,
|
||||||
|
perma_death: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DefaultSettings {
|
||||||
debug_mode: bool,
|
debug_mode: bool,
|
||||||
world_sync_version: u32,
|
world_sync_version: u32,
|
||||||
player_tether: bool,
|
player_tether: bool,
|
||||||
tether_length: u32,
|
tether_length: u32,
|
||||||
use_constant_seed: bool,
|
|
||||||
item_dedup: bool,
|
item_dedup: bool,
|
||||||
enemy_hp_mult: f32,
|
enemy_hp_mult: f32,
|
||||||
world_sync_interval: u32,
|
world_sync_interval: u32,
|
||||||
|
@ -81,24 +105,22 @@ pub struct GameSettings {
|
||||||
chunk_target: u32,
|
chunk_target: u32,
|
||||||
enemy_sync_interval: u32,
|
enemy_sync_interval: u32,
|
||||||
randomize_perks: bool,
|
randomize_perks: bool,
|
||||||
progress: Vec<String>,
|
|
||||||
max_players: u32,
|
max_players: u32,
|
||||||
health_per_player: u32,
|
health_per_player: u32,
|
||||||
health_lost_on_revive: u32,
|
health_lost_on_revive: u32,
|
||||||
no_material_damage: bool,
|
no_material_damage: bool,
|
||||||
global_hp_loss: bool,
|
global_hp_loss: bool,
|
||||||
perk_ban_list: String,
|
perk_ban_list: String,
|
||||||
|
perma_death: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GameSettings {
|
impl Default for DefaultSettings {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
GameSettings {
|
DefaultSettings {
|
||||||
seed: 0,
|
|
||||||
debug_mode: false,
|
debug_mode: false,
|
||||||
world_sync_version: 2,
|
world_sync_version: 2,
|
||||||
player_tether: true,
|
player_tether: true,
|
||||||
tether_length: 2048,
|
tether_length: 2048,
|
||||||
use_constant_seed: false,
|
|
||||||
item_dedup: true,
|
item_dedup: true,
|
||||||
randomize_perks: true,
|
randomize_perks: true,
|
||||||
enemy_hp_mult: 1.0,
|
enemy_hp_mult: 1.0,
|
||||||
|
@ -108,13 +130,13 @@ impl Default for GameSettings {
|
||||||
friendly_fire_team: 0,
|
friendly_fire_team: 0,
|
||||||
chunk_target: 24,
|
chunk_target: 24,
|
||||||
enemy_sync_interval: 3,
|
enemy_sync_interval: 3,
|
||||||
progress: Vec::new(),
|
|
||||||
max_players: 250,
|
max_players: 250,
|
||||||
health_per_player: 100,
|
health_per_player: 100,
|
||||||
health_lost_on_revive: 0,
|
health_lost_on_revive: 0,
|
||||||
no_material_damage: false,
|
no_material_damage: false,
|
||||||
global_hp_loss: false,
|
global_hp_loss: false,
|
||||||
perk_ban_list: String::new(),
|
perk_ban_list: "GLOBAL_GORE,GLASS_CANNON,REVENGE_RATS,PLAGUE_RATS,VOMIT_RATS,CORDYCEPS,MOLD,FUNGAL_DISEASE,HOMUNCULUS,LUKKI_MINION".to_string(),
|
||||||
|
perma_death: false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -498,7 +520,7 @@ impl App {
|
||||||
let peer = net::steam_networking::SteamPeer::new_host(
|
let peer = net::steam_networking::SteamPeer::new_host(
|
||||||
steamworks::LobbyType::Private,
|
steamworks::LobbyType::Private,
|
||||||
self.steam_state.as_ref().unwrap().client.clone(),
|
self.steam_state.as_ref().unwrap().client.clone(),
|
||||||
self.app_saved_state.game_settings.max_players,
|
self.app_saved_state.game_settings.max_players.unwrap_or(DefaultSettings::default().max_players),
|
||||||
);
|
);
|
||||||
let netman = net::NetManager::new(PeerVariant::Steam(peer), self.get_netman_init());
|
let netman = net::NetManager::new(PeerVariant::Steam(peer), self.get_netman_init());
|
||||||
self.set_netman_settings(&netman);
|
self.set_netman_settings(&netman);
|
||||||
|
@ -720,56 +742,93 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_game_settings(&mut self, ui: &mut Ui, show_local: bool) {
|
fn show_game_settings(&mut self, ui: &mut Ui, show_local: bool) {
|
||||||
|
let def = DefaultSettings::default();
|
||||||
heading_with_underline(ui, tr("connect_settings"));
|
heading_with_underline(ui, tr("connect_settings"));
|
||||||
let game_settings = &mut self.app_saved_state.game_settings;
|
let game_settings = &mut self.app_saved_state.game_settings;
|
||||||
ui.label(tr("Game-mode"));
|
{
|
||||||
ui.radio_value(
|
let mut temp = game_settings.game_mode.unwrap_or(def.game_mode);
|
||||||
&mut game_settings.game_mode,
|
ui.label(tr("Game-mode"));
|
||||||
GameMode::SharedHealth,
|
if ui.radio_value(
|
||||||
tr("Shared-health"),
|
&mut temp,
|
||||||
);
|
GameMode::SharedHealth,
|
||||||
ui.radio_value(
|
tr("Shared-health"),
|
||||||
&mut game_settings.game_mode,
|
).changed() || ui.radio_value(
|
||||||
GameMode::LocalHealth,
|
&mut temp,
|
||||||
tr("Local-health"),
|
GameMode::LocalHealth,
|
||||||
);
|
tr("Local-health"),
|
||||||
|
).changed() {
|
||||||
|
game_settings.game_mode = Some(temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ui.scope(|ui| {
|
ui.scope(|ui| {
|
||||||
ui.set_height(100.0);
|
ui.set_height(100.0);
|
||||||
|
|
||||||
match game_settings.game_mode {
|
match game_settings.game_mode.unwrap_or(def.game_mode) {
|
||||||
GameMode::SharedHealth => {
|
GameMode::SharedHealth => {
|
||||||
ui.label(tr("shared_health_desc_1"));
|
ui.label(tr("shared_health_desc_1"));
|
||||||
ui.label(tr("shared_health_desc_2"));
|
ui.label(tr("shared_health_desc_2"));
|
||||||
ui.label(tr("shared_health_desc_3"));
|
ui.label(tr("shared_health_desc_3"));
|
||||||
ui.add_space(5.0);
|
ui.add_space(5.0);
|
||||||
ui.label(tr("Health-per-player"));
|
ui.label(tr("Health-per-player"));
|
||||||
ui.add(Slider::new(&mut game_settings.health_per_player, 0..=100));
|
let mut temp = game_settings.health_per_player.unwrap_or(def.health_per_player);
|
||||||
|
if ui.add(Slider::new(&mut temp, 0..=100)).changed() {
|
||||||
|
game_settings.health_per_player = Some(temp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GameMode::LocalHealth => {
|
GameMode::LocalHealth => {
|
||||||
ui.label(tr("local_health_desc_1"));
|
ui.label(tr("local_health_desc_1"));
|
||||||
ui.label(tr("local_health_desc_2"));
|
ui.label(tr("local_health_desc_2"));
|
||||||
ui.add_space(5.0);
|
ui.add_space(5.0);
|
||||||
ui.label(tr("Health-percent-lost-on-reviving"));
|
ui.label(tr("Health-percent-lost-on-reviving"));
|
||||||
ui.add(Slider::new(
|
{
|
||||||
&mut game_settings.health_lost_on_revive,
|
let mut temp = game_settings.health_lost_on_revive.unwrap_or(def.health_lost_on_revive);
|
||||||
0..=100,
|
if ui.add(Slider::new(
|
||||||
));
|
&mut temp,
|
||||||
ui.checkbox(&mut game_settings.global_hp_loss, tr("global_hp_loss"));
|
0..=100,
|
||||||
ui.checkbox(
|
)).changed() {
|
||||||
&mut game_settings.no_material_damage,
|
game_settings.health_lost_on_revive = Some(temp)
|
||||||
tr("no_material_damage"),
|
}
|
||||||
);
|
}
|
||||||
|
{
|
||||||
|
let mut temp = game_settings.global_hp_loss.unwrap_or(def.global_hp_loss);
|
||||||
|
if ui.checkbox(&mut temp, tr("global_hp_loss")).changed() {
|
||||||
|
game_settings.global_hp_loss = Some(temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut temp = game_settings.no_material_damage.unwrap_or(def.no_material_damage);
|
||||||
|
if ui.checkbox(
|
||||||
|
&mut temp,
|
||||||
|
tr("no_material_damage"),
|
||||||
|
).changed() {
|
||||||
|
game_settings.no_material_damage = Some(temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui.add_space(1.0);
|
||||||
|
{
|
||||||
|
let mut temp = game_settings.perma_death.unwrap_or(def.perma_death);
|
||||||
|
if ui.checkbox(
|
||||||
|
&mut temp,
|
||||||
|
tr("perma_death"),
|
||||||
|
).changed() {
|
||||||
|
game_settings.perma_death = Some(temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
ui.label(tr("connect_settings_debug"));
|
ui.label(tr("connect_settings_debug"));
|
||||||
ui.checkbox(
|
{
|
||||||
&mut game_settings.debug_mode,
|
let mut temp = game_settings.debug_mode.unwrap_or(def.debug_mode);
|
||||||
tr("connect_settings_debug_en"),
|
if ui.checkbox(
|
||||||
);
|
&mut temp,
|
||||||
|
tr("connect_settings_debug_en"),
|
||||||
|
).changed() {
|
||||||
|
game_settings.debug_mode = Some(temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
ui.checkbox(
|
ui.checkbox(
|
||||||
&mut game_settings.use_constant_seed,
|
&mut game_settings.use_constant_seed,
|
||||||
tr("connect_settings_debug_fixed_seed"),
|
tr("connect_settings_debug_fixed_seed"),
|
||||||
|
@ -780,40 +839,87 @@ impl App {
|
||||||
});
|
});
|
||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
ui.label(tr("connect_settings_max_players"));
|
ui.label(tr("connect_settings_max_players"));
|
||||||
ui.add(Slider::new(&mut game_settings.max_players, 2..=250));
|
{
|
||||||
|
let mut temp = game_settings.max_players.unwrap_or(def.max_players);
|
||||||
|
if ui.add(Slider::new(&mut temp, 2..=250)).changed()
|
||||||
|
{
|
||||||
|
game_settings.max_players = Some(temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
ui.label(tr("Amount-of-chunks-host-has-loaded-at-once-synced-enemies-and-physics-objects-need-to-be-loaded-in-by-host-to-be-rendered-by-clients"));
|
ui.label(tr("Amount-of-chunks-host-has-loaded-at-once-synced-enemies-and-physics-objects-need-to-be-loaded-in-by-host-to-be-rendered-by-clients"));
|
||||||
ui.add(Slider::new(&mut game_settings.chunk_target, 12..=64));
|
{
|
||||||
|
let mut temp = game_settings.chunk_target.unwrap_or(def.chunk_target);
|
||||||
|
if ui.add(Slider::new(&mut temp, 12..=64)).changed() {
|
||||||
|
game_settings.chunk_target = Some(temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
ui.add_space(20.0);
|
ui.add_space(20.0);
|
||||||
ui.label(tr("connect_settings_player_tether_desc"));
|
ui.label(tr("connect_settings_player_tether_desc"));
|
||||||
ui.checkbox(
|
{
|
||||||
&mut game_settings.player_tether,
|
let mut temp = game_settings.player_tether.unwrap_or(def.player_tether);
|
||||||
tr("connect_settings_player_tether"),
|
if ui.checkbox(
|
||||||
);
|
&mut temp,
|
||||||
ui.add(
|
tr("connect_settings_player_tether"),
|
||||||
Slider::new(&mut game_settings.tether_length, 10..=5000)
|
).changed()
|
||||||
.text(tr("connect_settings_player_tether_length")),
|
{
|
||||||
);
|
game_settings.player_tether = Some(temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut temp = game_settings.tether_length.unwrap_or(def.tether_length);
|
||||||
|
if ui.add(
|
||||||
|
Slider::new(&mut temp, 10..=5000)
|
||||||
|
.text(tr("connect_settings_player_tether_length")),
|
||||||
|
).changed() {
|
||||||
|
game_settings.tether_length = Some(temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
ui.add_space(20.0);
|
ui.add_space(20.0);
|
||||||
ui.checkbox(
|
{
|
||||||
&mut game_settings.item_dedup,
|
let mut temp = game_settings.item_dedup.unwrap_or(def.item_dedup);
|
||||||
tr("connect_settings_item_dedup"),
|
if ui.checkbox(
|
||||||
);
|
&mut temp,
|
||||||
ui.checkbox(
|
tr("connect_settings_item_dedup"),
|
||||||
&mut game_settings.randomize_perks,
|
).changed() {
|
||||||
tr("Have-perk-pools-be-independent-of-each-other"),
|
game_settings.item_dedup = Some(temp)
|
||||||
);
|
}
|
||||||
ui.horizontal(|ui| {
|
}
|
||||||
ui.text_edit_singleline(&mut game_settings.perk_ban_list);
|
{
|
||||||
ui.label("perk ban list, comma seperated");
|
let mut temp = game_settings.randomize_perks.unwrap_or(def.randomize_perks);
|
||||||
});
|
if ui.checkbox(
|
||||||
ui.add(
|
&mut temp,
|
||||||
Slider::new(&mut game_settings.enemy_hp_mult, 1.0..=1000.0)
|
tr("Have-perk-pools-be-independent-of-each-other"),
|
||||||
.logarithmic(true)
|
).changed() {
|
||||||
.text(tr("connect_settings_enemy_hp_scale")),
|
game_settings.randomize_perks = Some(temp)
|
||||||
);
|
}
|
||||||
ui.checkbox(&mut game_settings.friendly_fire, tr("Enable-friendly-fire"));
|
}
|
||||||
|
{
|
||||||
|
let mut temp = game_settings.perk_ban_list.clone().unwrap_or(def.perk_ban_list);
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
if ui.text_edit_singleline(&mut temp)
|
||||||
|
.changed() {
|
||||||
|
game_settings.perk_ban_list = Some(temp)
|
||||||
|
}
|
||||||
|
ui.label("perk ban list, comma seperated");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut temp = game_settings.enemy_hp_mult.unwrap_or(def.enemy_hp_mult);
|
||||||
|
if ui.add(
|
||||||
|
Slider::new(&mut temp, 1.0..=1000.0)
|
||||||
|
.logarithmic(true)
|
||||||
|
.text(tr("connect_settings_enemy_hp_scale")),
|
||||||
|
).changed() {
|
||||||
|
game_settings.enemy_hp_mult = Some(temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut temp = game_settings.friendly_fire.unwrap_or(def.friendly_fire);
|
||||||
|
if ui.checkbox(&mut temp, tr("Enable-friendly-fire")).changed() {
|
||||||
|
game_settings.friendly_fire = Some(temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
if show_local {
|
if show_local {
|
||||||
heading_with_underline(ui, tr("connect_settings_local"));
|
heading_with_underline(ui, tr("connect_settings_local"));
|
||||||
ui.checkbox(
|
ui.checkbox(
|
||||||
|
@ -1097,10 +1203,14 @@ impl eframe::App for App {
|
||||||
ui.add_space(15.0);
|
ui.add_space(15.0);
|
||||||
if netman.friendly_fire.load(Ordering::Relaxed) {
|
if netman.friendly_fire.load(Ordering::Relaxed) {
|
||||||
let last = self.app_saved_state.game_settings.friendly_fire_team;
|
let last = self.app_saved_state.game_settings.friendly_fire_team;
|
||||||
ui.add(Slider::new(&mut self.app_saved_state.game_settings.friendly_fire_team, -1..=16));
|
let def = DefaultSettings::default();
|
||||||
|
let mut temp = self.app_saved_state.game_settings.friendly_fire_team.unwrap_or(def.friendly_fire_team);
|
||||||
|
if ui.add(Slider::new(&mut temp, -1..=16)).changed() {
|
||||||
|
self.app_saved_state.game_settings.friendly_fire_team = Some(temp);
|
||||||
|
}
|
||||||
if last != self.app_saved_state.game_settings.friendly_fire_team
|
if last != self.app_saved_state.game_settings.friendly_fire_team
|
||||||
|| netman.friendly_fire_team.load(Ordering::Relaxed) == -2 {
|
|| netman.friendly_fire_team.load(Ordering::Relaxed) == -2 {
|
||||||
netman.friendly_fire_team.store(self.app_saved_state.game_settings.friendly_fire_team, Ordering::Relaxed);
|
netman.friendly_fire_team.store(temp, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
ui.label("what team number you are on, 0 means no team, -1 means friendly");
|
ui.label("what team number you are on, 0 means no team, -1 means friendly");
|
||||||
ui.add_space(15.0);
|
ui.add_space(15.0);
|
||||||
|
|
|
@ -26,11 +26,7 @@ use tungstenite::{accept, WebSocket};
|
||||||
|
|
||||||
use crate::mod_manager::ModmanagerSettings;
|
use crate::mod_manager::ModmanagerSettings;
|
||||||
use crate::player_cosmetics::{create_player_png, PlayerPngDesc};
|
use crate::player_cosmetics::{create_player_png, PlayerPngDesc};
|
||||||
use crate::{
|
use crate::{bookkeeping::save_state::{SaveState, SaveStateEntry}, recorder::Recorder, DefaultSettings, GameSettings, PlayerColor};
|
||||||
bookkeeping::save_state::{SaveState, SaveStateEntry},
|
|
||||||
recorder::Recorder,
|
|
||||||
GameSettings, PlayerColor,
|
|
||||||
};
|
|
||||||
pub mod messages;
|
pub mod messages;
|
||||||
mod proxy_opt;
|
mod proxy_opt;
|
||||||
pub mod steam_networking;
|
pub mod steam_networking;
|
||||||
|
@ -133,6 +129,7 @@ pub struct NetManager {
|
||||||
pub friendly_fire: AtomicBool,
|
pub friendly_fire: AtomicBool,
|
||||||
pub ban_list: Mutex<Vec<OmniPeerId>>,
|
pub ban_list: Mutex<Vec<OmniPeerId>>,
|
||||||
pub kick_list: Mutex<Vec<OmniPeerId>>,
|
pub kick_list: Mutex<Vec<OmniPeerId>>,
|
||||||
|
pub no_more_players: AtomicBool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetManager {
|
impl NetManager {
|
||||||
|
@ -155,6 +152,7 @@ impl NetManager {
|
||||||
friendly_fire: AtomicBool::new(false),
|
friendly_fire: AtomicBool::new(false),
|
||||||
ban_list: Default::default(),
|
ban_list: Default::default(),
|
||||||
kick_list: Default::default(),
|
kick_list: Default::default(),
|
||||||
|
no_more_players: AtomicBool::new(false),
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
@ -472,6 +470,7 @@ impl NetManager {
|
||||||
.expect("can set write timeout");
|
.expect("can set write timeout");
|
||||||
|
|
||||||
let settings = self.settings.lock().unwrap();
|
let settings = self.settings.lock().unwrap();
|
||||||
|
let def = DefaultSettings::default();
|
||||||
state.try_ws_write(ws_encode_proxy("seed", settings.seed));
|
state.try_ws_write(ws_encode_proxy("seed", settings.seed));
|
||||||
let my_id = self.peer.my_id();
|
let my_id = self.peer.my_id();
|
||||||
state.try_ws_write(ws_encode_proxy("peer_id", format!("{:016x}", my_id.0)));
|
state.try_ws_write(ws_encode_proxy("peer_id", format!("{:016x}", my_id.0)));
|
||||||
|
@ -485,25 +484,27 @@ impl NetManager {
|
||||||
} else {
|
} else {
|
||||||
info!("No nickname chosen");
|
info!("No nickname chosen");
|
||||||
}
|
}
|
||||||
self.friendly_fire
|
let ff = settings.friendly_fire.unwrap_or(def.friendly_fire);
|
||||||
.store(settings.friendly_fire, atomic::Ordering::Relaxed);
|
self.friendly_fire.store(ff, atomic::Ordering::Relaxed);
|
||||||
state.try_ws_write_option("friendly_fire", settings.friendly_fire);
|
state.try_ws_write_option("friendly_fire", ff);
|
||||||
state.try_ws_write_option("debug", settings.debug_mode);
|
state.try_ws_write_option("debug", settings.debug_mode.unwrap_or(def.debug_mode));
|
||||||
state.try_ws_write_option("world_sync_version", settings.world_sync_version);
|
state.try_ws_write_option("world_sync_version", settings.world_sync_version.unwrap_or(def.world_sync_version));
|
||||||
state.try_ws_write_option("player_tether", settings.player_tether);
|
state.try_ws_write_option("player_tether", settings.player_tether.unwrap_or(def.player_tether));
|
||||||
state.try_ws_write_option("tether_length", settings.tether_length);
|
state.try_ws_write_option("tether_length", settings.tether_length.unwrap_or(def.tether_length));
|
||||||
state.try_ws_write_option("item_dedup", settings.item_dedup);
|
state.try_ws_write_option("item_dedup", settings.item_dedup.unwrap_or(def.item_dedup));
|
||||||
state.try_ws_write_option("randomize_perks", settings.randomize_perks);
|
state.try_ws_write_option("randomize_perks", settings.randomize_perks.unwrap_or(def.randomize_perks));
|
||||||
state.try_ws_write_option("enemy_hp_scale", settings.enemy_hp_mult);
|
state.try_ws_write_option("enemy_hp_scale", settings.enemy_hp_mult.unwrap_or(def.enemy_hp_mult));
|
||||||
state.try_ws_write_option("world_sync_interval", settings.world_sync_interval);
|
state.try_ws_write_option("world_sync_interval", settings.world_sync_interval.unwrap_or(def.world_sync_interval));
|
||||||
state.try_ws_write_option("game_mode", settings.game_mode);
|
state.try_ws_write_option("game_mode", settings.game_mode.unwrap_or(def.game_mode));
|
||||||
state.try_ws_write_option("chunk_target", settings.chunk_target);
|
state.try_ws_write_option("chunk_target", settings.chunk_target.unwrap_or(def.chunk_target));
|
||||||
state.try_ws_write_option("health_per_player", settings.health_per_player);
|
state.try_ws_write_option("health_per_player", settings.health_per_player.unwrap_or(def.health_per_player));
|
||||||
state.try_ws_write_option("enemy_sync_interval", settings.enemy_sync_interval);
|
state.try_ws_write_option("enemy_sync_interval", settings.enemy_sync_interval.unwrap_or(def.enemy_sync_interval));
|
||||||
state.try_ws_write_option("global_hp_loss", settings.global_hp_loss);
|
state.try_ws_write_option("global_hp_loss", settings.global_hp_loss.unwrap_or(def.global_hp_loss));
|
||||||
state.try_ws_write_option("perk_ban_list", settings.perk_ban_list.as_str());
|
state.try_ws_write_option("perma_death", settings.perma_death.unwrap_or(def.perma_death));
|
||||||
state.try_ws_write_option("no_material_damage", settings.no_material_damage);
|
let lst = settings.clone();
|
||||||
state.try_ws_write_option("health_lost_on_revive", settings.health_lost_on_revive);
|
state.try_ws_write_option("perk_ban_list", lst.perk_ban_list.unwrap_or(def.perk_ban_list).as_str());
|
||||||
|
state.try_ws_write_option("no_material_damage", settings.no_material_damage.unwrap_or(def.no_material_damage));
|
||||||
|
state.try_ws_write_option("health_lost_on_revive", settings.health_lost_on_revive.unwrap_or(def.health_lost_on_revive));
|
||||||
let rgb = self.init_settings.player_color.player_main;
|
let rgb = self.init_settings.player_color.player_main;
|
||||||
state.try_ws_write_option(
|
state.try_ws_write_option(
|
||||||
"mina_color",
|
"mina_color",
|
||||||
|
|
37
quant.ew/data/entities/animals/nibbana.xml
Normal file
37
quant.ew/data/entities/animals/nibbana.xml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<Entity tags="polymorphed_cessation" name="$animal_player" >
|
||||||
|
<PlatformShooterPlayerComponent
|
||||||
|
center_camera_on_this_entity="1"
|
||||||
|
aiming_reticle_distance_from_character="60"
|
||||||
|
camera_max_distance_from_character="50"
|
||||||
|
move_camera_with_aim="1"
|
||||||
|
eating_area_min.x="-6"
|
||||||
|
eating_area_max.x="6"
|
||||||
|
eating_area_min.y="-4"
|
||||||
|
eating_area_max.y="6"
|
||||||
|
eating_cells_per_frame="2"
|
||||||
|
></PlatformShooterPlayerComponent>
|
||||||
|
<ControlsComponent
|
||||||
|
enabled="1"
|
||||||
|
gamepad_fire_on_thumbstick_extend="0"
|
||||||
|
gamepad_fire_on_thumbstick_extend_threshold="0.9"
|
||||||
|
gamepad_indirect_aiming_enabled="0"
|
||||||
|
></ControlsComponent>
|
||||||
|
<Entity name="cursor">
|
||||||
|
<SpriteComponent
|
||||||
|
alpha="1"
|
||||||
|
image_file="mods/quant.ew/files/resource/sprites/cursor.png"
|
||||||
|
next_rect_animation=""
|
||||||
|
offset_x="6.5"
|
||||||
|
offset_y="6.5"
|
||||||
|
emissive="1"
|
||||||
|
additive="1"
|
||||||
|
rect_animation=""
|
||||||
|
z_index="1"
|
||||||
|
update_transform="1"
|
||||||
|
update_transform_rotation="0"
|
||||||
|
has_special_scale="1"
|
||||||
|
special_scale_x="0.5"
|
||||||
|
special_scale_y="0.5"
|
||||||
|
></SpriteComponent>
|
||||||
|
</Entity>
|
||||||
|
</Entity>
|
|
@ -176,9 +176,22 @@ local function player_died()
|
||||||
|
|
||||||
-- This may look like a hack, but it allows to use existing poly machinery to change player entity AND to store the original player for later,
|
-- This may look like a hack, but it allows to use existing poly machinery to change player entity AND to store the original player for later,
|
||||||
-- Which is, like, perfect.
|
-- Which is, like, perfect.
|
||||||
|
GameAddFlagRun("ew_flag_notplayer_active")
|
||||||
|
if ctx.proxy_opt.perma_death then
|
||||||
|
local ent = LoadGameEffectEntityTo(ctx.my_player.entity, "mods/quant.ew/files/system/local_health/notplayer/cessation.xml")
|
||||||
|
polymorph.switch_entity(ent + 1)
|
||||||
|
GameAddFlagRun("msg_gods_looking")
|
||||||
|
GameAddFlagRun("msg_gods_looking2")
|
||||||
|
EntityAddTag(ctx.my_player.entity, "ew_notplayer")
|
||||||
|
for _, child in ipairs(EntityGetAllChildren(ctx.my_player.entity) or {}) do
|
||||||
|
if EntityGetName(child) == "cursor" then
|
||||||
|
EntitySetComponentIsEnabled(child, EntityGetFirstComponentIncludingDisabled(child, "SpriteComponent"), false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
local ent = LoadGameEffectEntityTo(ctx.my_player.entity, "mods/quant.ew/files/system/local_health/notplayer/poly_effect.xml")
|
local ent = LoadGameEffectEntityTo(ctx.my_player.entity, "mods/quant.ew/files/system/local_health/notplayer/poly_effect.xml")
|
||||||
ctx.my_player.entity = ent + 1
|
ctx.my_player.entity = ent + 1
|
||||||
GameAddFlagRun("ew_flag_notplayer_active")
|
|
||||||
do_switch_effect(false)
|
do_switch_effect(false)
|
||||||
EntitySetName(ctx.my_player.entity, ctx.my_id.."?")
|
EntitySetName(ctx.my_player.entity, ctx.my_id.."?")
|
||||||
util.set_ent_health(ctx.my_player.entity, {max_hp, max_hp})
|
util.set_ent_health(ctx.my_player.entity, {max_hp, max_hp})
|
||||||
|
@ -191,7 +204,7 @@ local function player_died()
|
||||||
remove_healthbar_locally()
|
remove_healthbar_locally()
|
||||||
for _, child in ipairs(EntityGetAllChildren(ctx.my_player.entity) or {}) do
|
for _, child in ipairs(EntityGetAllChildren(ctx.my_player.entity) or {}) do
|
||||||
if EntityGetName(child) == "cursor" or EntityGetName(child) == "notcursor" then
|
if EntityGetName(child) == "cursor" or EntityGetName(child) == "notcursor" then
|
||||||
EntityKill(child)
|
EntitySetComponentIsEnabled(child, EntityGetFirstComponentIncludingDisabled(child, "SpriteComponent"), false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
inventory_helper.set_item_data(item_data, ctx.my_player)
|
inventory_helper.set_item_data(item_data, ctx.my_player)
|
||||||
|
|
13
quant.ew/files/system/local_health/notplayer/cessation.xml
Normal file
13
quant.ew/files/system/local_health/notplayer/cessation.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<Entity>
|
||||||
|
<InheritTransformComponent>
|
||||||
|
</InheritTransformComponent>
|
||||||
|
|
||||||
|
<GameEffectComponent
|
||||||
|
effect="POLYMORPH_CESSATION"
|
||||||
|
frames="-1"
|
||||||
|
disable_movement="0"
|
||||||
|
polymorph_target="data/entities/animals/nibbana.xml"
|
||||||
|
>
|
||||||
|
</GameEffectComponent >
|
||||||
|
|
||||||
|
</Entity>
|
|
@ -637,6 +637,8 @@ local function choose_movement()
|
||||||
ComponentSetValue2(state.control_component, "mButtonFrameRight", GameGetFrameNum()+100)
|
ComponentSetValue2(state.control_component, "mButtonFrameRight", GameGetFrameNum()+100)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
local air = ComponentGetValue2(state.damage_model, "air_in_lungs")
|
||||||
|
local fly = ComponentGetValue2(state.data_component, "mFlyingTimeLeft")
|
||||||
if state.target == nil or (has_ambrosia(ctx.my_player.entity) and state.init_timer > no_shoot_time + 4) then
|
if state.target == nil or (has_ambrosia(ctx.my_player.entity) and state.init_timer > no_shoot_time + 4) then
|
||||||
state.control_a = false
|
state.control_a = false
|
||||||
state.control_d = false
|
state.control_d = false
|
||||||
|
@ -663,13 +665,14 @@ local function choose_movement()
|
||||||
move = -1
|
move = -1
|
||||||
end
|
end
|
||||||
|
|
||||||
local air = ComponentGetValue2(state.damage_model, "air_in_lungs")
|
if air < 2 then
|
||||||
if air < 1 then
|
if fly < 0.5 then
|
||||||
state.control_w = true
|
state.control_s = true
|
||||||
state.control_s = false
|
state.control_w = false
|
||||||
elseif air < 2 then
|
else
|
||||||
state.control_s = true
|
state.control_w = true
|
||||||
state.control_w = false
|
state.control_s = false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -752,7 +755,7 @@ local function choose_movement()
|
||||||
on_right = my_x > t_x
|
on_right = my_x > t_x
|
||||||
end
|
end
|
||||||
|
|
||||||
if ComponentGetValue2(state.data_component, "mFlyingTimeLeft") < 0.2 and GameGetFrameNum() % 300 > 250 then
|
if fly < 0.2 and GameGetFrameNum() % 300 > 250 then
|
||||||
rest = true
|
rest = true
|
||||||
give_space = give_space + 10
|
give_space = give_space + 10
|
||||||
swap_side = false
|
swap_side = false
|
||||||
|
@ -863,13 +866,14 @@ local function choose_movement()
|
||||||
if did_hit_up and state.water_potion ~= nil then
|
if did_hit_up and state.water_potion ~= nil then
|
||||||
state.control_w = false
|
state.control_w = false
|
||||||
end
|
end
|
||||||
local air = ComponentGetValue2(state.damage_model, "air_in_lungs")
|
if air < 2 then
|
||||||
if air < 1 then
|
if fly < 0.5 then
|
||||||
state.control_w = true
|
state.control_s = true
|
||||||
state.control_s = false
|
state.control_w = false
|
||||||
elseif air < 2 then
|
else
|
||||||
state.control_s = true
|
state.control_w = true
|
||||||
state.control_w = false
|
state.control_s = false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1441,6 +1445,7 @@ end
|
||||||
|
|
||||||
function module.on_world_update()
|
function module.on_world_update()
|
||||||
local active = GameHasFlagRun("ew_flag_notplayer_active")
|
local active = GameHasFlagRun("ew_flag_notplayer_active")
|
||||||
|
and not ctx.proxy_opt.perma_death
|
||||||
if active and EntityGetIsAlive(ctx.my_player.entity) and EntityHasTag(ctx.my_player.entity, "ew_notplayer") then
|
if active and EntityGetIsAlive(ctx.my_player.entity) and EntityHasTag(ctx.my_player.entity, "ew_notplayer") then
|
||||||
if state == nil then
|
if state == nil then
|
||||||
init_state()
|
init_state()
|
||||||
|
|
|
@ -74,8 +74,15 @@ function module.on_world_update()
|
||||||
local mx, my = GameGetCameraPos()
|
local mx, my = GameGetCameraPos()
|
||||||
for peer_id, player in pairs(ctx.players) do
|
for peer_id, player in pairs(ctx.players) do
|
||||||
local ent = player.entity
|
local ent = player.entity
|
||||||
|
local children = EntityGetAllChildren(ent) or {}
|
||||||
|
for _, child in ipairs(children) do
|
||||||
|
if EntityGetName(child) == "cursor" or EntityGetName(child) == "notcursor" then
|
||||||
|
EntitySetComponentIsEnabled(child, EntityGetFirstComponentIncludingDisabled(child, "SpriteComponent"), true)
|
||||||
|
end
|
||||||
|
end
|
||||||
local x, y = EntityGetTransform(ent)
|
local x, y = EntityGetTransform(ent)
|
||||||
local notplayer = EntityHasTag(ent, "ew_notplayer")
|
local notplayer = EntityHasTag(ent, "ew_notplayer")
|
||||||
|
and not ctx.proxy_opt.perma_death
|
||||||
if notplayer and GameHasFlagRun("ending_game_completed") then
|
if notplayer and GameHasFlagRun("ending_game_completed") then
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
|
@ -84,7 +91,7 @@ function module.on_world_update()
|
||||||
end
|
end
|
||||||
local dx, dy = x - mx, y - my
|
local dx, dy = x - mx, y - my
|
||||||
local cape
|
local cape
|
||||||
for _, child in ipairs(EntityGetAllChildren(ent) or {}) do
|
for _, child in ipairs(children) do
|
||||||
if EntityGetName(child) == "cape" then
|
if EntityGetName(child) == "cape" then
|
||||||
local cpe = EntityGetFirstComponentIncludingDisabled(child, "VerletPhysicsComponent")
|
local cpe = EntityGetFirstComponentIncludingDisabled(child, "VerletPhysicsComponent")
|
||||||
local cx, cy = ComponentGetValue2(cpe, "m_position_previous")
|
local cx, cy = ComponentGetValue2(cpe, "m_position_previous")
|
||||||
|
|
|
@ -72,7 +72,7 @@ local function get_me()
|
||||||
local i = 0
|
local i = 0
|
||||||
local alive = -1, -1
|
local alive = -1, -1
|
||||||
for peer_id, potential_target in pairs(ctx.players) do
|
for peer_id, potential_target in pairs(ctx.players) do
|
||||||
if GameHasFlagRun("ending_game_completed") and EntityHasTag(potential_target.entity, "ew_notplayer") then
|
if (GameHasFlagRun("ending_game_completed") or ctx.proxy_opt.perma_death) and EntityHasTag(potential_target.entity, "ew_notplayer") then
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
@ -218,7 +218,7 @@ local function set_camera_pos()
|
||||||
if cam_target == nil or re_cam then
|
if cam_target == nil or re_cam then
|
||||||
local i = 0
|
local i = 0
|
||||||
for peer_id, potential_target in pairs(ctx.players) do
|
for peer_id, potential_target in pairs(ctx.players) do
|
||||||
if GameHasFlagRun("ending_game_completed") and EntityHasTag(potential_target.entity, "ew_notplayer") then
|
if (GameHasFlagRun("ending_game_completed") or ctx.proxy_opt.perma_death) and EntityHasTag(potential_target.entity, "ew_notplayer") then
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
@ -246,7 +246,8 @@ end
|
||||||
local function update_i()
|
local function update_i()
|
||||||
local i = 0
|
local i = 0
|
||||||
for peer_id, potential_target in pairs(ctx.players) do
|
for peer_id, potential_target in pairs(ctx.players) do
|
||||||
if GameHasFlagRun("ending_game_completed") and EntityHasTag(potential_target.entity, "ew_notplayer") then
|
if (GameHasFlagRun("ending_game_completed") or ctx.proxy_opt.perma_death)
|
||||||
|
and EntityHasTag(potential_target.entity, "ew_notplayer") then
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
@ -263,7 +264,7 @@ end
|
||||||
local function number_of_players()
|
local function number_of_players()
|
||||||
local i = 0
|
local i = 0
|
||||||
for _, potential_target in pairs(ctx.players) do
|
for _, potential_target in pairs(ctx.players) do
|
||||||
if GameHasFlagRun("ending_game_completed") and EntityHasTag(potential_target.entity, "ew_notplayer") then
|
if (GameHasFlagRun("ending_game_completed") or ctx.proxy_opt.perma_death) and EntityHasTag(potential_target.entity, "ew_notplayer") then
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
@ -296,7 +297,9 @@ function spectate.on_world_update()
|
||||||
update_i()
|
update_i()
|
||||||
last_len = number_of_players()
|
last_len = number_of_players()
|
||||||
end
|
end
|
||||||
if cam_target ~= nil and GameHasFlagRun("ending_game_completed") and EntityHasTag(cam_target.entity, "ew_notplayer") then
|
if cam_target ~= nil
|
||||||
|
and ((GameHasFlagRun("ending_game_completed") or ctx.proxy_opt.perma_death)
|
||||||
|
and EntityHasTag(cam_target.entity, "ew_notplayer")) then
|
||||||
update_i()
|
update_i()
|
||||||
last_len = number_of_players()
|
last_len = number_of_players()
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,15 @@ local rpc = net.new_rpc_namespace()
|
||||||
|
|
||||||
local shield_entities = {}
|
local shield_entities = {}
|
||||||
|
|
||||||
|
local function remove_shield(peer_id)
|
||||||
|
if shield_entities[peer_id] ~= nil then
|
||||||
|
if EntityGetIsAlive(shield_entities[peer_id][2]) then
|
||||||
|
EntityKill(shield_entities[peer_id][2])
|
||||||
|
end
|
||||||
|
shield_entities[peer_id] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
rpc.opts_everywhere()
|
rpc.opts_everywhere()
|
||||||
rpc.opts_reliable()
|
rpc.opts_reliable()
|
||||||
function rpc.add_shield(target)
|
function rpc.add_shield(target)
|
||||||
|
@ -12,23 +21,21 @@ function rpc.add_shield(target)
|
||||||
if not EntityGetIsAlive(entity) or EntityHasTag(entity, "polymorphed") then
|
if not EntityGetIsAlive(entity) or EntityHasTag(entity, "polymorphed") then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if shield_entities[ctx.rpc_peer_id] ~= nil then
|
if shield_entities[ctx.rpc_peer_id] == nil or shield_entities[ctx.rpc_peer_id][1] ~= target then
|
||||||
EntityKill(shield_entities[ctx.rpc_peer_id][2])
|
if shield_entities[ctx.rpc_peer_id] ~= nil
|
||||||
|
and EntityGetIsAlive(shield_entities[ctx.rpc_peer_id][2]) then
|
||||||
|
EntityKill(shield_entities[ctx.rpc_peer_id][2])
|
||||||
|
end
|
||||||
|
local ent = EntityLoad("mods/quant.ew/files/system/spectator_helps/shield_base.xml")
|
||||||
|
EntityAddChild(entity, ent)
|
||||||
|
shield_entities[ctx.rpc_peer_id] = {target, ent}
|
||||||
end
|
end
|
||||||
local ent = EntityLoad("mods/quant.ew/files/system/spectator_helps/shield_base.xml")
|
|
||||||
EntityAddChild(entity, ent)
|
|
||||||
shield_entities[ctx.rpc_peer_id] = {target, ent}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
rpc.opts_everywhere()
|
rpc.opts_everywhere()
|
||||||
rpc.opts_reliable()
|
rpc.opts_reliable()
|
||||||
function rpc.del_shield()
|
function rpc.del_shield()
|
||||||
if shield_entities[ctx.rpc_peer_id] ~= nil then
|
remove_shield(ctx.rpc_peer_id)
|
||||||
if EntityGetIsAlive(shield_entities[ctx.rpc_peer_id][2]) then
|
|
||||||
EntityKill(shield_entities[ctx.rpc_peer_id][2])
|
|
||||||
end
|
|
||||||
shield_entities[ctx.rpc_peer_id] = nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local module = {}
|
local module = {}
|
||||||
|
@ -48,11 +55,11 @@ local function is_acceptable_help_target(spectating_over)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
if shield_entities[ctx.my_id] ~= nil then
|
if shield_entities[ctx.my_id] ~= nil then
|
||||||
if shield_entities[ctx.my_id][1] ~= spectating_over then
|
if shield_entities[ctx.my_id][1] ~= spectating_over then
|
||||||
rpc.del_shield()
|
rpc.del_shield()
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
return false
|
return GameGetFrameNum() % 300 < 10
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
@ -77,7 +84,10 @@ end
|
||||||
local last_spectate
|
local last_spectate
|
||||||
|
|
||||||
function module.on_world_update()
|
function module.on_world_update()
|
||||||
if GameHasFlagRun("ending_game_completed") then
|
if GameHasFlagRun("ending_game_completed") or ctx.proxy_opt.perma_death then
|
||||||
|
if not ctx.proxy_opt.perma_death then
|
||||||
|
rpc.del_shield()
|
||||||
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if GameGetFrameNum() % 10 == 8 then
|
if GameGetFrameNum() % 10 == 8 then
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue