weapon styles module

Guide for weapon styles module

Weapon Styles Module Implementation

File: src/systems/combat/weapon_styles.rs

This module provides the weapon interface abstraction layer that maps weapon types to combat style options.

Core Data Structures

WeaponInterface

Represents the complete UI configuration for a weapon type:
pub struct WeaponInterface {
    pub name: String,              // Display name: "Unarmed", "Sword", "Bow", etc.
    pub styles: Vec<CombatStyleOption>,
}

CombatStyleOption

Individual combat style button configuration:
pub struct CombatStyleOption {
    pub name: String,              // Button label: "Punch", "Precision", etc.
    pub style: Style,              // Combat logic: Accurate, Aggressive, Defensive, etc.
    pub combat_type: CombatType,   // Melee, Ranged, or Magic
    pub description: String,       // Tooltip text
}

Main Entry Point

get_weapon_interface()

Signature:
pub fn get_weapon_interface(item_def: Option<&ItemDefinition>) -> WeaponInterface
Purpose: Returns the appropriate weapon interface based on the equipped item.
Logic:
  1. If item_def is None, return unarmed interface
  2. Otherwise, check item name (case-insensitive) for weapon type keywords
  3. Return corresponding interface
Weapon Type Detection:
let name = item.name.to_lowercase();
if name.contains("bow") || name.contains("shortbow") || name.contains("longbow") {
    get_bow_interface()
} else if name.contains("sword") || name.contains("scimitar") || name.contains("dagger") {
    get_sword_interface()
} else if name.contains("staff") || name.contains("wand") {
    get_staff_interface()
} else if name.contains("axe") || name.contains("hatchet") {
    get_axe_interface()
} else {
    get_generic_melee_interface()
}

Interface Definitions

Unarmed Interface

Use Case: No weapon equipped
Styles:
WeaponInterface {
    name: "Unarmed".to_string(),
    styles: vec![
        CombatStyleOption {
            name: "Punch".to_string(),
            style: Style::Accurate,
            combat_type: CombatType::Melee,
            description: "Accurate melee attack".to_string(),
        },
        CombatStyleOption {
            name: "Kick".to_string(),
            style: Style::Aggressive,
            combat_type: CombatType::Melee,
            description: "Aggressive melee attack".to_string(),
        },
        CombatStyleOption {
            name: "Block".to_string(),
            style: Style::Defensive,
            combat_type: CombatType::Melee,
            description: "Defensive blocking".to_string(),
        },
    ],
}
Design Notes:
  • 3 styles (no Controlled option for unarmed)
  • Martial arts themed names (Punch, Kick, Block)
  • All Melee combat type

Sword Interface

Use Case: Swords, scimitars, daggers
Styles:
WeaponInterface {
    name: "Sword".to_string(),
    styles: vec![
        CombatStyleOption {
            name: "Chop".to_string(),
            style: Style::Accurate,
            combat_type: CombatType::Melee,
            description: "Accurate cutting attack".to_string(),
        },
        CombatStyleOption {
            name: "Slash".to_string(),
            style: Style::Aggressive,
            combat_type: CombatType::Melee,
            description: "Aggressive slashing attack".to_string(),
        },
        CombatStyleOption {
            name: "Lunge".to_string(),
            style: Style::Controlled,
            combat_type: CombatType::Melee,
            description: "Controlled stabbing attack".to_string(),
        },
        CombatStyleOption {
            name: "Block".to_string(),
            style: Style::Defensive,
            combat_type: CombatType::Melee,
            description: "Defensive parrying".to_string(),
        },
    ],
}
Design Notes:
  • 4 styles (full set including Controlled)
  • Sword-appropriate action names
  • "Lunge" for Controlled (shared XP training)

Bow Interface

