en:rpd:combat_mechanic
Differences
This shows you the differences between two versions of the page.
| en:rpd:combat_mechanic [2026/01/01 19:45] – namespace move Mike | en:rpd:combat_mechanic [2026/01/01 19:46] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Combat Mechanic ====== | ||
| + | Combat in Remixed Dungeon is a complex system that combines attacking, defending, and damage calculation mechanics. | ||
| + | |||
| + | ==== Combat Overview ==== | ||
| + | |||
| + | Combat in Remixed Dungeon involves a two-step process: | ||
| + | 1. **Hit Detection**: | ||
| + | 2. **Damage Calculation**: | ||
| + | |||
| + | ==== Hit Detection System ==== | ||
| + | |||
| + | The hit detection is calculated in '' | ||
| + | |||
| + | <code java> | ||
| + | // In CharUtils.java | ||
| + | float acuRoll = Random.Float(attacker.attackSkill(defender)); | ||
| + | float defRoll = Random.Float(defender.defenseSkill(attacker)); | ||
| + | boolean hit = (magic ? acuRoll * 2 : acuRoll) >= defRoll; | ||
| + | |||
| + | if (hit) { | ||
| + | // Attack hits | ||
| + | int damage = attacker.damageRoll(); | ||
| + | defender.damage(damage, | ||
| + | } else { | ||
| + | // Attack misses | ||
| + | defender.defenseProc(attacker, | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | Note that for magic attacks, the attacker' | ||
| + | |||
| + | ==== Attack Skill Calculation ==== | ||
| + | |||
| + | The attack skill is calculated in '' | ||
| + | |||
| + | <code java> | ||
| + | public int attackSkill(Char target) { | ||
| + | int[] bf = {0}; | ||
| + | forEachBuff(b -> bf[0] += b.attackSkillBonus(this)); | ||
| + | |||
| + | int bonus = bf[0]; | ||
| + | float accuracy = (float) Math.pow(1.4, | ||
| + | |||
| + | if (target == null) { | ||
| + | target = CharsList.DUMMY; | ||
| + | } | ||
| + | |||
| + | if (rangedWeapon.valid() && level().distance(getPos(), | ||
| + | accuracy *= 0.5f; | ||
| + | } | ||
| + | |||
| + | float mainAccuracyFactor = getActiveWeapon().accuracyFactor(this); | ||
| + | float secondaryAccuracyFactor = getSecondaryWeapon().accuracyFactor(this); | ||
| + | |||
| + | float skillFactor = Utils.min(20f, | ||
| + | |||
| + | int aSkill = (int) ((baseAttackSkill + lvl()) * accuracy * skillFactor); | ||
| + | |||
| + | return aSkill; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== Defense Skill Calculation ==== | ||
| + | |||
| + | The defense skill is also calculated in '' | ||
| + | |||
| + | <code java> | ||
| + | public int defenseSkill(Char enemy) { | ||
| + | int defenseSkill = baseDefenseSkill + lvl(); | ||
| + | |||
| + | final int[] bf = {0}; | ||
| + | forEachBuff(b -> bf[0] += b.defenceSkillBonus(this)); | ||
| + | |||
| + | int bonus = bf[0]; | ||
| + | |||
| + | float evasion = (float) Math.pow(1.2, | ||
| + | if (paralysed) { | ||
| + | evasion /= 2; | ||
| + | } | ||
| + | |||
| + | int aEnc = getItemFromSlot(Belongings.Slot.ARMOR).requiredSTR() - effectiveSTR(); | ||
| + | |||
| + | if (aEnc > 0) { | ||
| + | return (int) (defenseSkill * evasion / Math.pow(1.5, | ||
| + | } else { | ||
| + | if (getHeroClass() == HeroClass.ROGUE) { | ||
| + | if (getCurAction() != null && getSubClass() == HeroSubClass.FREERUNNER && !isStarving()) { | ||
| + | evasion *= 2; | ||
| + | } | ||
| + | |||
| + | return (int) ((defenseSkill - aEnc) * evasion); | ||
| + | } else { | ||
| + | return (int) (defenseSkill * evasion); | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ==== Damage Calculation ==== | ||
| + | |||
| + | After a successful hit, damage reduction is calculated in the '' | ||
| + | |||
| + | <code java> | ||
| + | public int defenseProc(Char enemy, int baseDamage) { | ||
| + | int dr = defenceRoll(enemy); | ||
| + | |||
| + | final int[] damage = {baseDamage - dr}; | ||
| + | |||
| + | forEachBuff(b -> damage[0] = b.defenceProc(this, | ||
| + | damage[0] = getItemFromSlot(Belongings.Slot.ARMOR).defenceProc(enemy, | ||
| + | |||
| + | |||
| + | if (getOwnerId() != enemy.getId()) { | ||
| + | setEnemy(enemy); | ||
| + | } | ||
| + | |||
| + | return getScript().run(" | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | The damage reduction ('' | ||
| + | |||
| + | <code java> | ||
| + | public int defenceRoll(Char enemy) { | ||
| + | if (enemy.ignoreDr()) { | ||
| + | return 0; | ||
| + | } | ||
| + | |||
| + | final int[] dr = {dr()}; | ||
| + | forEachBuff(b -> dr[0] += b.drBonus(this)); | ||
| + | return Random.IntRange(0, | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | The base damage reduction is calculated from the equipped armor using its '' | ||
| + | |||
| + | <code java> | ||
| + | public int defenceProc(Char attacker, Char defender, int damage ) { | ||
| + | if (glyph != null) { | ||
| + | damage = glyph.defenceProc( this, attacker, defender, damage ); | ||
| + | } | ||
| + | |||
| + | if (!isLevelKnown()) { | ||
| + | if (--hitsToKnow <= 0) { | ||
| + | setLevelKnown(true); | ||
| + | GLog.w(StringsManager.getVar(R.string.Armor_Identify), | ||
| + | Badges.validateItemLevelAcquired( this ); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | return damage; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | The armor' | ||
| + | |||
| + | ==== Combat Elements ==== | ||
| + | |||
| + | ==== Attack Skill ==== | ||
| + | * **Function**: | ||
| + | * **Factors**: | ||
| + | * **Formula**: | ||
| + | * **Reference**: | ||
| + | |||
| + | ==== Defense Skill ==== | ||
| + | * **Function**: | ||
| + | * **Factors**: | ||
| + | * **Formula**: | ||
| + | * **Reference**: | ||
| + | |||
| + | ==== Armor Class ==== | ||
| + | * **Function**: | ||
| + | * **Factors**: | ||
| + | * **Formula**: | ||
| + | * **Reference**: | ||
| + | |||
| + | ==== Evasion ==== | ||
| + | * **Function**: | ||
| + | * **Result**: No damage taken | ||
| + | * **Reference**: | ||
| + | |||
| + | ==== Combat Phases ==== | ||
| + | |||
| + | ==== Phase 1: Hit Determination ==== | ||
| + | 1. Attacker rolls a random value between 0 and '' | ||
| + | 2. Defender rolls a random value between 0 and '' | ||
| + | 3. If '' | ||
| + | 4. If '' | ||
| + | |||
| + | ==== Phase 2: Damage Application ==== | ||
| + | 1. If attack hits, damage is calculated considering armor | ||
| + | 2. Armor reduces the damage according to the damage reduction formula | ||
| + | 3. The final damage is applied to the defender' | ||
| + | |||
| + | ==== Combat Modifiers ==== | ||
| + | |||
| + | ==== Status Effects ==== | ||
| + | * **Paralysis**: | ||
| + | * **Blessed**: | ||
| + | * **Other Buffs**: Various temporary effects that modify combat stats | ||
| + | |||
| + | ==== Weapon Properties ==== | ||
| + | * **Accuracy Factor**: Affects attack skill calculation | ||
| + | * **Damage Range**: Determines the potential damage dealt | ||
| + | * **Speed**: Affects attack frequency | ||
| + | |||
| + | ==== Equipment Effects ==== | ||
| + | * **Armor**: Reduces incoming damage | ||
| + | * **Rings**: Various combat-relevant bonuses | ||
| + | * **Enchantments**: | ||
| + | |||
| + | ==== Combat Outcomes ==== | ||
| + | |||
| + | ==== Hit ==== | ||
| + | * Attack skill > Defense skill roll | ||
| + | * Damage is calculated with armor reduction | ||
| + | * Target takes reduced damage | ||
| + | |||
| + | ==== Miss ==== | ||
| + | * Defense skill > Attack skill roll | ||
| + | * Target takes no damage | ||
| + | * Some classes may have special effects on evade | ||
| + | |||
| + | ==== Critical Hit ==== | ||
| + | * Not a standard mechanic in Remixed Dungeon (unlike some other roguelikes) | ||
| + | * Damage is determined by weapon damage range and modifiers | ||
| + | |||
| + | ==== Code References ==== | ||
| + | * Java: [[https:// | ||
| + | * Java: [[https:// | ||
| + | * Java: [[https:// | ||
| + | |||
| + | ==== Related ==== | ||
| + | * [[en: | ||
| + | * [[en: | ||
| + | * [[en: | ||
| + | * [[en: | ||
| + | * [[en: | ||
| + | |||
| + | {{tag> rpd mechanics combat fighting }} | ||
