pfrpg_core 0.0.2 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +23 -0
  3. data/Rakefile +1 -1
  4. data/lib/pfrpg_core/attack.rb +66 -0
  5. data/lib/pfrpg_core/attributes.rb +113 -0
  6. data/lib/pfrpg_core/avatar_url.rb +15 -0
  7. data/lib/pfrpg_core/bonus.rb +1 -1
  8. data/lib/pfrpg_core/character.rb +83 -0
  9. data/lib/pfrpg_core/class_feature.rb +31 -0
  10. data/lib/pfrpg_core/combat.rb +60 -0
  11. data/lib/pfrpg_core/demographics.rb +30 -0
  12. data/lib/pfrpg_core/derived/combat_bonuses.rb +78 -0
  13. data/lib/pfrpg_core/derived/defense.rb +29 -0
  14. data/lib/pfrpg_core/derived/magic.rb +145 -0
  15. data/lib/pfrpg_core/derived/misc.rb +114 -0
  16. data/lib/pfrpg_core/derived/offense.rb +49 -0
  17. data/lib/pfrpg_core/derived.rb +10 -0
  18. data/lib/pfrpg_core/effect_processor.rb +1 -1
  19. data/lib/pfrpg_core/effect_totaler.rb +29 -0
  20. data/lib/pfrpg_core/equipment_totaler.rb +14 -0
  21. data/lib/pfrpg_core/feat.rb +27 -0
  22. data/lib/pfrpg_core/feat_totaler.rb +61 -0
  23. data/lib/pfrpg_core/feature_duplicator.rb +26 -0
  24. data/lib/pfrpg_core/feature_totaler.rb +86 -0
  25. data/lib/pfrpg_core/filterable.rb +1 -1
  26. data/lib/pfrpg_core/filters/filter.rb +14 -0
  27. data/lib/pfrpg_core/filters/proficiency_mod.rb +34 -0
  28. data/lib/pfrpg_core/filters/prowess_mod.rb +20 -0
  29. data/lib/pfrpg_core/filters/ranged_attack_mod.rb +28 -0
  30. data/lib/pfrpg_core/filters/skill_focus_mod.rb +25 -0
  31. data/lib/pfrpg_core/filters/strength_mod.rb +21 -0
  32. data/lib/pfrpg_core/filters/weapon_finesse_mod.rb +24 -0
  33. data/lib/pfrpg_core/filters/weapon_focus_mod.rb +23 -0
  34. data/lib/pfrpg_core/filters/weapon_mastery_mod.rb +23 -0
  35. data/lib/pfrpg_core/filters/weapon_specialization_mod.rb +22 -0
  36. data/lib/pfrpg_core/filters/weapon_training_mod.rb +22 -0
  37. data/lib/pfrpg_core/inventory.rb +62 -0
  38. data/lib/pfrpg_core/item.rb +42 -0
  39. data/lib/pfrpg_core/level.rb +14 -0
  40. data/lib/pfrpg_core/level_parser.rb +9 -1
  41. data/lib/pfrpg_core/macros/macro.rb +62 -0
  42. data/lib/pfrpg_core/macros/manyshot_macro.rb +12 -0
  43. data/lib/pfrpg_core/macros/power_attack_macro.rb +12 -0
  44. data/lib/pfrpg_core/macros/rapid_shot_macro.rb +12 -0
  45. data/lib/pfrpg_core/macros/sneak_attack_macro.rb +33 -0
  46. data/lib/pfrpg_core/macros/vital_strike_macro.rb +12 -0
  47. data/lib/pfrpg_core/null_object.rb +31 -29
  48. data/lib/pfrpg_core/saving_throws.rb +43 -0
  49. data/lib/pfrpg_core/skills.rb +141 -0
  50. data/lib/pfrpg_core/specializer.rb +48 -0
  51. data/lib/pfrpg_core/spell.rb +37 -0
  52. data/lib/pfrpg_core/spell_books.rb +36 -0
  53. data/lib/pfrpg_core/spells_per_level.rb +53 -0
  54. data/lib/pfrpg_core/version.rb +1 -1
  55. data/lib/pfrpg_core/weapon_training_calculator.rb +36 -0
  56. data/lib/pfrpg_core.rb +13 -2
  57. data/test/alignment_test.rb +30 -0
  58. data/test/attributes_test.rb +50 -0
  59. data/test/bonus_test.rb +29 -0
  60. data/test/feat_totaler_test.rb +24 -7
  61. data/test/helper.rb +1 -1
  62. data/test/levels_test.rb +19 -0
  63. data/test/misc_test.rb +78 -0
  64. data/test/saves_test.rb +54 -0
  65. data/test/skills_test.rb +93 -0
  66. data/test/test_helper.rb +78 -0
  67. metadata +66 -35
  68. data/lib/pfrpg_core/affectable.rb +0 -7
  69. data/lib/pfrpg_core/effect.rb +0 -39
  70. data/lib/pfrpg_core/prerequisite.rb +0 -58
  71. data/lib/pfrpg_core/quick_classed.rb +0 -37
