1
|
|
|
<?php |
2
|
|
|
declare(strict_types=1); |
3
|
|
|
|
4
|
|
|
namespace HeroesofAbenez\Combat; |
5
|
|
|
|
6
|
|
|
require __DIR__ . "/../../bootstrap.php"; |
7
|
|
|
|
8
|
|
|
use Tester\Assert; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* @author Jakub Konečný |
12
|
|
|
* @testCase |
13
|
|
|
*/ |
14
|
|
|
final class CharacterTest extends \Tester\TestCase |
15
|
|
|
{ |
16
|
|
|
private function generateCharacter(int $id): Character |
17
|
|
|
{ |
18
|
|
|
$stats = [ |
19
|
|
|
"id" => $id, "name" => "Player $id", "level" => 1, "initiativeFormula" => "1d2+DEX/4", "strength" => 10, |
20
|
|
|
"dexterity" => 10, "constitution" => 10, "intelligence" => 10, "charisma" => 10 |
21
|
|
|
]; |
22
|
|
|
return new Character($stats); |
23
|
|
|
} |
24
|
|
|
|
25
|
|
|
public function testGetActivePet(): void |
26
|
|
|
{ |
27
|
|
|
$stats = [ |
28
|
|
|
"id" => 1, "name" => "Player 1", "level" => 1, "initiativeFormula" => "1d2+DEX/4", "strength" => 10, |
29
|
|
|
"dexterity" => 10, "constitution" => 10, "intelligence" => 10, "charisma" => 10 |
30
|
|
|
]; |
31
|
|
|
$petStats = [ |
32
|
|
|
"id" => 1, "deployed" => false, "bonusStat" => Character::STAT_STRENGTH, "bonusValue" => 10, |
33
|
|
|
]; |
34
|
|
|
$pet = new Pet($petStats); |
35
|
|
|
$character = new Character($stats, [], [$pet]); |
36
|
|
|
Assert::null($character->activePet); |
37
|
|
|
$pet->deployed = true; |
38
|
|
|
Assert::same(1, $character->activePet); |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
public function testAddAndRemoveEffect(): void |
42
|
|
|
{ |
43
|
|
|
$character = $this->generateCharacter(1); |
44
|
|
|
Assert::count(0, $character->effects); |
45
|
|
|
Assert::same(5, $character->damage); |
46
|
|
|
$character->effects[] = new CharacterEffect([ |
47
|
|
|
"id" => "equipment1bonusEffect", |
48
|
|
|
"type" => "buff", |
49
|
|
|
"stat" => Character::STAT_DAMAGE, |
50
|
|
|
"value" => 10, |
51
|
|
|
"valueAbsolute" => true, |
52
|
|
|
"duration" => CharacterEffect::DURATION_COMBAT, |
53
|
|
|
]); |
54
|
|
|
Assert::count(1, $character->effects); |
55
|
|
|
Assert::same(15, $character->damage); |
56
|
|
|
$character->effects->removeByFilter(["id" => "equipment1bonusEffect"]); |
57
|
|
|
Assert::count(0, $character->effects); |
58
|
|
|
Assert::same(5, $character->damage); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
public function testInitiativeFormulaParser(): void |
62
|
|
|
{ |
63
|
|
|
$character = $this->generateCharacter(1); |
64
|
|
|
Assert::type(InitiativeFormulaParser::class, $character->initiativeFormulaParser); |
65
|
|
|
Assert::notEqual(0, $character->initiative); |
66
|
|
|
$character->initiativeFormulaParser = new ConstantInitiativeFormulaParser(0); |
67
|
|
|
Assert::equal(0, $character->initiative); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
public function testDebuffsCap(): void |
71
|
|
|
{ |
72
|
|
|
$character = $this->generateCharacter(1); |
73
|
|
|
$effect = new CharacterEffect([ |
74
|
|
|
"id" => "skillEffect", "type" => SkillSpecial::TYPE_DEBUFF, "valueAbsolute" => false, |
75
|
|
|
"value" => 1000, "duration" => 1, "stat" => "constitution", |
76
|
|
|
]); |
77
|
|
|
$character->effects[] = $effect; |
78
|
|
|
Assert::same(2, $character->constitution); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
public function testDamageStat(): void |
82
|
|
|
{ |
83
|
|
|
$stats = [ |
84
|
|
|
"id" => 1, "name" => "Player 1", "level" => 1, "initiativeFormula" => "1d2+DEX/4", "strength" => 10, |
85
|
|
|
"dexterity" => 10, "constitution" => 10, "intelligence" => 10, "charisma" => 10 |
86
|
|
|
]; |
87
|
|
|
$equipment = [ |
88
|
|
|
new Weapon([ |
89
|
|
|
"id" => 1, "name" => "Novice Sword", "slot" => Equipment::SLOT_WEAPON, "type" => Weapon::TYPE_SWORD, |
90
|
|
|
"strength" => 1, "worn" => true |
91
|
|
|
]), |
92
|
|
|
new Weapon([ |
93
|
|
|
"id" => 2, "name" => "Novice Staff", "slot" => Equipment::SLOT_WEAPON, "type" => Weapon::TYPE_STAFF, |
94
|
|
|
"strength" => 1, "worn" => true |
95
|
|
|
]) |
96
|
|
|
]; |
97
|
|
|
$character = new Character($stats, $equipment); |
98
|
|
|
Assert::same(Character::STAT_STRENGTH, $character->damageStat()); |
99
|
|
|
$equipment[0]->worn = false; |
100
|
|
|
Assert::same(Character::STAT_INTELLIGENCE, $character->damageStat()); |
101
|
|
|
$equipment[1]->worn = false; |
102
|
|
|
Assert::same(Character::STAT_STRENGTH, $character->damageStat()); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
public function testStatus(): void |
106
|
|
|
{ |
107
|
|
|
$character = $this->generateCharacter(1); |
108
|
|
|
Assert::false($character->hasStatus("abc")); |
109
|
|
|
Assert::null($character->getStatus("abc")); |
110
|
|
|
Assert::false($character->hasStatus(Character::STATUS_STUNNED)); |
111
|
|
|
$character->effects[] = new CharacterEffect([ |
112
|
|
|
"id" => "stunEffect", |
113
|
|
|
"type" => SkillSpecial::TYPE_STUN, |
114
|
|
|
"duration" => CharacterEffect::DURATION_COMBAT, |
115
|
|
|
"valueAbsolute" => false, |
116
|
|
|
]); |
117
|
|
|
Assert::true($character->hasStatus(Character::STATUS_STUNNED)); |
118
|
|
|
$character->effects->removeByFilter(["id" => "stunEffect"]); |
119
|
|
|
Assert::false($character->hasStatus(Character::STATUS_STUNNED)); |
120
|
|
|
$character->effects[] = new CharacterEffect([ |
121
|
|
|
"id" => "poisonEffect", |
122
|
|
|
"type" => SkillSpecial::TYPE_POISON, |
123
|
|
|
"duration" => CharacterEffect::DURATION_COMBAT, |
124
|
|
|
"value" => 5, |
125
|
|
|
"valueAbsolute" => false, |
126
|
|
|
]); |
127
|
|
|
Assert::true($character->hasStatus(Character::STATUS_POISONED)); |
128
|
|
|
$character->effects->removeByFilter(["id" => "poisonEffect"]); |
129
|
|
|
Assert::false($character->hasStatus(Character::STATUS_POISONED)); |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
public function testCanAct(): void |
133
|
|
|
{ |
134
|
|
|
$character = $this->generateCharacter(1); |
135
|
|
|
Assert::true($character->canAct()); |
136
|
|
|
$character->effects[] = new CharacterEffect([ |
137
|
|
|
"id" => "stunEffect", |
138
|
|
|
"type" => SkillSpecial::TYPE_STUN, |
139
|
|
|
"duration" => CharacterEffect::DURATION_COMBAT, |
140
|
|
|
"valueAbsolute" => false, |
141
|
|
|
]); |
142
|
|
|
Assert::false($character->canAct()); |
143
|
|
|
$character->effects->removeByFilter(["id" => "stunEffect"]); |
144
|
|
|
Assert::true($character->canAct()); |
145
|
|
|
$character->harm($character->hitpoints / 2); |
146
|
|
|
Assert::true($character->canAct()); |
147
|
|
|
$character->harm($character->hitpoints); |
148
|
|
|
Assert::false($character->canAct()); |
149
|
|
|
$character->heal(1); |
150
|
|
|
Assert::true($character->canAct()); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
public function testCanDefend(): void |
154
|
|
|
{ |
155
|
|
|
$character = $this->generateCharacter(1); |
156
|
|
|
Assert::true($character->canDefend()); |
157
|
|
|
$character->effects[] = new CharacterEffect([ |
158
|
|
|
"id" => "stunEffect", |
159
|
|
|
"type" => SkillSpecial::TYPE_STUN, |
160
|
|
|
"duration" => CharacterEffect::DURATION_COMBAT, |
161
|
|
|
"valueAbsolute" => false, |
162
|
|
|
]); |
163
|
|
|
Assert::false($character->canDefend()); |
164
|
|
|
$character->effects->removeByFilter(["id" => "stunEffect"]); |
165
|
|
|
Assert::true($character->canDefend()); |
166
|
|
|
} |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
$test = new CharacterTest(); |
170
|
|
|
$test->run(); |
171
|
|
|
|