# SkillSpeedScale

The SkillSpeedScale plugin allows fine-tuning how attack speed affects individual skills, enabling precise balance control for multi-hit abilities that become overpowered at high attack speeds.

## File Location

```
GameServer/Data/Plugins/SkillSpeedScale.xml
```

## Dependencies

| Depends On                  | Purpose                                                                                                                                  |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| GameServerInfo - Common.dat | Uses global timing values from `[SkillTiming]` section: `MaxAttackSpeed`, `BaseSkillDelay`, `MinSkillDelay`, `SpeedDelayMultiplierX10`   |
| Skill.txt                   | References skill IDs (Index) from the skill database. Skills with `Delay > 0` in Skill.txt use fixed cooldowns and ignore speed scaling. |

## Configuration Structure

```xml
<SkillSpeedScale>
    <Skill Index="238" Name="Chaotic Diseier" SpeedScale="0.55" MinDelay="200" />
    <Skill Index="9" Name="Evil Spirit" SpeedScale="1.0" MinDelay="50" />
</SkillSpeedScale>
```

Each `<Skill>` entry overrides the default speed scaling behavior for a specific skill.

## Attributes

| Attribute    | Type   | Default  | Range   | Description                                                            |
| ------------ | ------ | -------- | ------- | ---------------------------------------------------------------------- |
| `Index`      | int    | Required | 0-299   | Skill ID from Skill.txt                                                |
| `Name`       | string | Optional | -       | Skill name for readability (not used by server, documentation only)    |
| `SpeedScale` | float  | 1.0      | 0.0-3.0 | How much attack speed affects this skill's delay (see below)           |
| `MinDelay`   | int    | 0        | 0+      | Per-skill minimum delay in milliseconds (0 = use global MinSkillDelay) |
| `MaxDelay`   | int    | 0        | 0+      | Per-skill maximum delay cap in milliseconds (0 = no cap)               |

### SpeedScale Values Explained

The `SpeedScale` attribute controls how much the character's attack speed stat affects the skill's casting delay:

| Value | Effect                                       | Use Case                                                        |
| ----- | -------------------------------------------- | --------------------------------------------------------------- |
| `0.0` | Speed has **NO effect** (fixed delay)        | Utility skills like Teleport that shouldn't be spammable        |
| `0.5` | Speed has **HALF effect** (nerfed)           | Multi-hit skills that become overpowered at high speed          |
| `1.0` | **Normal** speed scaling (default)           | Balanced single-hit skills                                      |
| `1.5` | Speed has **150% effect** (buffed)           | Underpowered skills that need speed scaling boost               |
| `2.0` | Speed has **DOUBLE effect** (heavily buffed) | Skills that should benefit greatly from attack speed investment |

{% hint style="info" %}
**Skills NOT listed in this config file default to `SpeedScale="1.0"` (normal speed scaling).**
{% endhint %}

## Timing Formula

The plugin modifies the skill delay calculation formula used by the server:

### Step-by-Step Calculation

```
1. If skill has Delay > 0 in Skill.txt → return that delay (fixed cooldown, no speed scaling)
2. Get character's attack/magic speed (physical skills use PhysiSpeed, magic skills use MagicSpeed)
3. Cap speed: speed = min(speed, MaxAttackSpeed)    // Default: 270
4. Apply per-skill scaling: effectiveSpeed = speed × SpeedScale
5. Calculate raw delay: rawDelay = BaseSkillDelay - (effectiveSpeed × SpeedDelayMultiplier)
6. Apply max cap: if MaxDelay > 0 then rawDelay = min(rawDelay, MaxDelay)
7. Apply min floor: finalDelay = max(rawDelay, MinDelay or global MinSkillDelay)
```

### Default Global Values

These are configured in `GameServerInfo - Common.dat` under the `[SkillTiming]` section:

| Global Setting            | Hardcoded Default | Purpose                                                       |
| ------------------------- | ----------------- | ------------------------------------------------------------- |
| `MaxAttackSpeed`          | 270               | Maximum effective speed before formula (0 = no cap)           |
| `BaseSkillDelay`          | 1500 ms           | Starting delay before speed reduction                         |
| `SpeedDelayMultiplierX10` | 50 (= 5.0)        | Delay reduction per speed point (stored as x10 for precision) |
| `MinSkillDelay`           | 50 ms             | Absolute minimum delay floor                                  |

{% hint style="info" %}
The actual values in your server's config file may differ. These are the **hardcoded defaults** used when the config file doesn't specify values.
{% endhint %}

### Formula Example

**Chaotic Diseier** with `SpeedScale="0.55"`, `MinDelay="200"`:

**Low-speed character (speed = 200):**