@@ -0,0 +1,141 @@
1
+ require 'pfrpg_skills'
2
+
3
+ module PfrpgCore
4
+ class PrettySkill
5
+ include PfrpgCore::Filterable
6
+ attr_reader :name, :class_skill, :stat_bonus, :ac_penalty,
7
+ :misc_bonus, :total_bonus, :trained_rank, :attribute,
8
+ :filters, :filter_str
9
+
10
+ def initialize(skill, character, skill_filters)
11
+ @class_skill = is_class_skill?(skill, character)
12
+ @ac_penalty = calculate_ac_penalty(skill, character)
13
+ @name = skill[:skill].description
14
+ if skill[:char_skill]
15
+ @trained_rank = skill[:char_skill]['trained_rank']
16
+ else
17
+ @trained_rank = 0
18
+ end
19
+ @stat_bonus = calculate_attribute_bonus(skill, character)
20
+ @misc_bonus = calculate_misc_bonus(skill, character)
21
+ @attribute = skill[:skill].attribute
22
+ @total_bonus = total_bonuses
23
+ @filters = skill_filters
24
+ @filter_str = []
25
+ apply_filters
26
+ end
27
+
28
+ def misc_bonus=(misc)
29
+ @misc_bonus=misc
30
+ end
31
+
32
+ def as_json(options={})
33
+ {
34
+ :class_skill => @class_skill,
35
+ :ac_penalty => @ac_penalty,
36
+ :name => @name,
37
+ :trained_rank => @trained_rank,
38
+ :stat_bonus => @stat_bonus,
39
+ :misc_bonus => @misc_bonus,
40
+ :total_bonus => @total_bonus,
41
+ :attribute => @attribute
42
+ }
43
+ end
44
+
45
+ def is_class_skill?(skill, character)
46
+ found = character.levels.any? do |l|
47
+ l.heroclass.skills.find { |x| x.to_s == skill[:skill].to_s }
48
+ end
49
+ found ||= class_skill_bonuses(character).find do |x|
50
+ if x
51
+ x.downcase == skill[:skill].description.downcase
52
+ else
53
+ false
54
+ end
55
+ end
56
+ return (found != nil)
57
+ end
58
+
59
+ def class_skill_bonuses(character)
60
+ bonuses = character.get_bonus("class_skill")
61
+ return bonuses || []
62
+ end
63
+
64
+ def calculate_ac_penalty(skill, character)
65
+ ac_penalty = 0
66
+ if skill[:skill].ac_penalty?
67
+ ac_penalty = character.get_ac_penalty
68
+ end
69
+ ac_penalty
70
+ end
71
+
72
+ def calculate_attribute_bonus(skill, character)
73
+ attribute = skill[:skill].attribute
74
+ character.attributes.send("#{attribute}_mod") || 0
75
+ end
76
+
77
+ def total_bonuses
78
+ total = @misc_bonus + @stat_bonus - @ac_penalty + @trained_rank
79
+ total += 3 if (@class_skill && @trained_rank > 0)
80
+ total
81
+ end
82
+
83
+ def calculate_misc_bonus(skill, character)
84
+ if skill[:skill].respond_to? "bonus_str"
85
+ return character.get_bonus(skill[:skill].bonus_str).to_i
86
+ else
87
+ return character.get_bonus(skill[:skill].description).to_i
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ class Skills
94
+ attr_reader :skills, :max_training_level
95
+ def initialize(character)
96
+ @character = character
97
+ @bonuses = character.bonuses
98
+ @attributes= character.attributes
99
+ @skillz = character.base_skills || []
100
+ @max_training_level = character.hit_die
101
+ @skills = @skillz.map { |x| PrettySkill.new(x, @character, skill_filters) }
102
+ end
103
+
104
+ def skill_filters
105
+ [
106
+ Filters::SkillFocusMod.new(@character),
107
+ Filters::ProwessMod.new(@character)
108
+ ]
109
+ end
110
+
111
+ def as_json(options={})
112
+ skillz = {}
113
+ @skills.each do |s|
114
+ skillz[s.name] = s
115
+ end
116
+ skillz
117
+ end
118
+
119
+ def current_trained_ranks(name)
120
+ begin
121
+ get_skill(name).trained_rank
122
+ rescue Exception => e
123
+ return 0
124
+ end
125
+ end
126
+
127
+ def get_skill(name)
128
+ @skills.find { |x| x.name.downcase[name.downcase] }
129
+ end
130
+
131
+ def skills_per_level(heroclass, favored_bonus)
132
+ base = heroclass.skills_per_level
133
+ i = @attributes.int_mod
134
+ r = ((@character.race.name == 'Human') && 1) || 0 # +1 for Human
135
+ f = ((favored_bonus == 'skill') && 1) || 0 # +1 for favored
136
+ # puts "base #{base} + i #{i} + r #{r} + f #{f} = #{base + i + r + f}"
137
+ return base + i + r + f
138
+ end
139
+
140
+ end
141
+ end
@@ -0,0 +1,48 @@
1
+ module PfrpgCore
2
+ class Specializer
3
+ attr_reader :character, :proficient_types
4
+ def initialize(character)
5
+ @character = character
6
+ @proficient_types = proficiency_strings(character)
7
+ end
8
+
9
+ def proficiency_strings(character)
10
+ proficient_items = { :types => [], :singles => [] }
11
+ prof_feats = character.feats.select { |x| x.name['Proficiency'] }
12
+ prof_feats.each do |feat|
13
+ proficient_items[:types] << parse_types(feat)
14
+ proficient_items[:singles] << parse_singles(feat)
15
+ end
16
+ proficient_items[:types] = proficient_items[:types].flatten
17
+ proficient_items[:singles] = proficient_items[:singles].flatten
18
+ proficient_items
19
+ end
20
+
21
+ def parse_types(feat)
22
+ if feat.effects && feat.effects['TYPE']
23
+ read_str(feat.effects)
24
+ end
25
+ end
26
+
27
+ def parse_singles(feat)
28
+ if feat.effects && feat.effects['SINGLE']
29
+ feat.special
30
+ elsif feat.effects && feat.effects['GROUP']
31
+ read_str(feat.effects)
32
+ end
33
+ end
34
+
35
+ def read_str(str)
36
+ str.split(':')[1].split(';')[0]
37
+ end
38
+
39
+ def is_proficient_in_weapon?(weapon)
40
+ return true if weapon.weapon_type == 'natural'
41
+ proficient_types[:types].include?(weapon.weapon_type) || proficient_types[:singles].include?(weapon.name)
42
+ end
43
+
44
+ def is_proficient_in_armor?(armor)
45
+ proficient_types[:types].include? armor.weight_class
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,37 @@
1
+ module PfrpgCore
2
+ class Spell
3
+ attr_reader :id, :name, :spell_level, :effect, :targets, :duration,
4
+ :range, :saving_throw, :spell_resistance, :sorcerer_level,
5
+ :description
6
+
7
+ def initialize(array)
8
+ @id = array[0]
9
+ @name = array[1]
10
+ @spell_level = array[2]
11
+ @effect = array[3]
12
+ @targets = array[4]
13
+ @duration = array[5]
14
+ @range = array[6]
15
+ @saving_throw = array[7]
16
+ @spell_resistance = array[8]
17
+ @sorcerer_level = array[9]
18
+ @description = array[10]
19
+ end
20
+
21
+ def as_json(options={})
22
+ {
23
+ :id => id,
24
+ :name => name,
25
+ :spell_level => spell_level,
26
+ :effect => effect,
27
+ :targets => targets,
28
+ :duration => duration,
29
+ :range => range,
30
+ :saving_throw => saving_throw,
31
+ :spell_resistance => spell_resistance,
32
+ :sorcerer_level => sorcerer_level,
33
+ :description => description
34
+ }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ module PfrpgCore
2
+ class SpellBooks
3
+
4
+ class InvalidClassException < Exception; end
5
+ class SpellNotFoundException < Exception; end
6
+ class TooManySpellsException < Exception; end
7
+ class InvalidSpellException < Exception; end
8
+ class TooLowAttributeException < Exception; end
9
+
10
+ attr_reader :sorcerer, :cleric, :wizard, :druid, :paladin,
11
+ :ranger, :bard
12
+ def initialize(character)
13
+ l = character.latest_levels
14
+ @wizard = character.spells_per_level('Wizard', l)
15
+ @cleric = character.spells_per_level('Cleric', l)
16
+ @druid = character.spells_per_level('Druid', l)
17
+ @paladin = character.spells_per_level('Paladin', l)
18
+ @ranger = character.spells_per_level('Ranger', l)
19
+ @bard = character.spells_per_level('Bard', l)
20
+ @sorcerer = character.known_sorcerer_spells
21
+ end
22
+
23
+ def as_json(options={})
24
+ {
25
+ :sorcerer_spells => @sorcerer,
26
+ :Cleric => @cleric,
27
+ :Wizard => @wizard,
28
+ :Druid => @druid,
29
+ :Paladin => @paladin,
30
+ :Ranger => @ranger,
31
+ :Bard => @bard
32
+ }
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,53 @@
1
+ module PfrpgCore
2
+ class SpellsPerLevel
3
+ def initialize(character)
4
+ @character = character
5
+ @spells = {}
6
+ end
7
+
8
+ def get_sorcerer_spells
9
+ @character.known_sorcerer_spells
10
+ end
11
+
12
+ def get_cleric
13
+ []
14
+ end
15
+
16
+ def get_sorcerer
17
+ []
18
+ end
19
+
20
+ def get_wizard
21
+ []
22
+ end
23
+
24
+ def get_druid
25
+ []
26
+ end
27
+
28
+ def get_ranger
29
+ []
30
+ end
31
+
32
+ def get_bard
33
+ []
34
+ end
35
+
36
+ def get_paladin
37
+ []
38
+ end
39
+
40
+ def as_json(options={})
41
+ l = @character.latest_levels
42
+ {
43
+ :sorcerer_spells => get_sorcerer_spells,
44
+ :Cleric => @character.spells_per_level('Cleric', l),
45
+ :Wizard => @character.spells_per_level('Wizard', l),
46
+ :Druid => @character.spells_per_level('Druid', l),
47
+ :Paladin => @character.spells_per_level('Paladin', l),
48
+ :Ranger => @character.spells_per_level('Ranger', l),
49
+ :Bard => @character.spells_per_level('Bard', l)
50
+ }
51
+ end
52
+ end
53
+ end
@@ -1,3 +1,3 @@
1
1
  module PfrpgCore
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -0,0 +1,36 @@
1
+ module PfrpgCore
2
+ class WeaponTrainingCalculator
3
+ attr_reader :character, :trained_types
4
+ def initialize(character)
5
+ @character = character
6
+ @trained_types = gen_trained_types
7
+ end
8
+
9
+ def gen_trained_types
10
+ types = []
11
+ trains = character.class_features.select { |x| x.type['WeaponTraining'] }
12
+ trains.sort! { |x,y| x.created < y.created }
13
+ trains.each do |train|
14
+ types << train.ability_name
15
+ end
16
+ types
17
+ end
18
+
19
+ def feature_trained?(weapon, feature)
20
+ PfrpgTables::Tables::Weapons.weapon_training_members(feature.ability_name).include? weapon.get_base_name
21
+ end
22
+
23
+ def trained_value(weapon, feature)
24
+ return 0 unless feature_trained?(weapon, feature)
25
+ bonus = trained_types.size
26
+ weapon_name = weapon.get_base_name
27
+ trained_types.each do |t|
28
+ if PfrpgTables::Tables::Weapons.weapon_training_members(t).include? weapon_name
29
+ return bonus
30
+ end
31
+ bonus -= 1
32
+ end
33
+ return 0
34
+ end
35
+ end
36
+ end
data/lib/pfrpg_core.rb CHANGED
@@ -1,11 +1,22 @@
1
1
  module PfrpgCore
