Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions korangar-networking/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,45 @@ pub enum NetworkEvent {
account_id: AccountId,
character_id: CharacterId,
},
PartyInvite {
party_id: PartyId,
party_name: String,
},
SetPartyInfo {
party_name: String,
members: Vec<PartyMember>,
},
PartyMemberAdded {
party_name: String,
member: PartyMember,
},
PartyMemberLeft {
account_id: AccountId,
player_name: String,
reason: PartyMemberLeaveReason,
},
PartyLeaderChanged {
previous_leader: AccountId,
new_leader: AccountId,
},
PartyMemberHealth {
account_id: AccountId,
health_points: u32,
maximum_health_points: u32,
},
PartyMemberPosition {
account_id: AccountId,
x: u16,
y: u16,
},
PartyMemberJobLevel {
account_id: AccountId,
job_id: u16,
level: u16,
},
PartyMemberDead {
account_id: AccountId,
},
SetHotkeyData {
tab: HotbarTab,
hotkeys: Vec<HotkeyState>,
Expand Down
40 changes: 40 additions & 0 deletions korangar-networking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,46 @@ where
}
}

pub fn create_party(&mut self, party_name: String) -> Result<(), NotConnectedError> {
match self.map_server_packet_version()? {
SupportedPacketVersion::_20220406 => self.send_map_server_packet(CreatePartyPacket::new(party_name, 0, 0)),
}
}

pub fn invite_player_to_party(&mut self, player_name: String) -> Result<(), NotConnectedError> {
match self.map_server_packet_version()? {
SupportedPacketVersion::_20220406 => self.send_map_server_packet(InvitePlayerToPartyPacket::new(player_name)),
}
}

pub fn reject_party_invite(&mut self, party_id: PartyId) -> Result<(), NotConnectedError> {
match self.map_server_packet_version()? {
SupportedPacketVersion::_20220406 => {
self.send_map_server_packet(PartyInviteResponsePacket::new(party_id, PartyInviteResponse::Reject))
}
}
}

pub fn accept_party_invite(&mut self, party_id: PartyId) -> Result<(), NotConnectedError> {
match self.map_server_packet_version()? {
SupportedPacketVersion::_20220406 => {
self.send_map_server_packet(PartyInviteResponsePacket::new(party_id, PartyInviteResponse::Accept))
}
}
}

pub fn leave_party(&mut self) -> Result<(), NotConnectedError> {
match self.map_server_packet_version()? {
SupportedPacketVersion::_20220406 => self.send_map_server_packet(LeavePartyPacket::new()),
}
}

pub fn expel_party_member(&mut self, account_id: AccountId, player_name: String) -> Result<(), NotConnectedError> {
match self.map_server_packet_version()? {
SupportedPacketVersion::_20220406 => self.send_map_server_packet(RemovePartyMemberPacket::new(account_id, player_name)),
}
}