```
effectiveSpeed = 200 × 0.55 = 110
rawDelay = 1500 - (110 × 5.0) = 1500 - 550 = 950 ms
finalDelay = max(950, 200) = 950 ms
```

**High-speed character (speed = 270, capped):**

```
effectiveSpeed = 270 × 0.55 = 148.5
rawDelay = 1500 - (148.5 × 5.0) = 1500 - 742.5 = 757 ms
finalDelay = max(757, 200) = 757 ms
```

**Compare to normal scaling (`SpeedScale="1.0"`):**

```
effectiveSpeed = 270 × 1.0 = 270
rawDelay = 1500 - (270 × 5.0) = 1500 - 1350 = 150 ms
finalDelay = max(150, 50) = 150 ms
```

By reducing `SpeedScale` to 0.55, the skill casts at **757ms instead of 150ms** at max speed—preventing spam of this powerful multi-hit AoE.

## Important Behavior

{% hint style="info" %}
**Skills with Fixed Delay**: If a skill has a non-zero `Delay` value in `Skill.txt`, that delay is used as a **fixed cooldown** and attack speed scaling is **completely ignored**. Only skills with `Delay=0` in Skill.txt are affected by the speed scaling formula and this plugin.
{% endhint %}

{% hint style="info" %}
**Per-Skill Overrides**: The `MinDelay` attribute in this config **overrides** the global `MinSkillDelay` from GameServerInfo - Common.dat for the specified skill only.
{% endhint %}

{% hint style="info" %}
**Clamping**: Invalid `SpeedScale` values are automatically clamped:

* Values below 0.0 → clamped to 0.0
* Values above 3.0 → clamped to 3.0
  {% endhint %}

{% hint style="info" %}
**Physical vs Magic Skills**: Physical skills (melee attacks, bow skills) use **PhysiSpeed** for timing calculations, while magic skills use **MagicSpeed**. This means the same character may have different casting speeds for different skill types based on their equipment and stats.
{% endhint %}

{% hint style="info" %}
**Reload Support**: Configuration can be reloaded at runtime using the `/reload plugins` GM command without restarting the server.
{% endhint %}

{% hint style="warning" %}
**Negative Values Ignored**: Negative values for `MinDelay` or `MaxDelay` are treated as 0 (use global/no cap).
{% endhint %}

## Common Use Cases

### Multi-Hit Skills - Nerf Speed Scaling

Multi-target or multi-hit skills become overpowered when spammed at high attack speed:

```xml
<!-- Evil Spirit: 10-target AoE -->
<Skill Index="9" Name="Evil Spirit" SpeedScale="0.5" MinDelay="350" />

<!-- Chaotic Diseier: 2-hit directional AoE -->
<Skill Index="238" Name="Chaotic Diseier" SpeedScale="0.55" MinDelay="200" />

<!-- Chain Lightning: Multi-target chain -->
<Skill Index="215" Name="Chain Lightning" SpeedScale="0.5" MinDelay="400" />
```

By reducing `SpeedScale` below 1.0, these skills remain powerful but can't be spammed continuously.

### Channeled Skills - Heavy Nerf

Skills with continuous or hold effects should be heavily rate-limited:

```xml
<!-- Force: Channeled push skill -->
<Skill Index="60" Name="Force" SpeedScale="0.2" MinDelay="600" />
```

A very low `SpeedScale` (0.2) combined with high `MinDelay` (600ms) ensures this utility skill cannot be spammed.

### Utility Skills - Fixed Delay

Teleport and buff skills should have fixed delays regardless of attack speed:

```xml
<!-- Teleport: Should not be spammable -->
<Skill Index="6" Name="Teleport" SpeedScale="0.0" MinDelay="1000" />

<!-- Soul Barrier: Defensive buff -->
<Skill Index="16" Name="Soul Barrier" SpeedScale="0.0" MinDelay="500" />
```

Setting `SpeedScale="0.0"` makes attack speed completely ineffective, using only the `MinDelay` value.

### Single-Hit Burst Skills - Buff Speed Scaling

Underpowered single-hit skills can benefit MORE from attack speed:

```xml
<!-- Twisting Slash: Benefits greatly from attack speed -->
<Skill Index="41" Name="Twisting Slash" SpeedScale="1.5" MinDelay="50" />
```

A `SpeedScale` above 1.0 makes attack speed investment more rewarding for this skill.

## Examples

{% tabs %}
{% tab title="Balanced Multi-Hit" %}

