Skip to content

Commit e9bddda

Browse files
committed
make ui a bit more clear, spawn ragdolls when you die in perma death
1 parent 33c86c5 commit e9bddda

File tree

5 files changed

+109
-95
lines changed

5 files changed

+109
-95
lines changed

noita-proxy/assets/lang/en-US/main.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ shared_health_desc_1 = Health is shared, but scales with player count.
106106
shared_health_desc_2 = Percentage-based damage and full heals are adjusted.
107107
shared_health_desc_3 = The original mode.
108108
Local-health = Local health
109+
Local-health-alt = Local health alternate
110+
Local-health-perma = Local health perma death
109111
Shared-health = Shared health
110112
Game-mode = Game mode
111113
world-sync-is-pixel-sync-note = Note: World sync refers to the part that syncs pixels(materials) of the world. Enemies and other entities aren't affected by this.

noita-proxy/src/lib.rs

Lines changed: 83 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -59,24 +59,28 @@ const DEFAULT_PORT: u16 = 5123;
5959
#[derive(Debug, Decode, Encode, Clone, Serialize, Deserialize, PartialEq, Eq, Copy)]
6060
pub(crate) enum GameMode {
6161
SharedHealth,
62-
LocalHealth,
62+
LocalHealth(LocalHealthMode),
6363
// MestariMina, // TODO later
6464
}
6565

