Finalize shops, interactions and world data
All checks were successful
Smoke tests / Build and smoke test (push) Successful in 1m53s
All checks were successful
Smoke tests / Build and smoke test (push) Successful in 1m53s
This commit is contained in:
109
src/commands.rs
109
src/commands.rs
@@ -1476,11 +1476,8 @@ async fn cmd_spells(pid: usize, state: &SharedState) -> CommandResult {
|
||||
|
||||
async fn cmd_shop(pid: usize, args: &str, state: &SharedState) -> CommandResult {
|
||||
let mut st = state.lock().await;
|
||||
let (conn, rid) = match st.players.get_mut(&pid) {
|
||||
Some(c) => {
|
||||
let rid = c.player.room_id.clone();
|
||||
(c, rid)
|
||||
}
|
||||
let rid = match st.players.get(&pid) {
|
||||
Some(c) => c.player.room_id.clone(),
|
||||
None => return simple("Error\r\n"),
|
||||
};
|
||||
|
||||
@@ -1543,42 +1540,48 @@ async fn cmd_shop(pid: usize, args: &str, state: &SharedState) -> CommandResult
|
||||
if subargs.is_empty() {
|
||||
return simple("Buy what?\r\n");
|
||||
}
|
||||
let npc = st.world.get_npc(&merchant_id).unwrap();
|
||||
let shop = npc.shop.as_ref().unwrap().clone();
|
||||
let (shop, _npc_name) = {
|
||||
let npc = st.world.get_npc(&merchant_id).unwrap();
|
||||
(npc.shop.as_ref().unwrap().clone(), npc.name.clone())
|
||||
};
|
||||
|
||||
let item_to_buy = shop.sells.iter().find(|id| {
|
||||
let item_id = shop.sells.iter().find(|id| {
|
||||
if let Some(obj) = st.world.get_object(*id) {
|
||||
obj.name.to_lowercase().contains(&subargs.to_lowercase())
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
}).cloned();
|
||||
|
||||
if let Some(item_id) = item_to_buy {
|
||||
let obj = st.world.get_object(item_id).unwrap().clone();
|
||||
if let Some(id) = item_id {
|
||||
let obj = st.world.get_object(&id).unwrap().clone();
|
||||
let total_copper = (obj.value_gold * 10000 + obj.value_silver * 100 + obj.value_copper) as f32;
|
||||
let price_copper = (total_copper * shop.markup).ceil() as i32;
|
||||
|
||||
let player_total_copper = conn.player.gold * 10000 + conn.player.silver * 100 + conn.player.copper;
|
||||
if player_total_copper < price_copper {
|
||||
return simple("You don't have enough money.\r\n");
|
||||
if let Some(conn) = st.players.get_mut(&pid) {
|
||||
let player_total_copper = conn.player.gold * 10000 + conn.player.silver * 100 + conn.player.copper;
|
||||
if player_total_copper < price_copper {
|
||||
return simple("You don't have enough money.\r\n");
|
||||
}
|
||||
|
||||
// Deduct money
|
||||
let mut remaining = player_total_copper - price_copper;
|
||||
conn.player.gold = remaining / 10000;
|
||||
remaining %= 10000;
|
||||
conn.player.silver = remaining / 100;
|
||||
conn.player.copper = remaining % 100;
|
||||
|
||||
// Add to inventory
|
||||
conn.player.inventory.push(obj.clone());
|
||||
|
||||
simple(&format!(
|
||||
"You buy {} for {} copper equivalents.\r\n",
|
||||
ansi::color(ansi::CYAN, &obj.name),
|
||||
price_copper
|
||||
))
|
||||
} else {
|
||||
simple("Error\r\n")
|
||||
}
|
||||
|
||||
// Deduct money
|
||||
let mut remaining = player_total_copper - price_copper;
|
||||
conn.player.gold = remaining / 10000;
|
||||
remaining %= 10000;
|
||||
conn.player.silver = remaining / 100;
|
||||
conn.player.copper = remaining % 100;
|
||||
|
||||
// Add to inventory
|
||||
conn.player.inventory.push(obj.clone());
|
||||
|
||||
simple(&format!(
|
||||
"You buy {} for {} copper equivalents.\r\n",
|
||||
ansi::color(ansi::CYAN, &obj.name),
|
||||
price_copper
|
||||
))
|
||||
} else {
|
||||
simple("The merchant doesn't sell that.\r\n")
|
||||
}
|
||||
@@ -1588,14 +1591,16 @@ async fn cmd_shop(pid: usize, args: &str, state: &SharedState) -> CommandResult
|
||||
if subargs.is_empty() {
|
||||
return simple("Sell what?\r\n");
|
||||
}
|
||||
let npc = st.world.get_npc(&merchant_id).unwrap();
|
||||
let shop = npc.shop.as_ref().unwrap().clone();
|
||||
let shop = st.world.get_npc(&merchant_id).unwrap().shop.as_ref().unwrap().clone();
|
||||
|
||||
let item_idx = conn.player.inventory.iter().position(|o| o.name.to_lowercase().contains(&subargs.to_lowercase()));
|
||||
let item_info = if let Some(conn) = st.players.get(&pid) {
|
||||
conn.player.inventory.iter().position(|o| o.name.to_lowercase().contains(&subargs.to_lowercase()))
|
||||
.map(|idx| (idx, conn.player.inventory[idx].clone()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some(idx) = item_idx {
|
||||
let obj = conn.player.inventory[idx].clone();
|
||||
|
||||
if let Some((idx, obj)) = item_info {
|
||||
// Check if merchant buys this kind of item
|
||||
let can_sell = shop.buys.is_empty() || shop.buys.iter().any(|k| {
|
||||
if let Some(kind) = &obj.kind {
|
||||
@@ -1612,22 +1617,26 @@ async fn cmd_shop(pid: usize, args: &str, state: &SharedState) -> CommandResult
|
||||
let total_copper = (obj.value_gold * 10000 + obj.value_silver * 100 + obj.value_copper) as f32;
|
||||
let price_copper = (total_copper * shop.markdown).floor() as i32;
|
||||
|
||||
// Add money to player
|
||||
let mut player_total_copper = conn.player.gold * 10000 + conn.player.silver * 100 + conn.player.copper;
|
||||
player_total_copper += price_copper;
|
||||
conn.player.gold = player_total_copper / 10000;
|
||||
player_total_copper %= 10000;
|
||||
conn.player.silver = player_total_copper / 100;
|
||||
conn.player.copper = player_total_copper % 100;
|
||||
if let Some(conn) = st.players.get_mut(&pid) {
|
||||
// Add money to player
|
||||
let mut player_total_copper = conn.player.gold * 10000 + conn.player.silver * 100 + conn.player.copper;
|
||||
player_total_copper += price_copper;
|
||||
conn.player.gold = player_total_copper / 10000;
|
||||
player_total_copper %= 10000;
|
||||
conn.player.silver = player_total_copper / 100;
|
||||
conn.player.copper = player_total_copper % 100;
|
||||
|
||||
// Remove from inventory
|
||||
conn.player.inventory.remove(idx);
|
||||
// Remove from inventory
|
||||
conn.player.inventory.remove(idx);
|
||||
|
||||
simple(&format!(
|
||||
"You sell {} for {} copper equivalents.\r\n",
|
||||
ansi::color(ansi::CYAN, &obj.name),
|
||||
price_copper
|
||||
))
|
||||
simple(&format!(
|
||||
"You sell {} for {} copper equivalents.\r\n",
|
||||
ansi::color(ansi::CYAN, &obj.name),
|
||||
price_copper
|
||||
))
|
||||
} else {
|
||||
simple("Error\r\n")
|
||||
}
|
||||
} else {
|
||||
simple("You don't have that in your inventory.\r\n")
|
||||
}
|
||||
|
||||
24
src/db.rs
24
src/db.rs
@@ -78,7 +78,7 @@ impl SqliteDb {
|
||||
.map_err(|e| format!("Failed to set pragmas: {e}"))?;
|
||||
|
||||
conn.execute_batch(
|
||||
CREATE TABLE IF NOT EXISTS players (
|
||||
r#"CREATE TABLE IF NOT EXISTS players (
|
||||
name TEXT PRIMARY KEY,
|
||||
race_id TEXT NOT NULL,
|
||||
class_id TEXT NOT NULL,
|
||||
@@ -89,8 +89,8 @@ impl SqliteDb {
|
||||
max_hp INTEGER NOT NULL,
|
||||
attack INTEGER NOT NULL,
|
||||
defense INTEGER NOT NULL,
|
||||
inventory_json TEXT NOT NULL DEFAULT '[]',
|
||||
equipped_json TEXT NOT NULL DEFAULT '{}',
|
||||
inventory_json TEXT NOT NULL DEFAULT "[]",
|
||||
equipped_json TEXT NOT NULL DEFAULT "{}",
|
||||
is_admin INTEGER NOT NULL DEFAULT 0,
|
||||
mana INTEGER NOT NULL DEFAULT 0,
|
||||
max_mana INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -127,13 +127,13 @@ impl SqliteDb {
|
||||
guild_id TEXT NOT NULL,
|
||||
level INTEGER NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (player_name, guild_id)
|
||||
);",
|
||||
);"#,
|
||||
)
|
||||
.map_err(|e| format!("Failed to create tables: {e}"))?;
|
||||
|
||||
// Migration: add is_admin column if missing
|
||||
let has_admin: bool = conn
|
||||
.prepare("SELECT COUNT(*) FROM pragma_table_info('players') WHERE name='is_admin'")
|
||||
.prepare(r#"SELECT COUNT(*) FROM pragma_table_info("players") WHERE name="is_admin""#)
|
||||
.and_then(|mut s| s.query_row([], |r| r.get::<_, i32>(0)))
|
||||
.map(|c| c > 0)
|
||||
.unwrap_or(false);
|
||||
@@ -146,34 +146,34 @@ impl SqliteDb {
|
||||
|
||||
// Migration: equipped_weapon_json/equipped_armor_json -> equipped_json
|
||||
let has_old_weapon: bool = conn
|
||||
.prepare("SELECT COUNT(*) FROM pragma_table_info('players') WHERE name='equipped_weapon_json'")
|
||||
.prepare(r#"SELECT COUNT(*) FROM pragma_table_info("players") WHERE name="equipped_weapon_json""#)
|
||||
.and_then(|mut s| s.query_row([], |r| r.get::<_, i32>(0)))
|
||||
.map(|c| c > 0)
|
||||
.unwrap_or(false);
|
||||
let has_equipped: bool = conn
|
||||
.prepare("SELECT COUNT(*) FROM pragma_table_info('players') WHERE name='equipped_json'")
|
||||
.prepare(r#"SELECT COUNT(*) FROM pragma_table_info("players") WHERE name="equipped_json""#)
|
||||
.and_then(|mut s| s.query_row([], |r| r.get::<_, i32>(0)))
|
||||
.map(|c| c > 0)
|
||||
.unwrap_or(false);
|
||||
if has_old_weapon && !has_equipped {
|
||||
let _ = conn.execute(
|
||||
"ALTER TABLE players ADD COLUMN equipped_json TEXT NOT NULL DEFAULT '{}'",
|
||||
r#"ALTER TABLE players ADD COLUMN equipped_json TEXT NOT NULL DEFAULT "{}"#,
|
||||
[],
|
||||
);
|
||||
log::info!("Migrating equipped_weapon_json/equipped_armor_json to equipped_json...");
|
||||
let _ = conn.execute_batch(
|
||||
"UPDATE players SET equipped_json = '{}' WHERE equipped_weapon_json IS NULL AND equipped_armor_json IS NULL;"
|
||||
r#"UPDATE players SET equipped_json = "{}" WHERE equipped_weapon_json IS NULL AND equipped_armor_json IS NULL;"#
|
||||
);
|
||||
} else if !has_equipped {
|
||||
let _ = conn.execute(
|
||||
"ALTER TABLE players ADD COLUMN equipped_json TEXT NOT NULL DEFAULT '{}'",
|
||||
r#"ALTER TABLE players ADD COLUMN equipped_json TEXT NOT NULL DEFAULT "{}"#,
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
// Migration: add mana/endurance columns
|
||||
let has_mana: bool = conn
|
||||
.prepare("SELECT COUNT(*) FROM pragma_table_info('players') WHERE name='mana'")
|
||||
.prepare(r#"SELECT COUNT(*) FROM pragma_table_info("players") WHERE name="mana""#)
|
||||
.and_then(|mut s| s.query_row([], |r| r.get::<_, i32>(0)))
|
||||
.map(|c| c > 0)
|
||||
.unwrap_or(false);
|
||||
@@ -186,7 +186,7 @@ impl SqliteDb {
|
||||
|
||||
// Migration: add currency columns
|
||||
let has_gold: bool = conn
|
||||
.prepare("SELECT COUNT(*) FROM pragma_table_info('players') WHERE name='gold'")
|
||||
.prepare(r#"SELECT COUNT(*) FROM pragma_table_info("players") WHERE name="gold""#)
|
||||
.and_then(|mut s| s.query_row([], |r| r.get::<_, i32>(0)))
|
||||
.map(|c| c > 0)
|
||||
.unwrap_or(false);
|
||||
|
||||
Reference in New Issue
Block a user