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.
- 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
|