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 {
|
async fn cmd_shop(pid: usize, args: &str, state: &SharedState) -> CommandResult {
|
||||||
let mut st = state.lock().await;
|
let mut st = state.lock().await;
|
||||||
let (conn, rid) = match st.players.get_mut(&pid) {
|
let rid = match st.players.get(&pid) {
|
||||||
Some(c) => {
|
Some(c) => c.player.room_id.clone(),
|
||||||
let rid = c.player.room_id.clone();
|
|
||||||
(c, rid)
|
|
||||||
}
|
|
||||||
None => return simple("Error\r\n"),
|
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() {
|
if subargs.is_empty() {
|
||||||
return simple("Buy what?\r\n");
|
return simple("Buy what?\r\n");
|
||||||
}
|
}
|
||||||
let npc = st.world.get_npc(&merchant_id).unwrap();
|
let (shop, _npc_name) = {
|
||||||
let shop = npc.shop.as_ref().unwrap().clone();
|
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) {
|
if let Some(obj) = st.world.get_object(*id) {
|
||||||
obj.name.to_lowercase().contains(&subargs.to_lowercase())
|
obj.name.to_lowercase().contains(&subargs.to_lowercase())
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
});
|
}).cloned();
|
||||||
|
|
||||||
if let Some(item_id) = item_to_buy {
|
if let Some(id) = item_id {
|
||||||
let obj = st.world.get_object(item_id).unwrap().clone();
|
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 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 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 let Some(conn) = st.players.get_mut(&pid) {
|
||||||
if player_total_copper < price_copper {
|
let player_total_copper = conn.player.gold * 10000 + conn.player.silver * 100 + conn.player.copper;
|
||||||
return simple("You don't have enough money.\r\n");
|
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 {
|
} else {
|
||||||
simple("The merchant doesn't sell that.\r\n")
|
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() {
|
if subargs.is_empty() {
|
||||||
return simple("Sell what?\r\n");
|
return simple("Sell what?\r\n");
|
||||||
}
|
}
|
||||||
let npc = st.world.get_npc(&merchant_id).unwrap();
|
let shop = st.world.get_npc(&merchant_id).unwrap().shop.as_ref().unwrap().clone();
|
||||||
let shop = npc.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()))
|
||||||
if let Some(idx) = item_idx {
|
.map(|idx| (idx, conn.player.inventory[idx].clone()))
|
||||||
let obj = conn.player.inventory[idx].clone();
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some((idx, obj)) = item_info {
|
||||||
// Check if merchant buys this kind of item
|
// Check if merchant buys this kind of item
|
||||||
let can_sell = shop.buys.is_empty() || shop.buys.iter().any(|k| {
|
let can_sell = shop.buys.is_empty() || shop.buys.iter().any(|k| {
|
||||||
if let Some(kind) = &obj.kind {
|
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 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;
|
let price_copper = (total_copper * shop.markdown).floor() as i32;
|
||||||
|
|
||||||
// Add money to player
|
if let Some(conn) = st.players.get_mut(&pid) {
|
||||||
let mut player_total_copper = conn.player.gold * 10000 + conn.player.silver * 100 + conn.player.copper;
|
// Add money to player
|
||||||
player_total_copper += price_copper;
|
let mut player_total_copper = conn.player.gold * 10000 + conn.player.silver * 100 + conn.player.copper;
|
||||||
conn.player.gold = player_total_copper / 10000;
|
player_total_copper += price_copper;
|
||||||
player_total_copper %= 10000;
|
conn.player.gold = player_total_copper / 10000;
|
||||||
conn.player.silver = player_total_copper / 100;
|
player_total_copper %= 10000;
|
||||||
conn.player.copper = player_total_copper % 100;
|
conn.player.silver = player_total_copper / 100;
|
||||||
|
conn.player.copper = player_total_copper % 100;
|
||||||
|
|
||||||
// Remove from inventory
|
// Remove from inventory
|
||||||
conn.player.inventory.remove(idx);
|
conn.player.inventory.remove(idx);
|
||||||
|
|
||||||
simple(&format!(
|
simple(&format!(
|
||||||
"You sell {} for {} copper equivalents.\r\n",
|
"You sell {} for {} copper equivalents.\r\n",
|
||||||
ansi::color(ansi::CYAN, &obj.name),
|
ansi::color(ansi::CYAN, &obj.name),
|
||||||
price_copper
|
price_copper
|
||||||
))
|
))
|
||||||
|
} else {
|
||||||
|
simple("Error\r\n")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
simple("You don't have that in your inventory.\r\n")
|
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}"))?;
|
.map_err(|e| format!("Failed to set pragmas: {e}"))?;
|
||||||
|
|
||||||
conn.execute_batch(
|
conn.execute_batch(
|
||||||
CREATE TABLE IF NOT EXISTS players (
|
r#"CREATE TABLE IF NOT EXISTS players (
|
||||||
name TEXT PRIMARY KEY,
|
name TEXT PRIMARY KEY,
|
||||||
race_id TEXT NOT NULL,
|
race_id TEXT NOT NULL,
|
||||||
class_id TEXT NOT NULL,
|
class_id TEXT NOT NULL,
|
||||||
@@ -89,8 +89,8 @@ impl SqliteDb {
|
|||||||
max_hp INTEGER NOT NULL,
|
max_hp INTEGER NOT NULL,
|
||||||
attack INTEGER NOT NULL,
|
attack INTEGER NOT NULL,
|
||||||
defense INTEGER NOT NULL,
|
defense INTEGER NOT NULL,
|
||||||
inventory_json TEXT NOT NULL DEFAULT '[]',
|
inventory_json TEXT NOT NULL DEFAULT "[]",
|
||||||
equipped_json TEXT NOT NULL DEFAULT '{}',
|
equipped_json TEXT NOT NULL DEFAULT "{}",
|
||||||
is_admin INTEGER NOT NULL DEFAULT 0,
|
is_admin INTEGER NOT NULL DEFAULT 0,
|
||||||
mana INTEGER NOT NULL DEFAULT 0,
|
mana INTEGER NOT NULL DEFAULT 0,
|
||||||
max_mana INTEGER NOT NULL DEFAULT 0,
|
max_mana INTEGER NOT NULL DEFAULT 0,
|
||||||
@@ -127,13 +127,13 @@ impl SqliteDb {
|
|||||||
guild_id TEXT NOT NULL,
|
guild_id TEXT NOT NULL,
|
||||||
level INTEGER NOT NULL DEFAULT 1,
|
level INTEGER NOT NULL DEFAULT 1,
|
||||||
PRIMARY KEY (player_name, guild_id)
|
PRIMARY KEY (player_name, guild_id)
|
||||||
);",
|
);"#,
|
||||||
)
|
)
|
||||||
.map_err(|e| format!("Failed to create tables: {e}"))?;
|
.map_err(|e| format!("Failed to create tables: {e}"))?;
|
||||||
|
|
||||||
// Migration: add is_admin column if missing
|
// Migration: add is_admin column if missing
|
||||||
let has_admin: bool = conn
|
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)))
|
.and_then(|mut s| s.query_row([], |r| r.get::<_, i32>(0)))
|
||||||
.map(|c| c > 0)
|
.map(|c| c > 0)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
@@ -146,34 +146,34 @@ impl SqliteDb {
|
|||||||
|
|
||||||
// Migration: equipped_weapon_json/equipped_armor_json -> equipped_json
|
// Migration: equipped_weapon_json/equipped_armor_json -> equipped_json
|
||||||
let has_old_weapon: bool = conn
|
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)))
|
.and_then(|mut s| s.query_row([], |r| r.get::<_, i32>(0)))
|
||||||
.map(|c| c > 0)
|
.map(|c| c > 0)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
let has_equipped: bool = conn
|
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)))
|
.and_then(|mut s| s.query_row([], |r| r.get::<_, i32>(0)))
|
||||||
.map(|c| c > 0)
|
.map(|c| c > 0)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
if has_old_weapon && !has_equipped {
|
if has_old_weapon && !has_equipped {
|
||||||
let _ = conn.execute(
|
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...");
|
log::info!("Migrating equipped_weapon_json/equipped_armor_json to equipped_json...");
|
||||||
let _ = conn.execute_batch(
|
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 {
|
} else if !has_equipped {
|
||||||
let _ = conn.execute(
|
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
|
// Migration: add mana/endurance columns
|
||||||
let has_mana: bool = conn
|
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)))
|
.and_then(|mut s| s.query_row([], |r| r.get::<_, i32>(0)))
|
||||||
.map(|c| c > 0)
|
.map(|c| c > 0)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
@@ -186,7 +186,7 @@ impl SqliteDb {
|
|||||||
|
|
||||||
// Migration: add currency columns
|
// Migration: add currency columns
|
||||||
let has_gold: bool = conn
|
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)))
|
.and_then(|mut s| s.query_row([], |r| r.get::<_, i32>(0)))
|
||||||
.map(|c| c > 0)
|
.map(|c| c > 0)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name = "Breda"
|
|||||||
description = "Breda is haughty in bearing, with thin auburn hair and narrow blue eyes. She wears simple clothing and several small tools hang from her belt. Breda will purchase monster teeth for a silver coin each."
|
description = "Breda is haughty in bearing, with thin auburn hair and narrow blue eyes. She wears simple clothing and several small tools hang from her belt. Breda will purchase monster teeth for a silver coin each."
|
||||||
room = "lawold:well_market_trade_stalls"
|
room = "lawold:well_market_trade_stalls"
|
||||||
race = "race:human"
|
race = "race:human"
|
||||||
base_attitude = "aggressive"
|
base_attitude = "neutral"
|
||||||
|
|
||||||
[dialogue]
|
[dialogue]
|
||||||
greeting = "What do you want? I'm busy. Unless you have some teeth to sell?"
|
greeting = "What do you want? I'm busy. Unless you have some teeth to sell?"
|
||||||
|
|||||||
Reference in New Issue
Block a user