mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
UI notifying player that their skillset has been invalidated.
This commit is contained in:
@ -756,7 +756,8 @@ impl Client {
|
||||
| ClientGeneral::RequestSiteInfo(_)
|
||||
| ClientGeneral::UnlockSkillGroup(_)
|
||||
| ClientGeneral::RequestPlayerPhysics { .. }
|
||||
| ClientGeneral::RequestLossyTerrainCompression { .. } => {
|
||||
| ClientGeneral::RequestLossyTerrainCompression { .. }
|
||||
| ClientGeneral::AcknowledgePersistenceLoadError => {
|
||||
#[cfg(feature = "tracy")]
|
||||
{
|
||||
ingame = 1.0;
|
||||
@ -1409,6 +1410,10 @@ impl Client {
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn acknolwedge_persistence_load_error(&mut self) {
|
||||
self.send_msg(ClientGeneral::AcknowledgePersistenceLoadError)
|
||||
}
|
||||
|
||||
/// Execute a single client tick, handle input and update the game state by
|
||||
/// the given duration.
|
||||
pub fn tick(
|
||||
|
@ -92,6 +92,7 @@ pub enum ClientGeneral {
|
||||
RequestLossyTerrainCompression {
|
||||
lossy_terrain_compression: bool,
|
||||
},
|
||||
AcknowledgePersistenceLoadError,
|
||||
}
|
||||
|
||||
impl ClientMsg {
|
||||
@ -130,7 +131,8 @@ impl ClientMsg {
|
||||
| ClientGeneral::RequestSiteInfo(_)
|
||||
| ClientGeneral::UnlockSkillGroup(_)
|
||||
| ClientGeneral::RequestPlayerPhysics { .. }
|
||||
| ClientGeneral::RequestLossyTerrainCompression { .. } => {
|
||||
| ClientGeneral::RequestLossyTerrainCompression { .. }
|
||||
| ClientGeneral::AcknowledgePersistenceLoadError => {
|
||||
c_type == ClientType::Game && presence.is_some()
|
||||
},
|
||||
//Always possible
|
||||
|
@ -237,6 +237,9 @@ pub struct SkillSet {
|
||||
skills: HashMap<Skill, u16>,
|
||||
pub modify_health: bool,
|
||||
pub modify_energy: bool,
|
||||
/// Used to indicate to the frontend that there was an error in loading the
|
||||
/// skillset from the database
|
||||
pub persistence_load_error: Option<SkillsPersistenceError>,
|
||||
}
|
||||
|
||||
impl Component for SkillSet {
|
||||
@ -254,6 +257,7 @@ impl Default for SkillSet {
|
||||
skills: SkillSet::initial_skills(),
|
||||
modify_health: false,
|
||||
modify_energy: false,
|
||||
persistence_load_error: None,
|
||||
};
|
||||
|
||||
// Insert default skill groups
|
||||
@ -284,6 +288,7 @@ impl SkillSet {
|
||||
skills: SkillSet::initial_skills(),
|
||||
modify_health: true,
|
||||
modify_energy: true,
|
||||
persistence_load_error: None,
|
||||
};
|
||||
|
||||
// Loops while checking the all_skills hashmap. For as long as it can find an
|
||||
@ -297,15 +302,26 @@ impl SkillSet {
|
||||
{
|
||||
// Remove valid skill group kind from the hash map so that loop eventually
|
||||
// terminates.
|
||||
if let Some(Ok(skills)) = all_skills.remove(&skill_group_kind) {
|
||||
let backup_skillset = skillset.clone();
|
||||
// Iterate over all skills and make sure that unlocking them is successful. If
|
||||
// any fail, fall back to skillset before unlocking any to allow a full respec
|
||||
if !skills
|
||||
.iter()
|
||||
.all(|skill| skillset.unlock_skill(*skill).is_ok())
|
||||
{
|
||||
skillset = backup_skillset;
|
||||
if let Some(skills_result) = all_skills.remove(&skill_group_kind) {
|
||||
match skills_result {
|
||||
Ok(skills) => {
|
||||
let backup_skillset = skillset.clone();
|
||||
// Iterate over all skills and make sure that unlocking them is successful.
|
||||
// If any fail, fall back to skillset before
|
||||
// unlocking any to allow a full respec
|
||||
if !skills
|
||||
.iter()
|
||||
.all(|skill| skillset.unlock_skill(*skill).is_ok())
|
||||
{
|
||||
skillset = backup_skillset;
|
||||
// If unlocking failed, set persistence_load_error
|
||||
skillset.persistence_load_error =
|
||||
Some(SkillsPersistenceError::SkillsUnlockFailed)
|
||||
}
|
||||
},
|
||||
Err(persistence_error) => {
|
||||
skillset.persistence_load_error = Some(persistence_error)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -549,9 +565,10 @@ pub enum SpRewardError {
|
||||
Overflow,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq, Clone, Copy, Deserialize, Serialize)]
|
||||
pub enum SkillsPersistenceError {
|
||||
HashMismatch,
|
||||
DeserializationFailure,
|
||||
SpentExpMismatch,
|
||||
SkillsUnlockFailed,
|
||||
}
|
||||
|
@ -276,6 +276,11 @@ impl Sys {
|
||||
} => {
|
||||
presence.lossy_terrain_compression = lossy_terrain_compression;
|
||||
},
|
||||
ClientGeneral::AcknowledgePersistenceLoadError => {
|
||||
skill_sets
|
||||
.get_mut(entity)
|
||||
.map(|mut skill_set| skill_set.persistence_load_error = None);
|
||||
},
|
||||
ClientGeneral::RequestCharacterList
|
||||
| ClientGeneral::CreateCharacter { .. }
|
||||
| ClientGeneral::EditCharacter { .. }
|
||||
|
@ -538,6 +538,7 @@ pub enum Event {
|
||||
ChangeAbility(usize, comp::ability::AuxiliaryAbility),
|
||||
|
||||
SettingsChange(SettingsChange),
|
||||
AcknowledgePersistenceLoadError,
|
||||
}
|
||||
|
||||
// TODO: Are these the possible layouts we want?
|
||||
@ -888,6 +889,7 @@ impl Show {
|
||||
pub struct PromptDialogSettings {
|
||||
message: String,
|
||||
affirmative_event: Event,
|
||||
negative_option: bool,
|
||||
negative_event: Option<Event>,
|
||||
outcome_via_keypress: Option<bool>,
|
||||
}
|
||||
@ -897,6 +899,7 @@ impl PromptDialogSettings {
|
||||
Self {
|
||||
message,
|
||||
affirmative_event,
|
||||
negative_option: true,
|
||||
negative_event,
|
||||
outcome_via_keypress: None,
|
||||
}
|
||||
@ -905,6 +908,11 @@ impl PromptDialogSettings {
|
||||
pub fn set_outcome_via_keypress(&mut self, outcome: bool) {
|
||||
self.outcome_via_keypress = Some(outcome);
|
||||
}
|
||||
|
||||
pub fn with_no_negative_option(mut self) -> Self {
|
||||
self.negative_option = false;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Floaters {
|
||||
@ -1129,6 +1137,47 @@ impl Hud {
|
||||
let me = client.entity();
|
||||
let poises = ecs.read_storage::<comp::Poise>();
|
||||
|
||||
// Check if there was a persistence load error of the skillset, and if so
|
||||
// display a dialog prompt
|
||||
if self.show.prompt_dialog.is_none() {
|
||||
if let Some(skill_set) = skill_sets.get(me) {
|
||||
if let Some(persistence_error) = skill_set.persistence_load_error {
|
||||
use comp::skillset::SkillsPersistenceError;
|
||||
let persistence_error = match persistence_error {
|
||||
SkillsPersistenceError::HashMismatch => {
|
||||
"There was a difference detected in one of your skill groups since \
|
||||
you last played."
|
||||
},
|
||||
SkillsPersistenceError::DeserializationFailure => {
|
||||
"There was a error in loading some of your skills from the \
|
||||
database."
|
||||
},
|
||||
SkillsPersistenceError::SpentExpMismatch => {
|
||||
"The amount of free experience you had in one of your skill groups \
|
||||
differed from when you last played."
|
||||
},
|
||||
SkillsPersistenceError::SkillsUnlockFailed => {
|
||||
"Your skills were not able to be obtained in the same order you \
|
||||
acquired them. Prerequisites or costs may have changed."
|
||||
},
|
||||
};
|
||||
let common_message = "At least one of your skill groups has been \
|
||||
invalidated. You will need to re-assign your skill \
|
||||
points to get skills.";
|
||||
let persistence_error =
|
||||
format!("{}\n{}", persistence_error, common_message);
|
||||
let prompt_dialog = PromptDialogSettings::new(
|
||||
persistence_error,
|
||||
Event::AcknowledgePersistenceLoadError,
|
||||
None,
|
||||
)
|
||||
.with_no_negative_option();
|
||||
// self.set_prompt_dialog(prompt_dialog);
|
||||
self.show.prompt_dialog = Some(prompt_dialog);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (client.pending_trade().is_some() && !self.show.trade)
|
||||
|| (client.pending_trade().is_none() && self.show.trade)
|
||||
{
|
||||
|
@ -150,35 +150,37 @@ impl<'a> Widget for PromptDialog<'a> {
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.accept_txt, ui);
|
||||
|
||||
if Button::image(self.imgs.key_button)
|
||||
.w_h(20.0, 20.0)
|
||||
.hover_image(self.imgs.close_btn_hover)
|
||||
.press_image(self.imgs.close_btn_press)
|
||||
.label(&decline_key)
|
||||
.image_color(UI_HIGHLIGHT_0)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(self.fonts.cyri.scale(16))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_y(conrod_core::position::Relative::Scalar(2.5))
|
||||
.label_x(conrod_core::position::Relative::Scalar(0.5))
|
||||
.bottom_right_with_margins_on(state.ids.bot, 4.0, 6.0)
|
||||
.set(state.ids.decline_key, ui)
|
||||
.was_clicked()
|
||||
|| self
|
||||
.prompt_dialog_settings
|
||||
.outcome_via_keypress
|
||||
.map_or(false, |outcome| !outcome)
|
||||
{
|
||||
event = Some(DialogOutcomeEvent::Negative(
|
||||
self.prompt_dialog_settings.negative_event.as_ref().cloned(),
|
||||
));
|
||||
if self.prompt_dialog_settings.negative_option {
|
||||
if Button::image(self.imgs.key_button)
|
||||
.w_h(20.0, 20.0)
|
||||
.hover_image(self.imgs.close_btn_hover)
|
||||
.press_image(self.imgs.close_btn_press)
|
||||
.label(&decline_key)
|
||||
.image_color(UI_HIGHLIGHT_0)
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(self.fonts.cyri.scale(16))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.label_y(conrod_core::position::Relative::Scalar(2.5))
|
||||
.label_x(conrod_core::position::Relative::Scalar(0.5))
|
||||
.bottom_right_with_margins_on(state.ids.bot, 4.0, 6.0)
|
||||
.set(state.ids.decline_key, ui)
|
||||
.was_clicked()
|
||||
|| self
|
||||
.prompt_dialog_settings
|
||||
.outcome_via_keypress
|
||||
.map_or(false, |outcome| !outcome)
|
||||
{
|
||||
event = Some(DialogOutcomeEvent::Negative(
|
||||
self.prompt_dialog_settings.negative_event.as_ref().cloned(),
|
||||
));
|
||||
}
|
||||
Text::new("Decline")
|
||||
.bottom_left_with_margins_on(state.ids.decline_key, 4.0, -65.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(18))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.decline_txt, ui);
|
||||
}
|
||||
Text::new("Decline")
|
||||
.bottom_left_with_margins_on(state.ids.decline_key, 4.0, -65.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(18))
|
||||
.color(TEXT_COLOR)
|
||||
.set(state.ids.decline_txt, ui);
|
||||
|
||||
// Prompt Description
|
||||
Text::new(&self.prompt_dialog_settings.message)
|
||||
|
@ -1428,6 +1428,11 @@ impl PlayState for SessionState {
|
||||
HudEvent::SettingsChange(settings_change) => {
|
||||
settings_change.process(global_state, self);
|
||||
},
|
||||
HudEvent::AcknowledgePersistenceLoadError => {
|
||||
self.client
|
||||
.borrow_mut()
|
||||
.acknolwedge_persistence_load_error();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user