Issues (30)

src/CharacterEffect.php (1 issue)

Severity
1
<?php
2
declare(strict_types=1);
3
4
namespace HeroesofAbenez\Combat;
5
6
use Nexendrie\Utils\Constants;
7
use Symfony\Component\OptionsResolver\OptionsResolver;
8
9
/**
10
 * Data structure for effect on character
11
 *
12
 * @author Jakub Konečný
13
 * @property int|string $duration
14
 * @method void onApply(Character $character, CharacterEffect $effect)
15
 * @method void onRemove(Character $character, CharacterEffect $effect)
16
 */
17 1
class CharacterEffect {
18
  use \Nette\SmartObject;
19
20
  public const DURATION_COMBAT = "combat";
21
  public const DURATION_FOREVER = "forever";
22
23
  public readonly string $id;
24
  public readonly string $type;
25
  public readonly string $stat;
26
  public readonly int $value;
27
  public readonly bool $valueAbsolute;
28
  protected int|string $duration;
29
  /** @var callable[] */
30
  public array $onApply = [];
31
  /** @var callable[] */
32
  public array $onRemove = [];
33
  
34
  public function __construct(array $effect) {
35 1
    $resolver = new OptionsResolver();
36 1
    $this->configureOptions($resolver);
37 1
    $effect = $resolver->resolve($effect);
38 1
    if(!in_array($effect["type"], SkillSpecial::NO_STAT_TYPES, true) && $effect["stat"] === "") {
39
      throw new \InvalidArgumentException("The option stat with value '' is invalid.");
40
    }
41 1
    $this->id = $effect["id"];
42 1
    $this->type = $effect["type"];
43 1
    $this->stat = $effect["stat"];
44 1
    $this->value = $effect["value"];
45 1
    $this->valueAbsolute = $effect["valueAbsolute"];
46 1
    $this->duration = $effect["duration"];
47 1
    $this->registerDefaultHandlers();
48 1
  }
49
50
  protected function registerDefaultHandlers(): void {
51 1
    $this->onApply[] = function(Character $character, self $effect): void {
52 1
      $character->recalculateStats();
53 1
      if($effect->stat === Character::STAT_MAX_HITPOINTS) {
54 1
        $character->heal($effect->value);
55
      }
56 1
    };
57 1
    $this->onRemove[] = function(Character $character, self $effect): void {
58 1
      $character->recalculateStats();
59 1
      if($effect->stat === Character::STAT_MAX_HITPOINTS) {
60 1
        $character->harm($effect->value);
61
      }
62 1
    };
63 1
  }
64
65
  protected function configureOptions(OptionsResolver $resolver): void {
66 1
    $allStats = ["id", "type", "value", "valueAbsolute", "duration", "stat", ];
67 1
    $resolver->setRequired($allStats);
68 1
    $resolver->setAllowedTypes("id", "string");
69 1
    $resolver->setAllowedTypes("type", "string");
70 1
    $resolver->setAllowedValues("type", function(string $value): bool {
71 1
      return in_array($value, $this->getAllowedTypes(), true);
72 1
    });
73 1
    $resolver->setAllowedTypes("stat", "string");
74 1
    $resolver->setDefault("stat", "");
75 1
    $resolver->setAllowedValues("stat", function(string $value): bool {
76 1
      return $value === "" || in_array($value, $this->getAllowedStats(), true);
77 1
    });
78 1
    $resolver->setAllowedTypes("value", "integer");
79 1
    $resolver->setAllowedTypes("valueAbsolute", "bool");
80 1
    $resolver->setDefault("value", 0);
81 1
    $resolver->setAllowedTypes("duration", ["string", "integer"]);
82 1
    $resolver->setAllowedValues("duration", function($value): bool {
83 1
      return (in_array($value, $this->getDurations(), true)) || ($value > 0);
84 1
    });
85 1
  }
86
  
87
  protected function getAllowedStats(): array {
88 1
    return Constants::getConstantsValues(Character::class, "STAT_");
89
  }
90
91
  /**
92
   * @return string[]
93
   */
94
  protected function getAllowedTypes(): array {
95 1
    return Constants::getConstantsValues(SkillSpecial::class, "TYPE_");
96
  }
97
  
98
  /**
99
   * @return string[]
100
   */
101
  protected function getDurations(): array {
102 1
    return Constants::getConstantsValues(static::class, "DURATION_");
103
  }
104
105
  protected function getDuration(): int|string {
106 1
    return $this->duration;
107
  }
108
  
109
  /**
110
   * @throws \InvalidArgumentException
111
   */
112
  protected function setDuration(string|int $value): void {
113 1
    if(!is_int($value) && !in_array($value, $this->getDurations(), true)) {
114
      throw new \InvalidArgumentException("Invalid value set to CharacterEffect::\$duration. Expected string or integer.");
0 ignored issues
show
Line exceeds 120 characters; contains 123 characters
Loading history...
115
    }
116 1
    $this->duration = $value;
117 1
  }
118
}
119
?>