2
2
  end
3
3
 
4
- require 'pfrpg_core/effect'
4
+ require 'pfrpg_utility'
5
+
6
+ require 'pfrpg_core/filters/filter'
7
+ require 'pfrpg_core/macros/macro'
8
+ require 'pfrpg_core/attributes'
9
+ require 'pfrpg_core/bonus'
10
+ require 'pfrpg_core/derived'
11
+ require 'pfrpg_core/character'
12
+ require 'pfrpg_core/feature_duplicator'
5
13
  require 'pfrpg_core/effect_processor'
14
+ require 'pfrpg_core/feat_finder'
15
+ require 'pfrpg_core/filterable'
6
16
  require 'pfrpg_core/math_helper'
7
17
  require 'pfrpg_core/null_object'
18
+ require 'pfrpg_core/weapon_training_calculator'
8
19
 
9
20
  Dir[File.expand_path(File.join(File.dirname(File.absolute_path(__FILE__)), 'pfrpg_core/')) + "/**/*.rb"].each do |file|
10
21
  require file
11
- end
22
+ end
@@ -0,0 +1,30 @@
1
+ require 'minitest/autorun'
2
+ require 'pfrpg_core'
3
+ require 'pfrpg_utility'
4
+
5
+ class AlignmentTest < Minitest::Test
6
+
7
+ def test_abbreviation_parse
8
+ assert PfrpgUtility::Alignment.parse("CN") == 'Chaotic Neutral'
9
+ assert PfrpgUtility::Alignment.parse("CNP") == "CNP"
10
+ end
11
+
12
+ def test_unlawful
13
+ assert PfrpgUtility::Alignment.never_lawful.include? 'True Neutral'
14
+ assert !(PfrpgUtility::Alignment.never_lawful.include? 'Lawful Good')
15
+ end
16
+
17
+ def test_evil
18
+ assert PfrpgUtility::Alignment.any_evil.include? 'Lawful Evil'
19
+ assert !(PfrpgUtility::Alignment.any_evil.include? 'Lawful Good')
20
+ end
21
+
22
+ def test_any
23
+ assert PfrpgUtility::Alignment.any_evil.include? 'Lawful Evil'
24
+ end
25
+
26
+ def test_obj
27
+ assert PfrpgUtility::Alignment.new('CN').alignment == 'Chaotic Neutral'
28
+ end
29
+
30
+ end
@@ -0,0 +1,50 @@
1
+ require 'minitest/autorun'
2
+ require 'pfrpg_core'
3
+ require_relative './test_helper'
4
+
5
+ class AttributesTest < Minitest::Test
6
+ include TestHelper
7
+
8
+ def test_max_dex_bonus
9
+ b = basic_attributes
10
+ b[:max_dex] = 4
11
+ b[:raw_dex] = 20
12
+ attributes = PfrpgCore::Attributes.new(b, PfrpgCore::Bonuses.new)
13
+ assert attributes.dex_mod == 4
14
+ end
15
+
16
+ def test_max_dex_bonus
17
+ b = basic_attributes
18
+ b[:max_dex] = 6
19
+ b[:raw_dex] = 20
20
+ attributes = PfrpgCore::Attributes.new(b, PfrpgCore::Bonuses.new)
21
+ assert attributes.dex_mod == 5
22
+ end
23
+
24
+ def test_negative_bonus
25
+ b = basic_attributes
26
+ b[:raw_str] = 8
27
+ attributes = PfrpgCore::Attributes.new(b, PfrpgCore::Bonuses.new)
28
+ assert attributes.str_mod == -1
29
+ end
30
+
31
+ def test_positive_bonus
32
+ b = basic_attributes
33
+ b[:raw_wis] = 12
34
+ attributes = PfrpgCore::Attributes.new(b, PfrpgCore::Bonuses.new)
35
+ assert attributes.wis_mod == 1
36
+ end
37
+
38
+ def test_zero_bonus
39
+ attributes = PfrpgCore::Attributes.new(basic_attributes, PfrpgCore::Bonuses.new)
40
+ assert attributes.cha_mod == 0
41
+ end
42
+
43
+ def test_additional_bonus
44
+ bonuses = PfrpgCore::Bonuses.new
45
+ bonuses.plus('con', 4)
46
+ attributes = PfrpgCore::Attributes.new(basic_attributes, bonuses)
47
+ assert attributes.con_mod == 2
48
+ end
49
+
50
+ end
@@ -0,0 +1,29 @@
1
+ require 'minitest/autorun'
2
+ require 'pfrpg_core'
3
+
4
+ class BonusTest < Minitest::Test
5
+
6
+ class LilBonus
7
+ attr_reader :map
8
+ def initialize(map)
9
+ @map = map
10
+ end
11
+
12
+ def get(str)
13
+ return map[str]
14
+ end
15
+ end
16
+
17
+ class BonusTester
18
+ include PfrpgCore::Bonus
19
+ def apply_bonuses
20
+ @bonuses = LilBonus.new({"test" => "Bonus!"})
21
+ end
22
+ end
23
+
24
+ def test_bonuses
25
+ b = BonusTester.new
26
+ assert b.get_bonus("test") == 'Bonus!'
27
+ end
28
+
29
+ end
@@ -1,14 +1,31 @@
1
1
  require 'minitest/autorun'
