Design a Diablo-style action-RPG combat system in Unreal Engine for online co-op. Players have many abilities with cooldowns, costs, and per-level scaling; enemies have health, resistances, and crit interactions; and designers must tune every number — ability damage, resistances, scaling curves — without a programmer recompiling the game. Damage must flow through a single mitigation pipeline so crits, elemental resistances, and damage-over-time compose consistently. The session is multiplayer, so health, kills, and damage must be resolved authoritatively on the server and must not be forgeable by a client, while combat still has to feel responsive (hits and damage numbers should appear without waiting on a round-trip). Describe how abilities, stats, and the damage pipeline are structured, where authority lives, and the trade-offs of your approach.
Drive everything server-authoritatively: abilities as data-driven objects, a stat component for health, and a damage pipeline applying FDamageEvent through mitigation. The server resolves hits and death; clients only predict cosmetics.
- ✗Trusting client-reported damage or health, which opens the game to trivial cheating
- ✗Hard-coding ability numbers in C++ instead of exposing them in data for designers
- ✗Applying damage in client overlap events instead of resolving hits on the server
- →How would you make damage numbers feel responsive despite server-authoritative resolution?
- →How would you structure crit, elemental resistances, and damage-over-time in the pipeline?
Key classes
UAbilityDataAsset— ability definition: cost, cooldown, base damage, element type, target tag.UCombatComponent— aUActorComponenton the character: activates abilities, tracks cooldowns, drives hit traces.UStatComponent— health, mana, resistances, multipliers; the single authoritative source of stats.FDamageEvent/UDamageType— Unreal's standard damage infrastructure, extended with element and a crit flag.
Data model
An ability is data, not code: a single C++ execution machine reads a UAbilityDataAsset. Damage is described by an FDamagePayload struct (source, base value, element, crit flag) that travels through a mitigation pipeline.
Data flow
- Client presses a skill → Server RPC
ActivateAbility(id). - The server checks cooldown and cost against
UStatComponent, then runs the trace/overlap. - For each target an
FDamagePayloadis built and passes through resistances and crits inUStatComponent. - The server applies the final damage, replicates health, and multicasts the hit for VFX and damage numbers.
Replication
Health and stats are replicated by the server only. Abilities are activated through a Server RPC; cosmetics (animations, VFX) are predicted locally on the client and confirmed via a Multicast RPC. Damage numbers are shown from the multicast event so everyone sees a consistent picture.
Designer-facing config
Each ability is a UAbilityDataAsset. Per-level damage curves are a UCurveTable. Monster resistances live in a DataTable. The designer balances combat with no programmer involved.
Trade-offs
- Server authority vs. responsiveness: the server kills cheats but adds latency — offset with client-side prediction of cosmetics.
- Custom system vs. GAS: a custom system is simpler for a small team, but GAS gives ready-made replication, effects, and prediction at scale.