Use Case: Bows, shortbows, longbows
Styles:
WeaponInterface {
    name: "Bow".to_string(),
    styles: vec![
        CombatStyleOption {
            name: "Precision".to_string(),
            style: Style::Accurate,
            combat_type: CombatType::Ranged,
            description: "Precise shot".to_string(),
        },
        CombatStyleOption {
            name: "Burst".to_string(),
            style: Style::Aggressive,
            combat_type: CombatType::Ranged,
            description: "Fast firing speed".to_string(),
        },
        CombatStyleOption {
            name: "Snipe".to_string(),
            style: Style::Longrange,
            combat_type: CombatType::Ranged,
            description: "Increased range".to_string(),
        },
    ],
}
Design Notes:
  • 3 styles (Ranged weapons typically don't have Defensive)
  • Renamed from OSRS terms:
    • Accurate → Precision
    • Rapid → Burst
    • Longrange → Snipe
  • All Ranged combat type
  • Note: "Burst" currently maps to Style::Aggressive but ideally should have its own variant for attack speed bonus

Staff Interface

Use Case: Magic staves, wands
Styles:
WeaponInterface {
    name: "Staff".to_string(),
    styles: vec![
        CombatStyleOption {
            name: "Focus".to_string(),
            style: Style::Accurate,
            combat_type: CombatType::Magic,
            description: "Accurate spellcasting".to_string(),
        },
        CombatStyleOption {
            name: "Barrage".to_string(),
            style: Style::Aggressive,
            combat_type: CombatType::Magic,
            description: "Aggressive spellcasting".to_string(),
        },
        CombatStyleOption {
            name: "Ward".to_string(),
            style: Style::Defensive,
            combat_type: CombatType::Magic,
            description: "Defensive casting".to_string(),
        },
    ],
}
Design Notes:
  • 3 styles
  • Magic-themed names (Focus, Barrage, Ward)
  • All Magic combat type

Axe Interface

Use Case: Axes, hatchets
Styles:
WeaponInterface {
    name: "Axe".to_string(),
    styles: vec![
        CombatStyleOption {
            name: "Chop".to_string(),
            style: Style::Accurate,
            combat_type: CombatType::Melee,
            description: "Accurate chopping attack".to_string(),
        },
        CombatStyleOption {
            name: "Hack".to_string(),
            style: Style::Aggressive,
            combat_type: CombatType::Melee,
            description: "Aggressive hacking attack".to_string(),
        },
        CombatStyleOption {
            name: "Smash".to_string(),
            style: Style::Aggressive,
            combat_type: CombatType::Melee,
            description: "Aggressive smashing attack".to_string(),
        },
        CombatStyleOption {
            name: "Block".to_string(),
            style: Style::Defensive,
            combat_type: CombatType::Melee,
            description: "Defensive blocking".to_string(),
        },
    ],
}
Design Notes:
  • 4 styles
  • Heavy weapon themed (Chop, Hack, Smash)
  • Two Aggressive styles (axes are damage-focused)

Generic Melee Interface

Use Case: Fallback for unrecognized melee weapons
Styles:
WeaponInterface {
    name: "Weapon".to_string(),
    styles: vec![
        CombatStyleOption {
            name: "Accurate".to_string(),
            style: Style::Accurate,
            combat_type: CombatType::Melee,
            description: "Accurate attack".to_string(),
        },
        CombatStyleOption {
            name: "Aggressive".to_string(),
            style: Style::Aggressive,
            combat_type: CombatType::Melee,
            description: "Aggressive attack".to_string(),
        },
        CombatStyleOption {
            name: "Defensive".to_string(),
            style: Style::Defensive,
            combat_type: CombatType::Melee,
            description: "Defensive stance".to_string(),
        },
    ],
}
Design Notes:
  • 3 basic styles
  • Generic names (not weapon-specific)
  • Safety fallback for unknown weapons

Extension Guide

Adding a New Weapon Type

  1. Create Interface Function:
fn get_spear_interface() -> WeaponInterface {
    WeaponInterface {
        name: "Spear".to_string(),
        styles: vec![
            CombatStyleOption {
                name: "Stab".to_string(),
                style: Style::Accurate,
                combat_type: CombatType::Melee,
                description: "Accurate stabbing attack".to_string(),
            },
            // ... more styles
        ],
    }
}
  1. Add Detection Logic:
pub fn get_weapon_interface(item_def: Option<&ItemDefinition>) -> WeaponInterface {
    match item_def {
        Some(item) => {
            let name = item.name.to_lowercase();
            if name.contains("spear") || name.contains("lance") {
                get_spear_interface()
            }
            // ... existing checks
        },
        None => get_unarmed_interface(),
    }
}

Adding a New Combat Style

If you need a new underlying combat style (e.g., Style::Rapid for attack speed):
  1. Update Combat Module:
// In src/systems/combat/mod.rs
pub enum Style {
    Accurate,
    Aggressive,
    Defensive,
    Controlled,
    Longrange,
    Rapid,  // NEW
}
  1. Update Damage Calculation:
fn calculate_damage(..., attack_style: Style) -> i32 {
    // Handle new style
    let effective_attack = match attack_style {
        Style::Rapid => attacker_stats.attack + 0, // No accuracy bonus
        // ... existing styles
    }
}
  1. Update Weapon Interface:
CombatStyleOption {
    name: "Burst".to_string(),
    style: Style::Rapid,  // Use new style
    combat_type: CombatType::Ranged,
    description: "Fast firing speed".to_string(),
}

Testing Checklist

  • Unarmed interface displays when no weapon equipped
  • Sword interface displays for swords, scimitars, daggers
  • Bow interface displays for bows, shortbows, longbows
  • Staff interface displays for staves, wands
  • Axe interface displays for axes, hatchets
  • Generic interface displays for unknown weapons
  • All style names are correctly displayed
  • Tooltips show correct descriptions
  • Style selection updates combat system
  • Combat type (Melee/Ranged/Magic) is correctly set