UI notifying player that their skillset has been invalidated.

This commit is contained in:
Sam
2021-12-04 00:03:26 -05:00
parent 0a9f3381f5
commit efbc5f9b75
7 changed files with 125 additions and 40 deletions

View File

@ -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(

View File

@ -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

View File

@ -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,
}

View File

@ -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 { .. }

View File

@ -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)
{

View File

@ -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)

View File

@ -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();
},
}
}