pfrpg_core 0.0.2 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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