amar-rpg 2.0.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 +7 -0
- data/LICENSE +675 -0
- data/README.md +155 -0
- data/amar-tui.rb +8195 -0
- data/cli_enc_output.rb +87 -0
- data/cli_enc_output_new.rb +433 -0
- data/cli_enc_output_new_3tier.rb +198 -0
- data/cli_enc_output_new_compact.rb +238 -0
- data/cli_name_gen.rb +21 -0
- data/cli_npc_output.rb +279 -0
- data/cli_npc_output_new.rb +700 -0
- data/cli_town_output.rb +39 -0
- data/cli_weather_output.rb +36 -0
- data/includes/class_enc.rb +341 -0
- data/includes/class_enc_new.rb +512 -0
- data/includes/class_monster_new.rb +551 -0
- data/includes/class_npc.rb +1378 -0
- data/includes/class_npc_new.rb +1187 -0
- data/includes/class_npc_new.rb.backup +706 -0
- data/includes/class_npc_new_skills.rb +153 -0
- data/includes/class_town.rb +237 -0
- data/includes/d6s.rb +40 -0
- data/includes/equipment_tables.rb +120 -0
- data/includes/functions.rb +67 -0
- data/includes/includes.rb +30 -0
- data/includes/randomizer.rb +15 -0
- data/includes/spell_catalog.rb +441 -0
- data/includes/tables/armour.rb +13 -0
- data/includes/tables/chartype.rb +4412 -0
- data/includes/tables/chartype_new.rb +765 -0
- data/includes/tables/chartype_new_full.rb +2713 -0
- data/includes/tables/enc_specific.rb +168 -0
- data/includes/tables/enc_type.rb +17 -0
- data/includes/tables/encounters.rb +99 -0
- data/includes/tables/magick.rb +169 -0
- data/includes/tables/melee.rb +36 -0
- data/includes/tables/missile.rb +17 -0
- data/includes/tables/monster_stats_new.rb +264 -0
- data/includes/tables/month.rb +18 -0
- data/includes/tables/names.rb +21 -0
- data/includes/tables/personality.rb +12 -0
- data/includes/tables/race_templates.rb +318 -0
- data/includes/tables/religions.rb +266 -0
- data/includes/tables/spells_new.rb +496 -0
- data/includes/tables/tier_system.rb +104 -0
- data/includes/tables/town.rb +71 -0
- data/includes/tables/weather.rb +41 -0
- data/includes/town_relations.rb +127 -0
- data/includes/weather.rb +108 -0
- data/includes/weather2latex.rb +114 -0
- data/lib/rcurses.rb +33 -0
- metadata +157 -0
@@ -0,0 +1,512 @@
|
|
1
|
+
# New Encounter class for the 3-tier system
|
2
|
+
|
3
|
+
class EncNew
|
4
|
+
attr_reader :terrain, :terraintype, :enc, :enc_spec, :enc_number, :enc_attitude
|
5
|
+
attr_reader :npcs, :encounter
|
6
|
+
|
7
|
+
def initialize(enc_spec = "", enc_number = 0, terraintype = nil, level_mod = 0)
|
8
|
+
# Set defaults
|
9
|
+
@terraintype = terraintype || $Terraintype || 8 # Default to day/rural
|
10
|
+
@level_mod = level_mod || $Level || 0
|
11
|
+
@terrain = @terraintype % 8 # Extract terrain from terraintype
|
12
|
+
@day = @terraintype >= 8 ? 1 : 0 # Extract day/night
|
13
|
+
|
14
|
+
@enc_spec = enc_spec.to_s
|
15
|
+
@enc_number = enc_number.to_i
|
16
|
+
@encounter = []
|
17
|
+
@npcs = []
|
18
|
+
|
19
|
+
# Load tables if not loaded
|
20
|
+
unless defined?($Enc_type)
|
21
|
+
load File.join($pgmdir, "includes/tables/enc_type.rb")
|
22
|
+
load File.join($pgmdir, "includes/tables/enc_specific.rb")
|
23
|
+
load File.join($pgmdir, "includes/tables/encounters.rb")
|
24
|
+
end
|
25
|
+
|
26
|
+
# Generate attitude
|
27
|
+
generate_attitude
|
28
|
+
|
29
|
+
# Generate the encounter
|
30
|
+
if @enc_spec.empty?
|
31
|
+
generate_random_encounter
|
32
|
+
else
|
33
|
+
generate_specific_encounter
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def generate_attitude
|
40
|
+
# Generate encounter attitude
|
41
|
+
case d6
|
42
|
+
when 1
|
43
|
+
@enc_attitude = "HOSTILE"
|
44
|
+
when 2
|
45
|
+
@enc_attitude = "ANTAGONISTIC"
|
46
|
+
when 3..4
|
47
|
+
@enc_attitude = "NEUTRAL"
|
48
|
+
when 5
|
49
|
+
@enc_attitude = "POSITIVE"
|
50
|
+
when 6
|
51
|
+
@enc_attitude = "FRIENDLY"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def generate_random_encounter
|
56
|
+
# Use the encounter tables from old system
|
57
|
+
enc_terrain = {}
|
58
|
+
$Enc_type.each do |key, value|
|
59
|
+
enc_terrain[key] = value[@terraintype]
|
60
|
+
end
|
61
|
+
|
62
|
+
@enc_type = randomizer(enc_terrain)
|
63
|
+
|
64
|
+
# Handle no encounter
|
65
|
+
if @enc_type =~ /NO ENCOUNTER/
|
66
|
+
@encounter[0] = {}
|
67
|
+
@encounter[0]["string"] = "NO ENCOUNTER"
|
68
|
+
return
|
69
|
+
end
|
70
|
+
|
71
|
+
# Get specific encounter from type
|
72
|
+
if defined?($Enc_specific) && $Enc_specific[@enc_type]
|
73
|
+
enc_terrain2 = {}
|
74
|
+
$Enc_specific[@enc_type].each do |key, value|
|
75
|
+
enc_terrain2[key] = value[@terraintype]
|
76
|
+
end
|
77
|
+
@enc_spec = randomizer(enc_terrain2)
|
78
|
+
else
|
79
|
+
# Fallback to basic type
|
80
|
+
@enc_spec = @enc_type
|
81
|
+
end
|
82
|
+
|
83
|
+
# Generate number of encounters
|
84
|
+
if @enc_number == 0
|
85
|
+
case oD6
|
86
|
+
when -Float::INFINITY..3
|
87
|
+
@enc_number = 1
|
88
|
+
when 4
|
89
|
+
@enc_number = dX(3)
|
90
|
+
when 5
|
91
|
+
@enc_number = d6
|
92
|
+
when 6..7
|
93
|
+
@enc_number = 2 * d6
|
94
|
+
else
|
95
|
+
@enc_number = 3 * d6
|
96
|
+
end
|
97
|
+
@enc_number = 5 if @enc_number > 5 && @enc_type =~ /onster/
|
98
|
+
end
|
99
|
+
|
100
|
+
# For humanoid encounters, sometimes create mixed groups
|
101
|
+
if @enc_type =~ /human/i && @enc_number > 3 && rand(100) < 30
|
102
|
+
generate_mixed_group
|
103
|
+
else
|
104
|
+
# Generate NPCs normally
|
105
|
+
generate_npcs_from_tables
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def generate_specific_encounter
|
110
|
+
@enc = @enc_spec
|
111
|
+
@enc_type = "human" # Default type
|
112
|
+
|
113
|
+
# Generate number if not specified
|
114
|
+
if @enc_number == 0
|
115
|
+
@enc_number = rand(6) + 1
|
116
|
+
end
|
117
|
+
|
118
|
+
# Generate NPCs
|
119
|
+
generate_npcs_from_tables
|
120
|
+
end
|
121
|
+
|
122
|
+
def generate_mixed_group
|
123
|
+
# Create a diverse but logical group
|
124
|
+
# Examples: merchant caravan, adventuring party, soldiers with support
|
125
|
+
|
126
|
+
# Load required classes if needed
|
127
|
+
unless defined?(NpcNew)
|
128
|
+
load File.join($pgmdir, "includes/class_npc_new.rb")
|
129
|
+
end
|
130
|
+
|
131
|
+
group_type = rand(100)
|
132
|
+
|
133
|
+
if group_type < 25
|
134
|
+
# Merchant caravan
|
135
|
+
leader_count = 1 + rand(2)
|
136
|
+
guard_count = (@enc_number - leader_count) * 2 / 3
|
137
|
+
worker_count = @enc_number - leader_count - guard_count
|
138
|
+
|
139
|
+
enc_types = []
|
140
|
+
leader_count.times { enc_types << "Merchant" }
|
141
|
+
guard_count.times { enc_types << ["Guard", "Warrior", "Soldier"].sample }
|
142
|
+
worker_count.times { enc_types << ["Worker", "Farmer", "Porter"].sample }
|
143
|
+
|
144
|
+
@enc_spec = "Mixed merchant caravan"
|
145
|
+
elsif group_type < 50
|
146
|
+
# Adventuring party
|
147
|
+
enc_types = []
|
148
|
+
enc_types << ["Warrior", "Soldier", "Gladiator"].sample
|
149
|
+
enc_types << ["Priest", "Cleric", "Healer"].sample if @enc_number > 2
|
150
|
+
enc_types << ["Wizard (fire)", "Wizard (water)", "Wizard (air)", "Wizard (earth)"].sample if @enc_number > 3
|
151
|
+
enc_types << ["Thief", "Ranger", "Scout"].sample if @enc_number > 4
|
152
|
+
|
153
|
+
# Fill rest with warriors/fighters
|
154
|
+
while enc_types.length < @enc_number
|
155
|
+
enc_types << ["Warrior", "Ranger", "Soldier", "Guard"].sample
|
156
|
+
end
|
157
|
+
|
158
|
+
@enc_spec = "Adventuring party"
|
159
|
+
elsif group_type < 75
|
160
|
+
# Military patrol
|
161
|
+
officer_count = 1
|
162
|
+
soldier_count = @enc_number - 1
|
163
|
+
|
164
|
+
enc_types = []
|
165
|
+
officer_count.times { enc_types << "Army officer" }
|
166
|
+
soldier_count.times { enc_types << ["Soldier", "Guard", "Warrior"].sample }
|
167
|
+
|
168
|
+
@enc_spec = "Military patrol"
|
169
|
+
else
|
170
|
+
# Bandits/thieves
|
171
|
+
leader_count = 1
|
172
|
+
thief_count = (@enc_number - leader_count) / 2
|
173
|
+
muscle_count = @enc_number - leader_count - thief_count
|
174
|
+
|
175
|
+
enc_types = []
|
176
|
+
leader_count.times { enc_types << ["Assassin", "Highwayman", "Bandit"].sample }
|
177
|
+
thief_count.times { enc_types << ["Thief", "Rogue", "Highwayman"].sample }
|
178
|
+
muscle_count.times { enc_types << ["Warrior", "Barbarian", "Thug"].sample }
|
179
|
+
|
180
|
+
@enc_spec = "Bandit group"
|
181
|
+
end
|
182
|
+
|
183
|
+
# Generate the NPCs
|
184
|
+
enc_types.shuffle! # Randomize order
|
185
|
+
|
186
|
+
@enc_number.times do |i|
|
187
|
+
@encounter[i] = {}
|
188
|
+
@encounter[i]["string"] = enc_types[i] || "Commoner"
|
189
|
+
|
190
|
+
# Generate level with some variety
|
191
|
+
base_level = rand(3) + 1 + @level_mod
|
192
|
+
if i == 0 && group_type != 50 # Leader gets bonus (except adventuring party)
|
193
|
+
base_level += 1
|
194
|
+
end
|
195
|
+
@encounter[i]["level"] = [base_level, 1].max
|
196
|
+
|
197
|
+
# Generate sex
|
198
|
+
@encounter[i]["sex"] = rand(2) == 0 ? "F" : "M"
|
199
|
+
|
200
|
+
# Create NPC
|
201
|
+
npc = NpcNew.new(
|
202
|
+
"", # Name will be generated
|
203
|
+
enc_types[i] || "Commoner",
|
204
|
+
@encounter[i]["level"],
|
205
|
+
"", # Area
|
206
|
+
@encounter[i]["sex"],
|
207
|
+
0, # Age will be generated
|
208
|
+
0, # Height will be generated
|
209
|
+
0, # Weight will be generated
|
210
|
+
"" # Description
|
211
|
+
)
|
212
|
+
|
213
|
+
@encounter[i]["npc"] = npc
|
214
|
+
@npcs << npc
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def generate_npcs_from_tables
|
219
|
+
# Load required classes if needed
|
220
|
+
unless defined?(MonsterNew)
|
221
|
+
load File.join($pgmdir, "includes/class_monster_new.rb")
|
222
|
+
end
|
223
|
+
|
224
|
+
unless defined?(NpcNew)
|
225
|
+
load File.join($pgmdir, "includes/class_npc_new.rb")
|
226
|
+
end
|
227
|
+
|
228
|
+
# Generate NPCs based on encounter tables
|
229
|
+
@enc_number.times do |i|
|
230
|
+
@encounter[i] = {}
|
231
|
+
@encounter[i]["string"] = @enc_spec
|
232
|
+
|
233
|
+
# Skip if event
|
234
|
+
if @encounter[i]["string"] =~ /Event:/
|
235
|
+
break
|
236
|
+
end
|
237
|
+
|
238
|
+
# Check if this is a monster/animal encounter
|
239
|
+
if @enc_spec =~ /Monster:|Animal:|animal:/i
|
240
|
+
# Generate level for monster
|
241
|
+
if defined?($Encounters) && $Encounters[@enc_spec]
|
242
|
+
stats = $Encounters[@enc_spec].dup
|
243
|
+
base_level = stats[0].is_a?(Array) ? dX(stats[0]) : stats[0]
|
244
|
+
else
|
245
|
+
base_level = rand(3) + 1
|
246
|
+
end
|
247
|
+
|
248
|
+
@encounter[i]["level"] = base_level + @level_mod
|
249
|
+
@encounter[i]["level"] = 1 if @encounter[i]["level"] < 1
|
250
|
+
|
251
|
+
# Create monster/animal NPC
|
252
|
+
npc = MonsterNew.new(@enc_spec, @encounter[i]["level"])
|
253
|
+
@encounter[i]["sex"] = npc.sex
|
254
|
+
else
|
255
|
+
# Handle humanoid encounters
|
256
|
+
# Check if this is a race-prefixed encounter (e.g., "Faerie: Sailor")
|
257
|
+
lookup_spec = @enc_spec
|
258
|
+
if @enc_spec =~ /^(\w+):\s+(.+)/
|
259
|
+
race_prefix = $1
|
260
|
+
base_type = $2
|
261
|
+
lookup_spec = base_type # Look up the base type in encounters table
|
262
|
+
end
|
263
|
+
|
264
|
+
# Get stats from encounter table if exists
|
265
|
+
if defined?($Encounters) && $Encounters[lookup_spec]
|
266
|
+
stats = $Encounters[lookup_spec].dup
|
267
|
+
|
268
|
+
# Generate level with modifier
|
269
|
+
base_level = stats[0].is_a?(Array) ? dX(stats[0]) : stats[0]
|
270
|
+
@encounter[i]["level"] = base_level + @level_mod
|
271
|
+
@encounter[i]["level"] += 2 if @enc_spec =~ /Elf|Faerie/
|
272
|
+
@encounter[i]["level"] += 1 if @enc_spec =~ /Dwarf/
|
273
|
+
@encounter[i]["level"] = 1 if @encounter[i]["level"] < 1
|
274
|
+
|
275
|
+
# Determine character type from encounter
|
276
|
+
char_type = determine_character_type(@enc_spec)
|
277
|
+
else
|
278
|
+
# Fallback values
|
279
|
+
@encounter[i]["level"] = rand(3) + 1 + @level_mod
|
280
|
+
@encounter[i]["level"] = 1 if @encounter[i]["level"] < 1
|
281
|
+
char_type = determine_character_type(@enc_spec)
|
282
|
+
end
|
283
|
+
|
284
|
+
# Generate sex
|
285
|
+
@encounter[i]["sex"] = rand(2) == 0 ? "F" : "M"
|
286
|
+
@encounter[i]["sex"] = "M" if @enc_spec =~ /officer/ && rand(6) != 0
|
287
|
+
@encounter[i]["sex"] = "F" if @enc_spec =~ /Prostitute/ && rand(10) != 0
|
288
|
+
@encounter[i]["sex"] = "F" if @enc_spec =~ /Nanny/ && rand(10) != 0
|
289
|
+
@encounter[i]["sex"] = "F" if @enc_spec =~ /wife/
|
290
|
+
|
291
|
+
# Create NPC with new system
|
292
|
+
npc = NpcNew.new(
|
293
|
+
"", # Name will be generated
|
294
|
+
char_type,
|
295
|
+
@encounter[i]["level"],
|
296
|
+
"", # Area
|
297
|
+
@encounter[i]["sex"],
|
298
|
+
0, # Age will be generated
|
299
|
+
0, # Height will be generated
|
300
|
+
0, # Weight will be generated
|
301
|
+
"" # Description
|
302
|
+
)
|
303
|
+
end
|
304
|
+
|
305
|
+
@encounter[i]["npc"] = npc
|
306
|
+
@npcs << npc
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def determine_character_type(enc_string)
|
311
|
+
# Map encounter strings to character types
|
312
|
+
# Check if encounter string already has race prefix
|
313
|
+
if enc_string =~ /^(\w+):\s+(.+)/
|
314
|
+
race = $1
|
315
|
+
profession = $2
|
316
|
+
|
317
|
+
# Map profession to appropriate type for that race
|
318
|
+
base_type = case profession.downcase
|
319
|
+
when /warrior/, /soldier/, /fighter/
|
320
|
+
"Warrior"
|
321
|
+
when /ranger/, /scout/, /hunter/
|
322
|
+
"Ranger"
|
323
|
+
when /mage/, /wizard/, /sorcerer/
|
324
|
+
"Mage"
|
325
|
+
when /thief/, /rogue/, /bandit/
|
326
|
+
"Thief"
|
327
|
+
when /smith/, /blacksmith/, /armour smith/
|
328
|
+
"Smith"
|
329
|
+
when /guard/, /watchman/
|
330
|
+
"Guard"
|
331
|
+
when /priest/, /cleric/, /monk/
|
332
|
+
"Priest"
|
333
|
+
when /merchant/, /trader/
|
334
|
+
"Merchant"
|
335
|
+
when /noble/, /lord/, /lady/
|
336
|
+
"Noble"
|
337
|
+
when /sailor/, /seaman/, /mariner/
|
338
|
+
"Sailor"
|
339
|
+
when /bard/, /minstrel/, /entertainer/
|
340
|
+
"Bard"
|
341
|
+
when /assassin/
|
342
|
+
"Assassin"
|
343
|
+
when /sage/, /scholar/
|
344
|
+
"Sage"
|
345
|
+
when /healer/, /physician/
|
346
|
+
"Healer"
|
347
|
+
when /commoner/, /farmer/, /peasant/
|
348
|
+
"Commoner"
|
349
|
+
else
|
350
|
+
# Use the profession directly if not matched
|
351
|
+
profession.capitalize
|
352
|
+
end
|
353
|
+
|
354
|
+
# Return race-specific type if it exists in templates
|
355
|
+
race_type = "#{race}: #{base_type}"
|
356
|
+
|
357
|
+
# Check if this race-type combo exists in templates
|
358
|
+
if defined?($ChartypeNew) && $ChartypeNew.key?(race_type)
|
359
|
+
return race_type
|
360
|
+
elsif defined?($RaceTemplates) && $RaceTemplates.key?(race_type)
|
361
|
+
return race_type
|
362
|
+
else
|
363
|
+
# Try alternate names
|
364
|
+
alt_types = []
|
365
|
+
case base_type
|
366
|
+
when "Mage"
|
367
|
+
alt_types = ["Wizard", "Sorcerer"]
|
368
|
+
when "Warrior"
|
369
|
+
alt_types = ["Fighter", "Soldier"]
|
370
|
+
when "Ranger"
|
371
|
+
alt_types = ["Scout", "Hunter"]
|
372
|
+
end
|
373
|
+
|
374
|
+
for alt in alt_types
|
375
|
+
alt_race_type = "#{race}: #{alt}"
|
376
|
+
if (defined?($ChartypeNew) && $ChartypeNew.key?(alt_race_type)) ||
|
377
|
+
(defined?($RaceTemplates) && $RaceTemplates.key?(alt_race_type))
|
378
|
+
return alt_race_type
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
# Fallback to generic warrior for that race
|
383
|
+
return "#{race}: Warrior"
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
# Original logic for encounters without race prefix
|
388
|
+
case enc_string.downcase
|
389
|
+
when /elf/
|
390
|
+
# Elves can be various types
|
391
|
+
["Elf: Ranger", "Elf: Warrior", "Elf: Mage"].sample
|
392
|
+
when /dwarf/
|
393
|
+
# Dwarves are typically warriors or smiths
|
394
|
+
["Dwarf: Warrior", "Dwarf: Smith", "Dwarf: Guard"].sample
|
395
|
+
when /araxi/, /arax/
|
396
|
+
# Araxi are savage predatory warriors
|
397
|
+
"Araxi: Warrior"
|
398
|
+
when /troll/
|
399
|
+
"Troll: Warrior"
|
400
|
+
when /ogre/
|
401
|
+
"Ogre: Warrior"
|
402
|
+
when /lizard/
|
403
|
+
"Lizard Man: Warrior"
|
404
|
+
when /goblin/
|
405
|
+
["Goblin: Warrior", "Goblin: Thief"].sample
|
406
|
+
when /centaur/
|
407
|
+
["Centaur: Warrior", "Centaur: Ranger"].sample
|
408
|
+
when /faer/
|
409
|
+
"Faerie: Mage"
|
410
|
+
# Then check for profession-based encounters
|
411
|
+
when /warrior/, /soldier/, /guard/
|
412
|
+
"Warrior"
|
413
|
+
when /merchant/, /trader/, /caravan/
|
414
|
+
"Merchant"
|
415
|
+
when /thief/, /bandit/, /robber/
|
416
|
+
"Thief"
|
417
|
+
when /wizard/, /mage/, /sorcerer/
|
418
|
+
["Wizard (fire)", "Wizard (water)", "Wizard (air)", "Wizard (earth)"].sample
|
419
|
+
when /priest/, /cleric/, /monk/
|
420
|
+
"Priest"
|
421
|
+
when /ranger/, /scout/, /hunter/
|
422
|
+
"Ranger"
|
423
|
+
when /noble/, /lord/, /lady/
|
424
|
+
"Noble"
|
425
|
+
when /barbarian/
|
426
|
+
"Barbarian"
|
427
|
+
when /assassin/
|
428
|
+
"Assassin"
|
429
|
+
when /gladiator/
|
430
|
+
"Gladiator"
|
431
|
+
when /smith/, /blacksmith/, /weaponsmith/, /armorer/
|
432
|
+
"Smith"
|
433
|
+
when /farmer/, /peasant/, /laborer/
|
434
|
+
"Farmer"
|
435
|
+
when /sailor/, /seaman/, /mariner/
|
436
|
+
"Sailor"
|
437
|
+
when /bard/, /minstrel/, /storyteller/
|
438
|
+
"Bard"
|
439
|
+
when /sage/, /scholar/, /learned/, /wise/
|
440
|
+
"Sage"
|
441
|
+
when /scribe/, /clerk/, /secretary/
|
442
|
+
"Scribe"
|
443
|
+
when /healer/, /physician/, /apothecary/
|
444
|
+
"Healer"
|
445
|
+
when /entertainer/, /actor/, /dancer/
|
446
|
+
"Entertainer"
|
447
|
+
when /artisan/, /craftsman/, /crafter/
|
448
|
+
"Artisan"
|
449
|
+
when /guard/, /watchman/
|
450
|
+
"Guard"
|
451
|
+
else
|
452
|
+
"Commoner"
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
# Helper methods from old system
|
457
|
+
def d6
|
458
|
+
rand(6) + 1
|
459
|
+
end
|
460
|
+
|
461
|
+
def oD6
|
462
|
+
d6 + rand(3) - 1
|
463
|
+
end
|
464
|
+
|
465
|
+
def dX(x)
|
466
|
+
return 0 if x <= 0
|
467
|
+
if x.is_a?(Array)
|
468
|
+
x = x.first.to_i
|
469
|
+
end
|
470
|
+
sum = 0
|
471
|
+
x.times { sum += d6 }
|
472
|
+
sum
|
473
|
+
end
|
474
|
+
|
475
|
+
def randomizer(hash)
|
476
|
+
# Weight-based random selection
|
477
|
+
total = hash.values.sum
|
478
|
+
return "" if total == 0
|
479
|
+
|
480
|
+
roll = rand(total) + 1
|
481
|
+
cumulative = 0
|
482
|
+
|
483
|
+
hash.each do |key, weight|
|
484
|
+
cumulative += weight
|
485
|
+
return key if roll <= cumulative
|
486
|
+
end
|
487
|
+
|
488
|
+
hash.keys.first
|
489
|
+
end
|
490
|
+
|
491
|
+
public
|
492
|
+
|
493
|
+
def summary
|
494
|
+
if @encounter.first && @encounter.first["string"] == "NO ENCOUNTER"
|
495
|
+
"NO ENCOUNTER"
|
496
|
+
else
|
497
|
+
"#{@enc_number} #{@enc_spec}"
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
def get_npc(index)
|
502
|
+
@npcs[index] if index < @npcs.length
|
503
|
+
end
|
504
|
+
|
505
|
+
def total_threat_level
|
506
|
+
@npcs.sum { |npc| npc.level }
|
507
|
+
end
|
508
|
+
|
509
|
+
def is_no_encounter?
|
510
|
+
@encounter.first && @encounter.first["string"] == "NO ENCOUNTER"
|
511
|
+
end
|
512
|
+
end
|