2
- require 'test/helper'
2
+ require 'pfrpg_core'
3
3
 
4
- class FeatFinderTest < Minitest::Test
4
+ class FeatTotalerTest < Minitest::Test
5
+
6
+ MockFeat = Struct.new(:name) do
7
+ def prereq_code
8
+ nil
9
+ end
10
+ end
11
+
12
+ class MockEntity
13
+ attr_accessor :feats
14
+ def initialize(feats = nil)
15
+ @feats = feats
16
+ @feats ||= default_feats
17
+ end
18
+
19
+ def default_feats
20
+ [ MockFeat.new('Feat1') ]
21
+ end
22
+ end
5
23
 
6
24
  def test_filter_feats_by_owned
7
- e = PsuedoEntity.new
8
- feats = [ PsuedoFeat.new('Feat1') ]
9
- finder = FeatFinder.new(e, feats)
25
+ e = MockEntity.new
26
+ feats = [ MockFeat.new('Feat1') ]
27
+ finder = PfrpgCore::FeatFinder.new(e, feats)
10
28
  assert finder.find_feats.empty?
11
29
  end
12
30
 
13
-
14
- end
31
+ end
data/test/helper.rb CHANGED
@@ -14,7 +14,7 @@ class Helper
14
14
  end
15
15
 