```xml
<SkillSpeedScale>
    <!-- Multi-hit skills nerfed to 50-60% speed scaling -->
    <Skill Index="78" Name="Fire Scream" SpeedScale="0.5" MinDelay="350" />
    <Skill Index="237" Name="Gigantic Storm" SpeedScale="0.5" MinDelay="400" />
    <Skill Index="238" Name="Chaotic Diseier" SpeedScale="0.55" MinDelay="200" />
    <Skill Index="215" Name="Chain Lightning" SpeedScale="0.5" MinDelay="400" />
    <Skill Index="230" Name="Lightning Shock" SpeedScale="0.5" MinDelay="350" />
</SkillSpeedScale>
```

{% endtab %}

{% tab title="Fixed Utility Delays" %}

```xml
<SkillSpeedScale>
    <!-- Utility skills with fixed delays (speed has no effect) -->
    <Skill Index="6" Name="Teleport" SpeedScale="0.0" MinDelay="1000" />
    <Skill Index="16" Name="Soul Barrier" SpeedScale="0.0" MinDelay="500" />
    <Skill Index="60" Name="Force" SpeedScale="0.0" MinDelay="800" />
</SkillSpeedScale>
```

{% endtab %}

{% tab title="Mixed Balance" %}

```xml
<SkillSpeedScale>
    <!-- Multi-hit AoE: nerfed -->
    <Skill Index="9" Name="Evil Spirit" SpeedScale="0.5" MinDelay="350" />

    <!-- Single-hit burst: normal -->
    <Skill Index="42" Name="Rageful Blow" SpeedScale="1.0" MinDelay="200" />

    <!-- Underpowered skill: buffed -->
    <Skill Index="41" Name="Twisting Slash" SpeedScale="1.5" MinDelay="50" />

    <!-- Utility: fixed -->
    <Skill Index="6" Name="Teleport" SpeedScale="0.0" MinDelay="1000" />
</SkillSpeedScale>
```

{% endtab %}

{% tab title="Class-Specific: Rage Fighter" %}

```xml
<SkillSpeedScale>
    <!-- Rage Fighter skills - multi-hit combos nerfed -->
    <Skill Index="260" Name="Killing Blow" SpeedScale="0.6" MinDelay="300" />
    <Skill Index="261" Name="Beast Uppercut" SpeedScale="0.6" MinDelay="300" />
    <Skill Index="262" Name="Chain Drive" SpeedScale="0.5" MinDelay="350" />
    <Skill Index="263" Name="Dark Side" SpeedScale="0.5" MinDelay="400" />
    <Skill Index="264" Name="Dragon Roar" SpeedScale="0.6" MinDelay="350" />
    <Skill Index="265" Name="Dragon Slasher" SpeedScale="0.5" MinDelay="400" />
</SkillSpeedScale>
```

{% endtab %}
{% endtabs %}

## Common Issues

{% hint style="danger" %}
**Skills Still Too Fast**: If a skill is still being spammed at high speed, check:

1. Is the skill's `Index` correct? Verify against Skill.txt
2. Is the config file loaded? Check server logs for "SkillSpeedScale" entries
3. Try increasing `MinDelay` or decreasing `SpeedScale` further
   {% endhint %}

{% hint style="warning" %}
**Skills Too Slow**: If a skill feels unresponsive:

1. Increase `SpeedScale` value (closer to 1.0)
2. Decrease `MinDelay` value
3. Check that global `MaxAttackSpeed` isn't too restrictive
   {% endhint %}

{% hint style="warning" %}
**Config Not Reloading**: Use `/reload plugins` command. If issues persist, restart the GameServer. Check logs for XML parsing errors.
{% endhint %}

{% hint style="info" %}
**Testing Changes**: Use characters with different attack speed values to verify the scaling behaves as expected:

* Low speed (\~100): Tests base delay
* Medium speed (\~200): Tests scaling curve
* High speed (\~270): Tests minimum delay floor
  {% endhint %}

## Finding Skill IDs

Skill IDs (`Index` attribute) come from `GameServer/Data/Skill.txt`. Each line represents a skill:

```
// Format: Index   Name   ...other attributes...
0    Energy Ball
1    Poison
...
238  Chaotic Diseier
```

Alternatively, check in-game or in the client's Skill.txt data file.

## Related Configurations

* **GameServerInfo - Common.dat** (`[SkillTiming]` section): Global attack speed settings (`MaxAttackSpeed`, `BaseSkillDelay`, `MinSkillDelay`, `SpeedDelayMultiplierX10`)
* **Skill.txt**: Base skill definitions, IDs, and fixed delays (Delay column)
* **SkillManager.cpp**: Server-side skill validation and timing enforcement (implements the speed scaling formula)

## Reload Command

```
/reload plugins
```

This command reloads all plugin configurations including SkillSpeedScale.xml without restarting the server.
