Skip to content

feored/halbu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

65 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Halbu

See also: Halbu Editor

A .d2s file parsing library written in Rust.

⚠ NPCs and Items section are not yet supported.

Notes regarding D2R with some useful information regarding quests in particular.

This library uses the log crate to log parsing errors.

Usage

use halbu::{quests::QuestFlag, waypoints::Waypoint, Class, Save};

fn main() {
    // Open a save file
    let save_file = std::fs::read("C:\\Users\\Example\\Saved Games\\Diablo II Resurrected\\Jamella.d2s").unwrap();

    let mut save = Save::parse(&save_file);

    // Alternatively, create a new save
    save = Save::default_class(Class::Necromancer);

    // Change class, name, etc
    save.character.class = Class::Paladin;
    save.character.name = String::from("Halbu");
    // Warning: save.character.level and save.attributes.level must
    // be the same or the game won't load!
    save.character.level = 47;
    save.attributes.level.value = 47;
    

    // Change mercenary stats
    // Refer to notes.md for a table with name/variant ID
    save.character.mercenary.name_id = 3;
    save.character.mercenary.variant_id = 34;

    // Set an attribute
    save.attributes.strength.value = 156;

    // Attribute names are taken from itemstatcosts.txt
    save.attributes.newskills.value = 5;

    // Some attributes are stored as fixed point numbers in 21 bits,
    // where the first 13 bits are the integer part and the last 8 the decimal
    // For those attributes (Current/Max HP, Mana & Stamina), you must multiply
    // the value by 256 to get the value displayed in game.
    save.attributes.maxmana.value = 200 * 256;
    println!(
        "Max mana: {}",
        save.attributes.maxmana.value as f64 / 256f64
    );

    // Acquire all waypoints in an act
    save.waypoints.normal.act1.set_all(true);

    // Set all waypoints in a difficulty
    save.waypoints.hell.set_all(true);

    // Get/set whether a specific waypoint is acquired
    // Waypoints are a numbered 0-8 (0-2 for Act IV)
    save.waypoints.hell.act4.set_num(1, true);
    println!("Hell Act IV WP 1: {}", save.waypoints.hell.act4.get_num(1));

    save.waypoints.hell.act4.set(Waypoint::CityOfTheDamned, false);
    println!(
        "Hell Act IV WP 1: {}",
        save.waypoints.hell.act4.get(Waypoint::CityOfTheDamned)
    );

    // Set all skills to 20
    save.skills.set_all(20);
    println!("{}", save.skills);

    // Set the skill points of a given skill to 0
    save.skills.set(17, 0);
    println!("Skillpoints: {}", save.skills.get(17));

    // A quest is a struct with a single member State which is a hashset
    // containing all the flags currently active for that quest.

    // Clear all flags
    // Warning: The quest numbers may not be what you think it is! Refer to NOTES.md.
    save.quests.hell.act1.q1.state.clear();
    println!("Hell Act I Q1 State: {}", save.quests.hell.act1.q1);

    // The flag names are from D2MOO. Refer to NOTES.md for a flagname <> bit # table.
    save.quests.hell.act1.q1.state.insert(QuestFlag::RewardGranted);
    println!(
        "Hell Act I Q1 Completed: {}",
        save.quests.hell.act1.q1.state.contains(&QuestFlag::RewardGranted)
    );
    // Save the file
    // Warning: The file name must match the character's name!
    std::fs::write("C:\\Users\\Example\\Saved Games\\Diablo II Resurrected\\Halbu.d2s", save.to_bytes()).unwrap();
}

For more information, please check the documentation.

Resources

These resources have helped me understand the .d2s format. Many thanks to their authors for the work they've done!

Releases

No releases published

Packages

No packages published

Languages