66+
#[derive(Debug, Decode, Encode, Clone, Serialize, Deserialize, PartialEq, Eq, Copy)]
67+
pub(crate) enum LocalHealthMode {
68+
Normal,
69+
Alternate,
70+
PermaDeath,
71+
}
72+
6673
#[derive(Debug, Decode, Encode, Clone, Serialize, Deserialize, PartialEq, Default)]
6774
#[serde(default)]
6875
pub struct GameSettings {
6976
seed: u64,
7077
world_num: u16,
7178
debug_mode: Option<bool>,
72-
world_sync_version: Option<u32>,
7379
use_constant_seed: bool,
7480
item_dedup: Option<bool>,
7581
enemy_hp_mult: Option<f32>,
76-
world_sync_interval: Option<u32>,
7782
game_mode: Option<GameMode>,
7883
friendly_fire: Option<bool>,
79-
enemy_sync_interval: Option<u32>,
8084
randomize_perks: Option<bool>,
8185
progress: Vec<String>,
8286
max_players: Option<u32>,
@@ -85,10 +89,8 @@ pub struct GameSettings {
8589
no_material_damage: Option<bool>,
8690
global_hp_loss: Option<bool>,
8791
perk_ban_list: Option<String>,
88-
perma_death: Option<bool>,
8992
physics_damage: Option<bool>,
9093
share_gold: Option<bool>,
91-
no_notplayer: Option<bool>,
9294
}
9395
impl GameSettings {
9496
fn show_editor(&mut self, ui: &mut Ui, enabled: bool) {
@@ -102,7 +104,25 @@ impl GameSettings {
102104
.radio_value(&mut temp, GameMode::SharedHealth, tr("Shared-health"))
103105
.changed()
104106
|| ui
105-
.radio_value(&mut temp, GameMode::LocalHealth, tr("Local-health"))
107+
.radio_value(
108+
&mut temp,
109+
GameMode::LocalHealth(LocalHealthMode::Normal),
110+
tr("Local-health"),
111+
)
112+
.changed()
113+
|| ui
114+
.radio_value(
115+
&mut temp,
116+
GameMode::LocalHealth(LocalHealthMode::Alternate),
117+
tr("Local-health-alt"),
118+
)
119+
.changed()
120+
|| ui
121+
.radio_value(
122+
&mut temp,
123+
GameMode::LocalHealth(LocalHealthMode::PermaDeath),
124+
tr("Local-health-perma"),
125+
)
106126
.changed()
107127
{
108128
game_settings.game_mode = Some(temp)
@@ -124,55 +144,64 @@ impl GameSettings {
124144
game_settings.health_per_player = Some(temp)
125145
}
126146
}
127-
GameMode::LocalHealth => {
147+
GameMode::LocalHealth(mode) => {
128148
ui.label(tr("local_health_desc_1"));
129-
ui.label(tr("local_health_desc_2"));
130-
ui.add_space(5.0);
131-
ui.label(tr("Health-percent-lost-on-reviving"));
132-
{
133-
let mut temp = game_settings
134-
.health_lost_on_revive
135-
.unwrap_or(def.health_lost_on_revive);
136-
if ui.add(Slider::new(&mut temp, 0..=100)).changed() {
137-
game_settings.health_lost_on_revive = Some(temp)
138-
}
139-
}
140-
{
141-
let mut temp =
142-
game_settings.global_hp_loss.unwrap_or(def.global_hp_loss);
143-
if ui.checkbox(&mut temp, tr("global_hp_loss")).changed() {
144-
game_settings.global_hp_loss = Some(temp)
145-
}
146-
}
147-
{
148-
let mut temp = game_settings
149-
.no_material_damage
150-
.unwrap_or(def.no_material_damage);
151-
if ui.checkbox(&mut temp, tr("no_material_damage")).changed() {
152-
game_settings.no_material_damage = Some(temp)
153-
}
154-
}
155-
ui.add_space(1.0);
156-
{
157-
let mut temp = game_settings.perma_death.unwrap_or(def.perma_death);
158-
if ui.checkbox(&mut temp, tr("perma_death")).changed() {
159-
game_settings.perma_death = Some(temp)
160-
}
161-
}
162-
ui.add_space(1.0);
163-
{
164-
let mut temp =
165-
game_settings.physics_damage.unwrap_or(def.physics_damage);
166-
if ui.checkbox(&mut temp, tr("physics_damage")).changed() {
167-
game_settings.physics_damage = Some(temp)
149+
match mode {
150+
LocalHealthMode::Normal => {
151+
ui.add_space(5.0);
152+
ui.label(tr("Health-percent-lost-on-reviving"));
153+
{
154+
let mut temp = game_settings
155+
.health_lost_on_revive
156+
.unwrap_or(def.health_lost_on_revive);
157+
if ui.add(Slider::new(&mut temp, 0..=100)).changed() {
158+
game_settings.health_lost_on_revive = Some(temp)
159+
}
160+
}
161+
{
162+
let mut temp =
163+
game_settings.global_hp_loss.unwrap_or(def.global_hp_loss);
164+
if ui.checkbox(&mut temp, tr("global_hp_loss")).changed() {
165+
game_settings.global_hp_loss = Some(temp)
166+
}
167+
}
168+
{
169+
let mut temp = game_settings
170+
.no_material_damage
171+
.unwrap_or(def.no_material_damage);
172+
if ui.checkbox(&mut temp, tr("no_material_damage")).changed() {
173+
game_settings.no_material_damage = Some(temp)
174+
}
175+
}
176+
ui.add_space(1.0);
177+
{
178+
let mut temp =
179+
game_settings.physics_damage.unwrap_or(def.physics_damage);
180+
if ui.checkbox(&mut temp, tr("physics_damage")).changed() {
181+
game_settings.physics_damage = Some(temp)
182+
}
183+
}
168184
}
169-
}
170-
ui.add_space(1.0);
171-
{
172-
let mut temp = game_settings.no_notplayer.unwrap_or(def.no_notplayer);
173-
if ui.checkbox(&mut temp, "no minua").changed() {
174-
game_settings.no_notplayer = Some(temp)
185+
LocalHealthMode::Alternate => {
186+
ui.add_space(5.0);
187+
ui.label(tr("Health-percent-lost-on-reviving"));
188+
{
189+
let mut temp = game_settings
190+
.health_lost_on_revive
191+
.unwrap_or(def.health_lost_on_revive);
192+
if ui.add(Slider::new(&mut temp, 0..=100)).changed() {
193+
game_settings.health_lost_on_revive = Some(temp)
194+
}
195+
}
196+
{
197+
let mut temp =
198+
game_settings.global_hp_loss.unwrap_or(def.global_hp_loss);
199+
if ui.checkbox(&mut temp, tr("global_hp_loss")).changed() {
200+
game_settings.global_hp_loss = Some(temp)
201+
}
202+
}
175203
}
204+
LocalHealthMode::PermaDeath => {}
176205
}
177206
}
178207
}
@@ -284,38 +313,30 @@ impl GameSettings {
284313
}
285314
pub struct DefaultSettings {
286315
debug_mode: bool,
287-
world_sync_version: u32,
288316
item_dedup: bool,
289317
enemy_hp_mult: f32,
290-
world_sync_interval: u32,
291318
game_mode: GameMode,
292319
friendly_fire: bool,
293-
enemy_sync_interval: u32,
294320
randomize_perks: bool,
295321
max_players: u32,
296322
health_per_player: u32,
297323
health_lost_on_revive: u32,
298324
no_material_damage: bool,
299325
global_hp_loss: bool,
300326
perk_ban_list: String,
301-
perma_death: bool,
302327
physics_damage: bool,
303328
share_gold: bool,
304-
no_notplayer: bool,
305329
}
306330

307331
impl Default for DefaultSettings {
308332
fn default() -> Self {
309333
DefaultSettings {
310334
debug_mode: false,
311-
world_sync_version: 2,
312335
item_dedup: true,
313336
randomize_perks: true,
314337
enemy_hp_mult: 1.0,
315-
world_sync_interval: 3,
316-
game_mode: GameMode::LocalHealth,
338+
game_mode: GameMode::LocalHealth(LocalHealthMode::Normal),
317339
friendly_fire: false,
318-
enemy_sync_interval: 3,
319340
max_players: 250,
320341
health_per_player: 100,
321342
health_lost_on_revive: 0,
@@ -324,10 +345,8 @@ impl Default for DefaultSettings {
324345
perk_ban_list:
325346
"GLOBAL_GORE,GLASS_CANNON,REVENGE_RATS,PLAGUE_RATS,VOMIT_RATS,CORDYCEPS,MOLD"
326347
.to_string(),
327-
perma_death: false,
328348
physics_damage: true,
329349
share_gold: false,
330-
no_notplayer: false,
331350
}
332351
}
333352
}

noita-proxy/src/net.rs

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::mod_manager::{get_mods, ModmanagerSettings};
2727
use crate::player_cosmetics::{create_player_png, PlayerPngDesc};
2828
use crate::{
2929
bookkeeping::save_state::{SaveState, SaveStateEntry},
30-
DefaultSettings, GameSettings,
30+
DefaultSettings, GameMode, GameSettings, LocalHealthMode,
3131
};
3232
pub mod messages;
3333
mod proxy_opt;
@@ -508,12 +508,6 @@ impl NetManager {
508508
);
509509
state.try_ws_write_option("share_gold", settings.share_gold.unwrap_or(def.share_gold));
510510
state.try_ws_write_option("debug", settings.debug_mode.unwrap_or(def.debug_mode));
511-
state.try_ws_write_option(
512-
"world_sync_version",
513-
settings
514-
.world_sync_version
515-
.unwrap_or(def.world_sync_version),
516-
);
517511
state.try_ws_write_option("item_dedup", settings.item_dedup.unwrap_or(def.item_dedup));
518512
state.try_ws_write_option(
519513
"randomize_perks",
@@ -523,39 +517,27 @@ impl NetManager {
523517
"enemy_hp_scale",
524518
settings.enemy_hp_mult.unwrap_or(def.enemy_hp_mult),
525519
);
526-
state.try_ws_write_option(
527-
"world_sync_interval",
528-
settings
529-
.world_sync_interval
530-
.unwrap_or(def.world_sync_interval),
531-
);
532-
state.try_ws_write_option("game_mode", settings.game_mode.unwrap_or(def.game_mode));
520+
let mode = settings.game_mode.unwrap_or(def.game_mode);
521+
state.try_ws_write_option("game_mode", mode);
522+
if let GameMode::LocalHealth(mode) = mode {
523+
match mode {
524+
LocalHealthMode::Normal => {}
525+
LocalHealthMode::PermaDeath => state.try_ws_write_option("perma_death", true),
526+
LocalHealthMode::Alternate => state.try_ws_write_option("no_notplayer", true),
527+
}
528+
}
533529
state.try_ws_write_option(
534530
"health_per_player",
535531
settings.health_per_player.unwrap_or(def.health_per_player),
536532
);
537-
state.try_ws_write_option(
538-
"enemy_sync_interval",
539-
settings
540-
.enemy_sync_interval
541-
.unwrap_or(def.enemy_sync_interval),
542-
);
543533
state.try_ws_write_option(
544534
"global_hp_loss",
545535
settings.global_hp_loss.unwrap_or(def.global_hp_loss),
546536
);
547-
state.try_ws_write_option(
548-
"perma_death",
549-
settings.perma_death.unwrap_or(def.perma_death),
550-
);
551537
state.try_ws_write_option(
552538
"physics_damage",
553539
settings.physics_damage.unwrap_or(def.physics_damage),
554540
);
555-
state.try_ws_write_option(
556-
"no_notplayer",
557-
settings.no_notplayer.unwrap_or(def.no_notplayer),
558-
);
559541
let lst = settings.clone();
560542
state.try_ws_write_option(
561543
"perk_ban_list",

noita-proxy/src/net/proxy_opt.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use std::io::Write;
2-
31
use crate::GameMode;
2+
use std::io::Write;
43

54
/// Trait that allows to pass value to mod as proxy options.
65
pub(crate) trait ProxyOpt {
@@ -43,7 +42,7 @@ impl ProxyOpt for GameMode {
4342
GameMode::SharedHealth => {
4443
write!(buf, "proxy_opt {} shared_health", key).unwrap();
4544
}
46-
GameMode::LocalHealth => {
45+
GameMode::LocalHealth(_) => {
4746
write!(buf, "proxy_opt {} local_health", key).unwrap();
4847
}
4948
}

quant.ew/files/system/local_health/local_health.lua

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,11 @@ local function no_notplayer()
292292
polymorph.switch_entity(ent + 1)
293293
end
294294

295+
rpc.opts_everywhere()
296+
function rpc.spawn_ragdoll(x, y)
297+
LoadRagdoll("mods/quant.ew/files/system/player/tmp/".. ctx.rpc_peer_id.."_ragdoll.txt", x, y)
298+
end
299+
295300
local function player_died()
296301
if ctx.my_player.entity == nil then
297302
return
@@ -315,11 +320,13 @@ local function player_died()
315320
end
316321
if ctx.proxy_opt.perma_death then
317322
remove_inventory()
323+
local x, y = EntityGetTransform(ctx.my_player.entity)
318324
local ent = LoadGameEffectEntityTo(ctx.my_player.entity, "mods/quant.ew/files/system/local_health/notplayer/cessation.xml")
319325
EntityAddTag(ent + 1, "ew_notplayer")
320326
polymorph.switch_entity(ent + 1)
321327
GameAddFlagRun("msg_gods_looking")
322328
GameAddFlagRun("msg_gods_looking2")
329+
rpc.spawn_ragdoll(x, y)
323330
return
324331
end
325332
local gold = get_gold()
@@ -389,6 +396,11 @@ local function do_game_over(message)
389396
GameRemoveFlagRun("ew_flag_notplayer_active")
390397
set_camera_free(true, ctx.my_player.entity)
391398

399+
if ctx.proxy_opt.perma_death then
400+
GameTriggerGameOver()
401+
return
402+
end
403+
392404
if not GameHasFlagRun("ending_game_completed") then
393405
for peer_id, data in pairs(ctx.players) do
394406
if peer_id ~= ctx.my_id

0 commit comments

Comments
 (0)