16
16
  def default_feats
17
- [ PsuedoFeat.new('Feat1') ]
17
+ [ MockFeat.new('Feat1') ]
18
18
  end
19
19
  end
20
20
  end
@@ -0,0 +1,19 @@
1
+ require 'minitest/autorun'
2
+ require 'pfrpg_core'
3
+ require_relative './test_helper'
4
+
5
+ class LevelsTest < Minitest::Test
6
+ include TestHelper
7
+
8
+ def setup
9
+ @c = plain_character
10
+ end
11
+
12
+ def test_basic
13
+ assert @c.levels.size == 1
14
+ assert @c.levels[0].classname == 'Fighter'
15
+ assert @c.levels[0].rank == 10
16
+ assert @c.hit_die == 10
17
+ end
18
+
19
+ end
data/test/misc_test.rb ADDED
@@ -0,0 +1,78 @@
1
+ require 'minitest/autorun'
2
+ require 'pfrpg_core'
3
+ require_relative './test_helper'
4
+
5
+ class MiscTest < Minitest::Test
6
+ include TestHelper
7
+
8
+ def setup
9
+ @c = plain_character
10
+ end
11
+
12
+ def test_initiative
13
+ assert @c.initiative == 0
14
+ end
15
+
16
+ def test_upgraded_initiative_dex
17
+ @bonuses.plus('dex', 4)
18
+ @c.bonuses = @bonuses
19
+ assert @c.initiative == 2
20
+ end
21
+
22
+ def test_upgraded_initiative
23
+ @bonuses.plus('initiative', 4)
24
+ @c.bonuses = @bonuses
25
+ assert @c.initiative == 4
26
+ end
27
+
28
+ def test_speed
29
+ ['land','fly','climb','swim'].each do |type|
30
+ assert @c.speed["#{type}_speed"] == 30
31
+ end
32
+ end
33
+
34
+ class MockSlowArmor
35
+ def slot; 'armor'; end
36
+ def speed_thirty; 15; end
37
+ def speed_twenty; 10; end
38
+ end
39
+
40
+ def test_speed_heavy
41
+ @c.inventory = PfrpgCore::Inventory.new([MockSlowArmor.new], [])
42
+ assert @c.speed['land_speed'] == 15
43
+ end
44
+
45
+ def test_speed_heavy_dwarf
46
+ @c.race = PfrpgRaces::Race.fetch('Dwarf')
47
+ @c.inventory = PfrpgCore::Inventory.new([MockSlowArmor.new], [])
48
+ assert @c.speed['land_speed'] == 20
49
+ end
50
+
51
+ class MockMockCharacter
52
+ def hit_points; 15; end
53
+ end
54
+
55
+ def test_hit_points
56
+ @c.character = MockMockCharacter.new
57
+ assert @c.hit_points == 15
58
+ end
59
+
60
+ def test_hit_points
61
+ feats = [ PfrpgCore::Feat.new({name: 'Toughness'}) ]
62
+ @c.character = MockMockCharacter.new
63
+ @c.feats = feats
64
+ # formual for toughness
65
+ assert @c.hit_points == (15 + 3 + @c.total_level - 3)
66
+ end
67
+
68
+ def test_total_level
69
+ assert @c.total_level == 10
70
+ end
71
+
72
+ def test_total_level_more
73
+ @c.levels << PfrpgCore::Level.new(Le.new('Rogue', 5, false))
74
+ assert @c.total_level == 15
75
+ assert @c.hit_die == 15
76
+ end
77
+
78
+ end
@@ -0,0 +1,54 @@
1
+ require 'minitest/autorun'
2
+ require 'pfrpg_core'
3
+ require_relative './test_helper'
4
+
5
+ class SavesTest < Minitest::Test
6
+
7
+ include TestHelper
8
+
9
+ def setup
10
+ @bonuses = PfrpgCore::Bonuses.new
11
+ @attributes = PfrpgCore::Attributes.new(basic_attributes, @bonuses)
12
+ end
13
+
14
+ def test_basc
15
+ b = basic_saves
16
+ saves = PfrpgCore::SavingThrows.new(b, @bonuses, @attributes)
17
+ assert saves.reflex == 5
18
+ end
19
+
20
+ def test_positive_bonus
21
+ b = basic_saves
22
+ bonuses = PfrpgCore::Bonuses.new
23
+ bonuses.plus('ref', 4)
24
+ saves = PfrpgCore::SavingThrows.new(b, bonuses, @attributes)
25
+ assert saves.reflex == 9
26
+ end
27
+
28
+ def test_negative_bonus
29
+ b = basic_saves
30
+ bonuses = PfrpgCore::Bonuses.new
31
+ bonuses.plus('ref', -4)
32
+ saves = PfrpgCore::SavingThrows.new(b, bonuses, @attributes)
33
+ assert saves.reflex == 1
34
+ end
35
+
36
+ def test_con_bonus
37
+ @bonuses.plus('con', 4)
38
+ saves = PfrpgCore::SavingThrows.new(basic_saves, @bonuses, @attributes)
39
+ assert saves.fortitude == 7
40
+ end
41
+
42
+ def test_wis_bonus
43
+ @bonuses.plus('wis', -4)
44
+ saves = PfrpgCore::SavingThrows.new(basic_saves, @bonuses, @attributes)
45
+ assert saves.will == 3
46
+ end
47
+
48
+ def test_dex_bonus
49
+ @bonuses.plus('dex', 4)
50
+ @bonuses.plus('ref', -2)
51
+ saves = PfrpgCore::SavingThrows.new(basic_saves, @bonuses, @attributes)
52
+ assert saves.reflex == 5
53
+ end
54
+ end