pub fn set_hotkey_data(&mut self, tab: HotbarTab, index: HotbarSlot, hotkey_data: HotkeyData) -> Result<(), NotConnectedError> {
match self.map_server_packet_version()? {
SupportedPacketVersion::_20220406 => self.send_map_server_packet(SetHotkeyData2Packet::new(tab, index, hotkey_data)),
Expand Down
153 changes: 151 additions & 2 deletions korangar-networking/src/packet_versions/version_20220406.rs
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,38 @@ where
},
})?;
packet_handler.register_noop::<UseSkillSuccessPacket>()?;
packet_handler.register_noop::<ToUseSkillSuccessPacket>()?;
packet_handler.register(|packet: ToUseSkillSuccessPacket| {
// The server reports skill use failures through this packet. A flag of
// zero means the skill failed. The causes match rAthena's
// `useskill_fail_cause` enum.
const NOVICE_BASIC_SKILL: SkillId = SkillId(1);

if packet.flag != 0 {
return None;
}

let text = match packet.cause {
0 if packet.skill_id == NOVICE_BASIC_SKILL => format!("You need Basic Skill level {} to do that.", packet.btype),
0 => "Your skill level is too low.".to_owned(),
1 => "Not enough SP.".to_owned(),
2 => "Not enough HP.".to_owned(),
3 => "You are missing a required item.".to_owned(),
4 => "The skill is still on cooldown.".to_owned(),
5 => "Not enough Zeny.".to_owned(),
6 => "This skill cannot be used with your current weapon.".to_owned(),
7 => "You need a Red Gemstone.".to_owned(),
8 => "You need a Blue Gemstone.".to_owned(),
9 => "You are carrying too much weight.".to_owned(),
11 => "This skill cannot reach the target.".to_owned(),
23 => "The skill conditions are not met.".to_owned(),
_ => "The skill failed.".to_owned(),
};

Some(NetworkEvent::ChatMessage {
text,
color: MessageColor::Error,
})
})?;
packet_handler.register(|packet: NotifySkillUnitPacket| {
let NotifySkillUnitPacket {
entity_id,
Expand Down Expand Up @@ -797,7 +828,125 @@ where
account_id: packet.account_id,
character_id: packet.character_id,
})?;
packet_handler.register_noop::<PartyInvitePacket>()?;
packet_handler.register(|packet: PartyInvitePacket| NetworkEvent::PartyInvite {
party_id: packet.party_id,
party_name: packet.party_name,
})?;
packet_handler.register(|packet: CreatePartyResultPacket| {
let text = match packet.result {
CreatePartyResult::Success => "Party created.".to_owned(),
CreatePartyResult::NameAlreadyExists => "A party with that name already exists.".to_owned(),
CreatePartyResult::AlreadyInParty => "You are already in a party.".to_owned(),
CreatePartyResult::NotAllowedOnMap => "You cannot create a party on this map.".to_owned(),
};

NetworkEvent::ChatMessage {
text,
color: MessageColor::Information,
}
})?;
packet_handler.register(|packet: PartyInviteResultPacket| {
let text = match packet.result {
PartyInviteResult::AlreadyInParty => format!("{} is already in a party.", packet.player_name),
PartyInviteResult::Rejected => format!("{} rejected your party invitation.", packet.player_name),
PartyInviteResult::Accepted => format!("{} accepted your party invitation.", packet.player_name),
PartyInviteResult::PartyFull => "Your party is full.".to_owned(),
PartyInviteResult::DuplicateMember => format!("{} is already in your party.", packet.player_name),
PartyInviteResult::JoinMessageRefused => format!("{} is blocking party invitations.", packet.player_name),
PartyInviteResult::UnknownError => "Party invitation failed.".to_owned(),
PartyInviteResult::UnknownCharacter => "That character is not online.".to_owned(),
PartyInviteResult::InvalidMapProperty | PartyInviteResult::InvalidMapPropertySelf => {
"Party invitations are not allowed on this map.".to_owned()
}
PartyInviteResult::MemorialDungeon => "Party invitations are not allowed in a Memorial Dungeon.".to_owned(),
PartyInviteResult::LevelMismatch => "Party invitation failed due to a level difference.".to_owned(),
};

NetworkEvent::ChatMessage {
text,
color: MessageColor::Information,
}
})?;
packet_handler.register(|packet: PartyMemberListPacket| NetworkEvent::SetPartyInfo {
party_name: packet.party_name,
members: packet.members,
})?;
packet_handler.register(|packet: PartyMemberAddedPacket| {
let PartyMemberAddedPacket {
account_id,
character_id,
leader,
job_id,
level,
offline,
party_name,
player_name,
map_name,
..
} = packet;

NetworkEvent::PartyMemberAdded {
party_name,
member: PartyMember {
account_id,
character_id,
name: player_name,
map_name,
leader: leader.min(1) as u8,
offline,
job_id,
level,
},
}
})?;
packet_handler.register(|packet: PartyMemberLeftPacket| NetworkEvent::PartyMemberLeft {
account_id: packet.account_id,
player_name: packet.player_name,
reason: packet.reason,
})?;
packet_handler.register_noop::<UpdatePartyOptionsPacket>()?;
packet_handler.register(|packet: PartyMemberPositionPacket| {
// A coordinate of 65535 means the position is unavailable.
match packet.x == u16::MAX || packet.y == u16::MAX {
true => None,
false => Some(NetworkEvent::PartyMemberPosition {
account_id: packet.account_id,
x: packet.x,
y: packet.y,
}),
}
})?;
packet_handler.register(|packet: PartyMemberHealthPacket| NetworkEvent::PartyMemberHealth {
account_id: packet.account_id,
health_points: packet.health_points,
maximum_health_points: packet.maximum_health_points,
})?;
packet_handler.register(|packet: PartyMemberDeadPacket| match packet.is_dead != 0 {
true => Some(NetworkEvent::PartyMemberDead {
account_id: packet.account_id,
}),
false => None,
})?;
packet_handler.register(|packet: PartyMemberJobLevelPacket| NetworkEvent::PartyMemberJobLevel {
account_id: packet.account_id,
job_id: packet.job_id,
level: packet.level,
})?;
packet_handler.register_noop::<UseSkillAckPacket>()?;
packet_handler.register_noop::<NpcSpriteChangePacket>()?;
packet_handler.register(|packet: PartyLeaderChangedPacket| NetworkEvent::PartyLeaderChanged {
previous_leader: packet.previous_leader,
new_leader: packet.new_leader,
})?;
packet_handler.register(|packet: PartyChatMessagePacket| NetworkEvent::ChatMessage {
text: packet.message,
color: MessageColor::Rgb {
red: 220,
green: 200,
blue: 30,
},
})?;
packet_handler.register_noop::<PartyItemPickupPacket>()?;
packet_handler.register_noop::<StatusChangeSequencePacket>()?;
packet_handler.register_noop::<ReputationPacket>()?;
packet_handler.register_noop::<ClanInfoPacket>()?;
Expand Down
6 changes: 6 additions & 0 deletions korangar/archive/data/languages/de-DE.ron
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
stats_button_text: "Attribute",
skill_tree_button_text: "Fertigkeitenbaum",
friend_list_button_text: "Freundesliste",
party_button_text: "Gruppe",
menu_button_text: "Menü",
chat_window_title: "Chat",
chat_text_box_message: "Gib einen Nachricht oder ein Kommando ein",
Expand All @@ -40,6 +41,11 @@
friend_list_window_title: "Freundesliste",
friend_list_text_box_message: "Freund durch Name hinzufügen",
remove_button_text: "Entfernen",
party_window_title: "Gruppe",
party_create_text_box_message: "Gruppe mit Namen erstellen",
party_invite_text_box_message: "Spieler durch Name einladen",
party_leave_button_text: "Gruppe verlassen",
party_expel_button_text: "Entfernen",
hotbar_window_title: "Schnellzugriff",
inventory_window_title: "Inventar",
respawn_window_title: "Wiederbelebungsmenü",
Expand Down
6 changes: 6 additions & 0 deletions korangar/archive/data/languages/en-US.ron
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
stats_button_text: "Stats",
skill_tree_button_text: "Skill tree",
friend_list_button_text: "Friend list",
party_button_text: "Party",
menu_button_text: "Menu",
chat_window_title: "Chat",
chat_text_box_message: "Enter chat message or command",
Expand All @@ -40,6 +41,11 @@
friend_list_window_title: "Friend List",
friend_list_text_box_message: "Add friend by name",
remove_button_text: "Remove",
party_window_title: "Party",
party_create_text_box_message: "Create party by name",
party_invite_text_box_message: "Invite player by name",
party_leave_button_text: "Leave party",
party_expel_button_text: "Expel",
hotbar_window_title: "Hotbar",
inventory_window_title: "Inventory",
respawn_window_title: "Respawn Menu",
Expand Down
35 changes: 33 additions & 2 deletions korangar/src/input/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use korangar_debug::profiling::FrameMeasurement;
use korangar_interface::event::{ClickHandler, Event, EventQueue};
use korangar_networking::{InventoryItem, ShopItem};
use ragnarok_packets::{
AccountId, BuyOrSellOption, CharacterId, CharacterServerInformation, EntityId, HotbarSlot, ShopId, SkillId, SoldItemInformation,
StatUpType, TilePosition,
AccountId, BuyOrSellOption, CharacterId, CharacterServerInformation, EntityId, HotbarSlot, PartyId, ShopId, SkillId,
SoldItemInformation, StatUpType, TilePosition,
};
use rust_state::State;

Expand Down Expand Up @@ -75,6 +75,8 @@ pub enum InputEvent {
ToggleAudioSettingsWindow,
/// Open or close the friend list window. Only works while playing.
ToggleFriendListWindow,
/// Open or close the party window. Only works while playing.
TogglePartyWindow,
/// Close the most recently opened or clicked closable window.
CloseTopWindow,
/// Toggle if the user interface should be rendered or not.
Expand Down Expand Up @@ -205,6 +207,35 @@ pub enum InputEvent {
/// Character id of the requestor.
character_id: CharacterId,
},
/// Create a new party.
CreateParty {
/// Name of the party to create.
party_name: String,
},
/// Invite a player to the current party.
InvitePlayerToParty {
/// Name of the character to invite.
player_name: String,
},
/// Reject a pending party invitation.
RejectPartyInvite {
/// Id of the inviting party.
party_id: PartyId,
},
/// Accept a pending party invitation.
AcceptPartyInvite {
/// Id of the inviting party.
party_id: PartyId,
},
/// Leave the current party.
LeaveParty,
/// Expel a member from the current party. Only works as party leader.
ExpelPartyMember {
/// Account id of the member to expel.
account_id: AccountId,
/// Name of the member to expel.
player_name: String,
},
/// Buy items from a shop.
BuyItems {
/// Items to buy.
Expand Down
4 changes: 4 additions & 0 deletions korangar/src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ impl InputSystem {
events.push(InputEvent::ToggleFriendListWindow);
}

if alt_down && self.get_key(KeyCode::KeyP).pressed() {
events.push(InputEvent::TogglePartyWindow);
}

if alt_down && self.get_key(KeyCode::KeyQ).pressed() {
events.push(InputEvent::ToggleEquipmentWindow);
}
Expand Down
4 changes: 4 additions & 0 deletions korangar/src/interface/windows/character_overview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ where
text: client_state().localization().friend_list_button_text(),
event: InputEvent::ToggleFriendListWindow,
},
button! {
text: client_state().localization().party_button_text(),
event: InputEvent::TogglePartyWindow,
},
button! {
text: client_state().localization().menu_button_text(),
event: InputEvent::ToggleMenuWindow,
Expand Down
Loading