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.
- checksums.yaml +4 -4
- data/LICENSE +23 -0
- data/Rakefile +1 -1
- data/lib/pfrpg_core/attack.rb +66 -0
- data/lib/pfrpg_core/attributes.rb +113 -0
- data/lib/pfrpg_core/avatar_url.rb +15 -0
- data/lib/pfrpg_core/bonus.rb +1 -1
- data/lib/pfrpg_core/character.rb +83 -0
- data/lib/pfrpg_core/class_feature.rb +31 -0
- data/lib/pfrpg_core/combat.rb +60 -0
- data/lib/pfrpg_core/demographics.rb +30 -0
- data/lib/pfrpg_core/derived/combat_bonuses.rb +78 -0
- data/lib/pfrpg_core/derived/defense.rb +29 -0
- data/lib/pfrpg_core/derived/magic.rb +145 -0
- data/lib/pfrpg_core/derived/misc.rb +114 -0
- data/lib/pfrpg_core/derived/offense.rb +49 -0
- data/lib/pfrpg_core/derived.rb +10 -0
- data/lib/pfrpg_core/effect_processor.rb +1 -1
- data/lib/pfrpg_core/effect_totaler.rb +29 -0
- data/lib/pfrpg_core/equipment_totaler.rb +14 -0
- data/lib/pfrpg_core/feat.rb +27 -0
- data/lib/pfrpg_core/feat_totaler.rb +61 -0
- data/lib/pfrpg_core/feature_duplicator.rb +26 -0
- data/lib/pfrpg_core/feature_totaler.rb +86 -0
- data/lib/pfrpg_core/filterable.rb +1 -1
- data/lib/pfrpg_core/filters/filter.rb +14 -0
- data/lib/pfrpg_core/filters/proficiency_mod.rb +34 -0
- data/lib/pfrpg_core/filters/prowess_mod.rb +20 -0
- data/lib/pfrpg_core/filters/ranged_attack_mod.rb +28 -0
- data/lib/pfrpg_core/filters/skill_focus_mod.rb +25 -0
- data/lib/pfrpg_core/filters/strength_mod.rb +21 -0
- data/lib/pfrpg_core/filters/weapon_finesse_mod.rb +24 -0
- data/lib/pfrpg_core/filters/weapon_focus_mod.rb +23 -0
- data/lib/pfrpg_core/filters/weapon_mastery_mod.rb +23 -0
- data/lib/pfrpg_core/filters/weapon_specialization_mod.rb +22 -0
- data/lib/pfrpg_core/filters/weapon_training_mod.rb +22 -0
- data/lib/pfrpg_core/inventory.rb +62 -0
- data/lib/pfrpg_core/item.rb +42 -0
- data/lib/pfrpg_core/level.rb +14 -0
- data/lib/pfrpg_core/level_parser.rb +9 -1
- data/lib/pfrpg_core/macros/macro.rb +62 -0
- data/lib/pfrpg_core/macros/manyshot_macro.rb +12 -0
- data/lib/pfrpg_core/macros/power_attack_macro.rb +12 -0
- data/lib/pfrpg_core/macros/rapid_shot_macro.rb +12 -0
- data/lib/pfrpg_core/macros/sneak_attack_macro.rb +33 -0
- data/lib/pfrpg_core/macros/vital_strike_macro.rb +12 -0
- data/lib/pfrpg_core/null_object.rb +31 -29
- data/lib/pfrpg_core/saving_throws.rb +43 -0
- data/lib/pfrpg_core/skills.rb +141 -0
- data/lib/pfrpg_core/specializer.rb +48 -0
- data/lib/pfrpg_core/spell.rb +37 -0
- data/lib/pfrpg_core/spell_books.rb +36 -0
- data/lib/pfrpg_core/spells_per_level.rb +53 -0
- data/lib/pfrpg_core/version.rb +1 -1
- data/lib/pfrpg_core/weapon_training_calculator.rb +36 -0
- data/lib/pfrpg_core.rb +13 -2
- data/test/alignment_test.rb +30 -0
- data/test/attributes_test.rb +50 -0
- data/test/bonus_test.rb +29 -0
- data/test/feat_totaler_test.rb +24 -7
- data/test/helper.rb +1 -1
- data/test/levels_test.rb +19 -0
- data/test/misc_test.rb +78 -0
- data/test/saves_test.rb +54 -0
- data/test/skills_test.rb +93 -0
- data/test/test_helper.rb +78 -0
- metadata +66 -35
- data/lib/pfrpg_core/affectable.rb +0 -7
- data/lib/pfrpg_core/effect.rb +0 -39
- data/lib/pfrpg_core/prerequisite.rb +0 -58
- 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
|
data/lib/pfrpg_core/version.rb
CHANGED
@@ -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 '
|
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
|
data/test/bonus_test.rb
ADDED
@@ -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
|
data/test/feat_totaler_test.rb
CHANGED
@@ -1,14 +1,31 @@
|
|
1
1
|
require 'minitest/autorun'
|
2
|
-
require '
|
2
|
+
require 'pfrpg_core'
|
3
3
|
|
4
|
-
class
|
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 =
|
8
|
-
feats = [
|
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
data/test/levels_test.rb
ADDED
@@ -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
|
data/test/saves_test.rb
ADDED
@@ -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
|