Merge branch 'james/merchant-tell' into 'master'

Make merchants /tell instead of /say

See merge request veloren/veloren!2293
This commit is contained in:
Marcel 2021-05-11 17:26:22 +00:00
commit 7e1f32c283
6 changed files with 78 additions and 28 deletions

View File

@ -102,6 +102,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Cultist Husk no longer drops weapons and armor
- Animal Trainers now spawn in tier-5 dungeon and not in tier-3
- Reworked clay golem to have unique attacks.
- Merchants now use `/tell` instead of `/say` to communicate prices
### Removed

View File

@ -2216,20 +2216,6 @@ impl Client {
let comp::ChatMsg {
chat_type, message, ..
} = &msg;
let alias_of_uid = |uid| {
self.player_list
.get(uid)
.map_or("<?>".to_string(), |player_info| {
if player_info.is_moderator {
format!(
"MOD - {}",
self.personalize_alias(*uid, player_info.player_alias.clone())
)
} else {
self.personalize_alias(*uid, player_info.player_alias.clone())
}
})
};
let name_of_uid = |uid| {
let ecs = self.state.ecs();
(
@ -2240,6 +2226,21 @@ impl Client {
.find(|(_, u)| u == &uid)
.map(|(c, _)| c.name.clone())
};
let alias_of_uid = |uid| {
self.player_list.get(uid).map_or(
name_of_uid(uid).unwrap_or_else(|| "<?>".to_string()),
|player_info| {
if player_info.is_moderator {
format!(
"MOD - {}",
self.personalize_alias(*uid, player_info.player_alias.clone())
)
} else {
self.personalize_alias(*uid, player_info.player_alias.clone())
}
},
)
};
let message_format = |uid, message, group| {
let alias = alias_of_uid(uid);
let name = if character_name {
@ -2401,6 +2402,15 @@ impl Client {
// by server (due to not having a Pos) for chat-cli
comp::ChatType::Npc(_uid, _r) => "".to_string(),
comp::ChatType::NpcSay(uid, _r) => message_format(uid, message, None),
comp::ChatType::NpcTell(from, to, _r) => {
let from_alias = alias_of_uid(from);
let to_alias = alias_of_uid(to);
if Some(*from) == self.uid() {
format!("To [{}]: {}", to_alias, message)
} else {
format!("From [{}]: {}", from_alias, message)
}
},
comp::ChatType::Meta => message.to_string(),
}
}

View File

@ -108,6 +108,9 @@ pub enum ChatType<G> {
Npc(Uid, u16),
/// From NPCs but in the chat for clients in the near vicinity
NpcSay(Uid, u16),
/// From NPCs but in the chat for a specific client. Shows a chat bubble.
/// (from, to, localization variant)
NpcTell(Uid, Uid, u16),
/// Anything else
Meta,
// Looted items
@ -152,6 +155,11 @@ impl<G> GenericChatMsg<G> {
Self { chat_type, message }
}
pub fn npc_tell(from: Uid, to: Uid, message: String) -> Self {
let chat_type = ChatType::NpcTell(from, to, rand::random());
Self { chat_type, message }
}
pub fn map_group<T>(self, mut f: impl FnMut(G) -> T) -> GenericChatMsg<T> {
let chat_type = match self.chat_type {
ChatType::Online(a) => ChatType::Online(a),
@ -170,6 +178,7 @@ impl<G> GenericChatMsg<G> {
ChatType::World(a) => ChatType::World(a),
ChatType::Npc(a, b) => ChatType::Npc(a, b),
ChatType::NpcSay(a, b) => ChatType::NpcSay(a, b),
ChatType::NpcTell(a, b, c) => ChatType::NpcTell(a, b, c),
ChatType::Meta => ChatType::Meta,
};
@ -189,7 +198,9 @@ impl<G> GenericChatMsg<G> {
pub fn to_bubble(&self) -> Option<(SpeechBubble, Uid)> {
let icon = self.icon();
if let ChatType::Npc(from, r) | ChatType::NpcSay(from, r) = self.chat_type {
if let ChatType::Npc(from, r) | ChatType::NpcSay(from, r) | ChatType::NpcTell(from, _, r) =
self.chat_type
{
Some((SpeechBubble::npc_new(&self.message, r, icon), from))
} else {
self.uid()
@ -215,6 +226,7 @@ impl<G> GenericChatMsg<G> {
ChatType::World(_u) => SpeechBubbleType::World,
ChatType::Npc(_u, _r) => SpeechBubbleType::None,
ChatType::NpcSay(_u, _r) => SpeechBubbleType::Say,
ChatType::NpcTell(_f, _t, _) => SpeechBubbleType::Say,
ChatType::Meta => SpeechBubbleType::None,
}
}
@ -237,6 +249,7 @@ impl<G> GenericChatMsg<G> {
ChatType::World(u) => Some(*u),
ChatType::Npc(u, _r) => Some(*u),
ChatType::NpcSay(u, _r) => Some(*u),
ChatType::NpcTell(u, _t, _r) => Some(*u),
ChatType::Meta => None,
}
}

View File

@ -654,6 +654,15 @@ impl StateExt for State {
}
}
},
comp::ChatType::NpcTell(from, to, _r) => {
for (client, uid) in
(&ecs.read_storage::<Client>(), &ecs.read_storage::<Uid>()).join()
{
if uid == from || uid == to {
client.send_fallible(ServerGeneral::ChatMsg(resolved_msg.clone()));
}
}
},
comp::ChatType::FactionMeta(s) | comp::ChatType::Faction(_, s) => {
for (client, faction) in (
&ecs.read_storage::<Client>(),

View File

@ -1276,9 +1276,21 @@ impl<'a> AgentData<'a> {
"That only covers {:.1}% of my costs!",
balance0 / balance1 * 100.0
);
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc_say(
*self.uid, msg,
)));
if let Some(tgt_data) = &agent.target {
if let Some(with) = read_data.uids.get(tgt_data.target) {
event_emitter.emit(ServerEvent::Chat(
UnresolvedChatMsg::npc_tell(*self.uid, *with, msg),
));
} else {
event_emitter.emit(ServerEvent::Chat(
UnresolvedChatMsg::npc_say(*self.uid, msg),
));
}
} else {
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc_say(
*self.uid, msg,
)));
}
}
if pending.phase != TradePhase::Mutate {
// we got into the review phase but without balanced goods, decline
@ -1461,16 +1473,20 @@ impl<'a> AgentData<'a> {
&& !invulnerability_is_in_buffs(read_data.buffs.get(*e))
&& (try_owner_alignment(self.alignment, &read_data).and_then(|a| try_owner_alignment(*e_alignment, &read_data).map(|b| a.hostile_towards(*b))).unwrap_or(false) || (
if let Some(rtsim_entity) = &self.rtsim_entity {
if rtsim_entity.brain.remembers_fight_with_character(&e_stats.name) {
agent.rtsim_controller.events.push(
RtSimEvent::AddMemory(Memory {
item: MemoryItem::CharacterFight { name: e_stats.name.clone() },
time_to_forget: read_data.time.0 + 300.0,
})
);
let msg = format!("{}! How dare you cross me again!", e_stats.name.clone());
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg)));
true
if agent.behavior.can(BehaviorCapability::SPEAK) {
if rtsim_entity.brain.remembers_fight_with_character(&e_stats.name) {
agent.rtsim_controller.events.push(
RtSimEvent::AddMemory(Memory {
item: MemoryItem::CharacterFight { name: e_stats.name.clone() },
time_to_forget: read_data.time.0 + 300.0,
})
);
let msg = format!("{}! How dare you cross me again!", e_stats.name.clone());
event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg)));
true
} else {
false
}
} else {
false
}

View File

@ -619,6 +619,7 @@ fn render_chat_line(chat_type: &ChatType<String>, imgs: &Imgs) -> (Color, conrod
ChatType::World(_uid) => (WORLD_COLOR, imgs.chat_world_small),
ChatType::Npc(_uid, _r) => panic!("NPCs can't talk!"), // Should be filtered by hud/mod.rs
ChatType::NpcSay(_uid, _r) => (SAY_COLOR, imgs.chat_say_small),
ChatType::NpcTell(_from, _to, _r) => (TELL_COLOR, imgs.chat_tell_small),
ChatType::Meta => (INFO_COLOR, imgs.chat_command_info_small),
}
}