Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions src/Modules/GameServer.bb
Original file line number Diff line number Diff line change
Expand Up @@ -548,16 +548,20 @@ Function ActorAttack(A1.ActorInstance, A2.ActorInstance)
EndIf
EndIf

; Damage armour
; Damage armour. The DEFENDER's (A2's) equipped armour absorbed the
; blow (the damage formulas read GetArmourLevel(A2\Inventory)), so it
; is A2's armour that wears -- this block was historically a
; copy-paste of the weapon-wear block above, which left the wear
; target as A1 (the attacker).
If ArmourDamage = True
For i = SlotI_Shield To SlotI_Feet
If A1\Inventory\Items[i] <> Null
If A1\Inventory\Items[i]\ItemHealth > 0
If A2\Inventory\Items[i] <> Null
If A2\Inventory\Items[i]\ItemHealth > 0
If Rand(1, 5) = 1
A1\Inventory\Items[i]\ItemHealth = A1\Inventory\Items[i]\ItemHealth - 1
If A1\RNID > 0
Pa$ = RCE_StrFromInt$(i, 1) + RCE_StrFromInt$(A1\Inventory\Items[i]\ItemHealth, 2)
RCE_Send(Host, A1\RNID, P_ItemHealth, Pa$, True)
A2\Inventory\Items[i]\ItemHealth = A2\Inventory\Items[i]\ItemHealth - 1
If A2\RNID > 0
Pa$ = RCE_StrFromInt$(i, 1) + RCE_StrFromInt$(A2\Inventory\Items[i]\ItemHealth, 2)
RCE_Send(Host, A2\RNID, P_ItemHealth, Pa$, True)
EndIf
EndIf
EndIf
Expand Down
24 changes: 14 additions & 10 deletions src/Tests/Modules/CombatDamageFormulaTest.bb
Original file line number Diff line number Diff line change
Expand Up @@ -829,13 +829,17 @@ End Test
; ActorAttack -- equipment wear
; ============================================================================

; FLAG-FOR-HUMAN: the "Damage armour" block in ActorAttack wears down the
; ATTACKER's (A1's) equipped armour, not the defender's (A2's), even
; though A2's armour is what absorbed the blow. Pinned as shipped: after
; 300 swings with ArmourDamage on, the defender's chest piece is still at
; exactly 100 health while the attacker's has lost some (1-in-5 chance
; per swing; P(zero losses in 300) ~ 1e-29).
Test testArmourWearHitsAttackerNotDefender()
; The "Damage armour" block in ActorAttack wears down the DEFENDER's
; (A2's) equipped armour -- the armour that absorbed the blow. This test
; originally pinned (FLAG-FOR-HUMAN) the opposite, shipped-buggy behavior:
; the block was a copy-paste of the weapon-wear block above it and wore
; the ATTACKER's (A1's) armour instead. That bug is now fixed in
; GameServer.bb (A1 -> A2 in the armour-wear block only), and this test
; was deliberately flipped to assert the corrected behavior: after 300
; swings with ArmourDamage on, the defender's chest piece has lost some
; health (1-in-5 chance per swing; P(zero losses in 300) ~ 1e-29) while
; the attacker's is still at exactly 100.
Test testArmourWearHitsDefender()
ResetWorld()
SeedRnd(4001)
CombatFormula = 2
Expand All @@ -849,9 +853,9 @@ Test testArmourWearHitsAttackerNotDefender()
For i = 1 To 300
ActorAttack(A1, A2)
Next
Assert(DefenderChest\ItemHealth = 100) ; FLAG-FOR-HUMAN
Assert(AttackerChest\ItemHealth < 100) ; FLAG-FOR-HUMAN
Assert(AttackerChest\ItemHealth > 0)
Assert(DefenderChest\ItemHealth < 100)
Assert(DefenderChest\ItemHealth > 0)
Assert(AttackerChest\ItemHealth = 100)
ResetWorld()
End Test

Expand Down
Loading