amar-tui 2.1.0 → 2.1.5
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/amar-tui.rb +7 -4
- data/cli_npc_output_new.rb +72 -20
- data/includes/class_npc_new.rb +102 -1
- metadata +7 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 125a3a252cf7e2f0da6837a2dfb7f3a526e0f24a712183ba8acc699afc9dba1a
|
|
4
|
+
data.tar.gz: 0ed40220339f8bf83eb908c756c0677557bef623da788541e59ec154a437264e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 56bc6852d14d0434a8a5c53c19d862554c4db0b020e31e8dbc6e63f8d6ff85aaace4c0570d0663d5223304a9d450893ab7bc12ea77a3a35a3353b86fc27c899c
|
|
7
|
+
data.tar.gz: '014357922ee46c72392a3dee618569d2d785445cfcd6ab521083921ca68697cb771fdf6c745047bff2d5140c73d04c3e4aca36d042775e639b335f22ab6b5f06'
|
data/amar-tui.rb
CHANGED
|
@@ -60,7 +60,7 @@ require 'stringio' # For suppressing output
|
|
|
60
60
|
require 'fcntl' # For non-blocking IO
|
|
61
61
|
|
|
62
62
|
# GLOBAL VARS & CONSTANTS
|
|
63
|
-
@version = "2.1.
|
|
63
|
+
@version = "2.1.5"
|
|
64
64
|
$pgmdir = File.dirname(__FILE__) # Global for includes
|
|
65
65
|
|
|
66
66
|
# Debug logging
|
|
@@ -2048,17 +2048,20 @@ def npc_input_new_tui
|
|
|
2048
2048
|
show_content(type_text)
|
|
2049
2049
|
type_input = get_text_input("")
|
|
2050
2050
|
return nil if type_input == :cancelled
|
|
2051
|
-
|
|
2051
|
+
|
|
2052
2052
|
type = ""
|
|
2053
2053
|
if type_input && type_input.to_i > 0 && type_input.to_i <= types.length
|
|
2054
2054
|
type = types[type_input.to_i - 1]
|
|
2055
|
+
else
|
|
2056
|
+
# Random type selection (0 or empty input)
|
|
2057
|
+
type = types.sample
|
|
2055
2058
|
end
|
|
2056
|
-
|
|
2059
|
+
|
|
2057
2060
|
# If race is not Human and type doesn't already include race, prepend it
|
|
2058
2061
|
if race != "Human" && !type.include?(":")
|
|
2059
2062
|
type = "#{race}: #{type}" if !type.empty?
|
|
2060
2063
|
end
|
|
2061
|
-
|
|
2064
|
+
|
|
2062
2065
|
inputs << type
|
|
2063
2066
|
|
|
2064
2067
|
# Level selection
|
data/cli_npc_output_new.rb
CHANGED
|
@@ -94,10 +94,21 @@ def npc_output_new(n, cli, custom_width = nil)
|
|
|
94
94
|
n.tiers["BODY"].each do |attr_name, attr_data|
|
|
95
95
|
# Skip if attr_data is not a hash or doesn't have skills
|
|
96
96
|
next unless attr_data.is_a?(Hash) && attr_data["skills"].is_a?(Hash)
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
non_zero_skills = attr_data["skills"].select { |_, v| v > 0 }
|
|
99
|
+
|
|
100
|
+
# For Melee Combat and Missile Combat, show attribute but not individual weapon skills
|
|
101
|
+
if attr_name == "Melee Combat" || attr_name == "Missile Combat"
|
|
102
|
+
# Show attribute only if there are any skills
|
|
103
|
+
if non_zero_skills.any?
|
|
104
|
+
attr_level = attr_data["level"]
|
|
105
|
+
body_lines << " #{@attr_color}#{attr_name} (#{attr_level.to_s.rjust(2)})#{@reset}"
|
|
106
|
+
end
|
|
107
|
+
next # Skip individual weapon skills
|
|
108
|
+
end
|
|
109
|
+
|
|
99
110
|
next if non_zero_skills.empty?
|
|
100
|
-
|
|
111
|
+
|
|
101
112
|
attr_level = attr_data["level"]
|
|
102
113
|
body_lines << " #{@attr_color}#{attr_name} (#{attr_level.to_s.rjust(2)})#{@reset}"
|
|
103
114
|
non_zero_skills.each do |skill_name, skill_level|
|
|
@@ -274,11 +285,21 @@ def npc_output_new(n, cli, custom_width = nil)
|
|
|
274
285
|
f += "\n"
|
|
275
286
|
end
|
|
276
287
|
else
|
|
277
|
-
# 3-tier weapon display - show ALL weapon skills
|
|
288
|
+
# 3-tier weapon display - show ALL weapon skills with actual weapon names
|
|
278
289
|
melee_weapons = n.tiers["BODY"]["Melee Combat"]["skills"].select { |_, v| v > 0 } rescue {}
|
|
279
290
|
missile_weapons = n.tiers["BODY"]["Missile Combat"]["skills"].select { |_, v| v > 0 } rescue {}
|
|
291
|
+
actual_melee = (n.tiers["BODY"]["Melee Combat"]["actual_weapons"] rescue nil) || {}
|
|
292
|
+
actual_missile = (n.tiers["BODY"]["Missile Combat"]["actual_weapons"] rescue nil) || {}
|
|
280
293
|
|
|
281
294
|
if melee_weapons.any? || missile_weapons.any?
|
|
295
|
+
# Load weapon tables for stats lookup
|
|
296
|
+
unless defined?($Melee)
|
|
297
|
+
load File.join($pgmdir, "includes/tables/melee.rb")
|
|
298
|
+
end
|
|
299
|
+
unless defined?($Missile)
|
|
300
|
+
load File.join($pgmdir, "includes/tables/missile.rb")
|
|
301
|
+
end
|
|
302
|
+
|
|
282
303
|
f += "─" * width + "\n"
|
|
283
304
|
f += "#{@weapon_color}WEAPON SKILL INI OFF DEF DAM HP RANGE#{@reset}\n"
|
|
284
305
|
|
|
@@ -292,19 +313,35 @@ def npc_output_new(n, cli, custom_width = nil)
|
|
|
292
313
|
reaction_speed = n.get_skill_total("MIND", "Awareness", "Reaction speed") || 0
|
|
293
314
|
|
|
294
315
|
# Display melee weapons
|
|
295
|
-
melee_weapons.sort_by { |_, skill| -skill }.each do |
|
|
296
|
-
|
|
316
|
+
melee_weapons.sort_by { |_, skill| -skill }.each do |weapon_skill, skill|
|
|
317
|
+
# Get actual weapon name
|
|
318
|
+
actual_weapon_name = actual_melee[weapon_skill] || weapon_skill
|
|
319
|
+
|
|
320
|
+
# Find weapon in $Melee table
|
|
321
|
+
weapon_data = $Melee.find { |w| w && w[0] && w[0].strip == actual_weapon_name.strip }
|
|
322
|
+
|
|
297
323
|
attr = n.get_attribute("BODY", "Melee Combat") || 0
|
|
298
324
|
skill_total = body_char + attr + skill
|
|
299
325
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
326
|
+
if weapon_data
|
|
327
|
+
# Use actual weapon stats from table: [Name, Type, Str, Dam, Init, Off, Def, HP, Wt]
|
|
328
|
+
init = reaction_speed + weapon_data[4]
|
|
329
|
+
off = skill_total + weapon_data[5]
|
|
330
|
+
defense = skill_total + weapon_data[6] + dodge_bonus
|
|
331
|
+
dmg = (n.DB || 0) + weapon_data[3]
|
|
332
|
+
hp = weapon_data[7]
|
|
333
|
+
else
|
|
334
|
+
# Fallback to pattern matching
|
|
335
|
+
wpn_stats = get_weapon_stats(actual_weapon_name)
|
|
336
|
+
init = reaction_speed + (wpn_stats[:init] || 0)
|
|
337
|
+
off = skill_total + (wpn_stats[:off] || 0)
|
|
338
|
+
defense = skill_total + (wpn_stats[:def] || 0) + dodge_bonus
|
|
339
|
+
dmg_mod = wpn_stats[:dmg].to_s =~ /special/ ? 0 : (wpn_stats[:dmg].to_s.to_i || 0)
|
|
340
|
+
dmg = (n.DB || 0) + dmg_mod
|
|
341
|
+
hp = wpn_stats[:hp] || 0
|
|
342
|
+
end
|
|
306
343
|
|
|
307
|
-
f += "#{
|
|
344
|
+
f += "#{actual_weapon_name.ljust(19)}"
|
|
308
345
|
f += "#{skill_total.to_s.ljust(9)}"
|
|
309
346
|
f += "#{init.to_s.ljust(8)}"
|
|
310
347
|
f += "#{off.to_s.ljust(7)}"
|
|
@@ -315,18 +352,33 @@ def npc_output_new(n, cli, custom_width = nil)
|
|
|
315
352
|
end
|
|
316
353
|
|
|
317
354
|
# Display missile weapons
|
|
318
|
-
missile_weapons.sort_by { |_, skill| -skill }.each do |
|
|
319
|
-
|
|
355
|
+
missile_weapons.sort_by { |_, skill| -skill }.each do |weapon_skill, skill|
|
|
356
|
+
# Get actual weapon name
|
|
357
|
+
actual_weapon_name = actual_missile[weapon_skill] || weapon_skill
|
|
358
|
+
|
|
359
|
+
# Find weapon in $Missile table
|
|
360
|
+
weapon_data = $Missile.find { |w| w && w[0] && w[0].strip == actual_weapon_name.strip }
|
|
361
|
+
|
|
320
362
|
attr = n.get_attribute("BODY", "Missile Combat") || 0
|
|
321
363
|
skill_total = body_char + attr + skill
|
|
322
364
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
365
|
+
if weapon_data
|
|
366
|
+
# Use actual weapon stats from table: [Name, Type, Str, Dam, Off, Rng, Max, Init, Wt]
|
|
367
|
+
off = skill_total + weapon_data[4]
|
|
368
|
+
dmg = (n.DB || 0) + weapon_data[3]
|
|
369
|
+
range = "#{weapon_data[5]}m"
|
|
370
|
+
hp = weapon_data[7]
|
|
371
|
+
else
|
|
372
|
+
# Fallback to pattern matching
|
|
373
|
+
wpn_stats = get_missile_stats(actual_weapon_name)
|
|
374
|
+
off = skill_total + (wpn_stats[:off] || 0)
|
|
375
|
+
range = wpn_stats[:range] || "30m"
|
|
376
|
+
dmg_mod = wpn_stats[:dmg].to_s =~ /special/ ? 0 : (wpn_stats[:dmg].to_s.to_i || 0)
|
|
377
|
+
dmg = (n.DB || 0) + dmg_mod
|
|
378
|
+
hp = wpn_stats[:hp] || 0
|
|
379
|
+
end
|
|
328
380
|
|
|
329
|
-
f += "#{
|
|
381
|
+
f += "#{actual_weapon_name.ljust(19)}"
|
|
330
382
|
f += "#{skill_total.to_s.ljust(9)}"
|
|
331
383
|
f += "#{' '.ljust(8)}" # No init for missile
|
|
332
384
|
f += "#{off.to_s.ljust(7)}"
|
data/includes/class_npc_new.rb
CHANGED
|
@@ -18,7 +18,7 @@ class NpcNew
|
|
|
18
18
|
# Generate random values for missing data
|
|
19
19
|
@name = name && !name.empty? ? name : generate_random_name(sex)
|
|
20
20
|
@type = type
|
|
21
|
-
@level = level.to_i
|
|
21
|
+
@level = level.to_i > 0 ? level.to_i : rand(1..6) # Random level 1-6 if 0 or invalid
|
|
22
22
|
@area = area && !area.empty? ? area : ["Amaronir", "Merisir", "Calaronir", "Feronir", "Rauinir"].sample
|
|
23
23
|
@sex = sex && !sex.empty? ? sex : ["M", "F"].sample
|
|
24
24
|
|
|
@@ -460,14 +460,94 @@ class NpcNew
|
|
|
460
460
|
level
|
|
461
461
|
end
|
|
462
462
|
|
|
463
|
+
def select_actual_weapon_from_table(skill_name, strength_char, is_missile = false)
|
|
464
|
+
# Select actual weapon from $Melee or $Missile table based on skill and strength
|
|
465
|
+
# This mimics the original weapon selection system
|
|
466
|
+
unless defined?($Melee)
|
|
467
|
+
load File.join($pgmdir, "includes/tables/melee.rb")
|
|
468
|
+
end
|
|
469
|
+
unless defined?($Missile)
|
|
470
|
+
load File.join($pgmdir, "includes/tables/missile.rb")
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
if is_missile
|
|
474
|
+
# Select from $Missile table based on skill type
|
|
475
|
+
case skill_name.downcase
|
|
476
|
+
when /bow/
|
|
477
|
+
# Select bow based on strength: L(2), M(4), H(6), H2(8), H3(10)
|
|
478
|
+
if strength_char >= 10
|
|
479
|
+
"Bow(H3) [1]"
|
|
480
|
+
elsif strength_char >= 8
|
|
481
|
+
"Bow(H2) [1]"
|
|
482
|
+
elsif strength_char >= 6
|
|
483
|
+
"Bow(H) [1]"
|
|
484
|
+
elsif strength_char >= 4
|
|
485
|
+
"Bow(M) [1]"
|
|
486
|
+
else
|
|
487
|
+
"Bow(L) [1]"
|
|
488
|
+
end
|
|
489
|
+
when /crossbow|x-bow/
|
|
490
|
+
if strength_char >= 4
|
|
491
|
+
"X-bow(H) [¼]"
|
|
492
|
+
elsif strength_char >= 3
|
|
493
|
+
"X-bow(M) [⅓]"
|
|
494
|
+
else
|
|
495
|
+
"X-bow(L) [½]"
|
|
496
|
+
end
|
|
497
|
+
when /throwing/
|
|
498
|
+
"Th Knife [2]"
|
|
499
|
+
when /javelin/
|
|
500
|
+
"Javelin [1]"
|
|
501
|
+
when /sling/
|
|
502
|
+
"Sling [1]"
|
|
503
|
+
when /net/
|
|
504
|
+
"Net"
|
|
505
|
+
when /spear/
|
|
506
|
+
"Javelin [1]"
|
|
507
|
+
else
|
|
508
|
+
"Rock [2]"
|
|
509
|
+
end
|
|
510
|
+
else
|
|
511
|
+
# Select from $Melee table based on Wield Weapon total (replaces old STRENGTH)
|
|
512
|
+
# This is BODY + Strength + Wield weapon skill
|
|
513
|
+
# Determine weapon level range based on Wield Weapon total
|
|
514
|
+
wpn_level = case strength_char
|
|
515
|
+
when 0..1 then 2
|
|
516
|
+
when 2..3 then 4
|
|
517
|
+
when 4..6 then 11
|
|
518
|
+
when 7..9 then 18
|
|
519
|
+
when 10..12 then 22
|
|
520
|
+
when 13..15 then 26
|
|
521
|
+
when 16..18 then 28
|
|
522
|
+
else 30
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
# Select random weapon from available range
|
|
526
|
+
weapon_idx = rand(wpn_level) + 1
|
|
527
|
+
weapon_data = $Melee[weapon_idx]
|
|
528
|
+
|
|
529
|
+
if weapon_data
|
|
530
|
+
weapon_data[0].strip # Return weapon name like "Longsword/Buc"
|
|
531
|
+
else
|
|
532
|
+
skill_name # Fallback to skill name
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
|
|
463
537
|
def add_weapon_skills(template)
|
|
464
538
|
# Add melee weapon skills with primary weapon specialization
|
|
539
|
+
# Also store actual weapon selections from $Melee/$Missile tables
|
|
465
540
|
if template["melee_weapons"]
|
|
466
541
|
@tiers["BODY"]["Melee Combat"]["skills"] ||= {}
|
|
542
|
+
@tiers["BODY"]["Melee Combat"]["actual_weapons"] ||= {}
|
|
467
543
|
|
|
468
544
|
# Find primary weapon (highest base value)
|
|
469
545
|
primary_weapon = template["melee_weapons"].max_by { |_, v| v }
|
|
470
546
|
|
|
547
|
+
# Get Wield Weapon total for weapon table selection (replaces old STRENGTH)
|
|
548
|
+
# This is BODY + Strength + Wield weapon skill
|
|
549
|
+
wield_total = get_skill_total("BODY", "Strength", "Wield weapon") rescue 3
|
|
550
|
+
|
|
471
551
|
template["melee_weapons"].each_with_index do |(weapon, skill_level), index|
|
|
472
552
|
base_level = calculate_tier_level(skill_level, @level, 0.6)
|
|
473
553
|
|
|
@@ -478,16 +558,24 @@ class NpcNew
|
|
|
478
558
|
end
|
|
479
559
|
|
|
480
560
|
@tiers["BODY"]["Melee Combat"]["skills"][weapon] = base_level
|
|
561
|
+
|
|
562
|
+
# Select actual weapon from $Melee table based on Wield Weapon total
|
|
563
|
+
actual_weapon = select_actual_weapon_from_table(weapon, wield_total, false)
|
|
564
|
+
@tiers["BODY"]["Melee Combat"]["actual_weapons"][weapon] = actual_weapon
|
|
481
565
|
end
|
|
482
566
|
end
|
|
483
567
|
|
|
484
568
|
# Add missile weapon skills
|
|
485
569
|
if template["missile_weapons"]
|
|
486
570
|
@tiers["BODY"]["Missile Combat"]["skills"] ||= {}
|
|
571
|
+
@tiers["BODY"]["Missile Combat"]["actual_weapons"] ||= {}
|
|
487
572
|
|
|
488
573
|
# Find primary missile weapon
|
|
489
574
|
primary_missile = template["missile_weapons"].max_by { |_, v| v }
|
|
490
575
|
|
|
576
|
+
# Get Wield Weapon total for missile weapon selection (bow strength requirements)
|
|
577
|
+
wield_total = get_skill_total("BODY", "Strength", "Wield weapon") rescue 3
|
|
578
|
+
|
|
491
579
|
template["missile_weapons"].each do |weapon, skill_level|
|
|
492
580
|
base_level = calculate_tier_level(skill_level, @level, 0.6)
|
|
493
581
|
|
|
@@ -498,6 +586,10 @@ class NpcNew
|
|
|
498
586
|
end
|
|
499
587
|
|
|
500
588
|
@tiers["BODY"]["Missile Combat"]["skills"][weapon] = base_level
|
|
589
|
+
|
|
590
|
+
# Select actual weapon based on Wield Weapon total
|
|
591
|
+
actual_weapon = select_actual_weapon_from_table(weapon, wield_total, true)
|
|
592
|
+
@tiers["BODY"]["Missile Combat"]["actual_weapons"][weapon] = actual_weapon
|
|
501
593
|
end
|
|
502
594
|
end
|
|
503
595
|
|
|
@@ -1166,6 +1258,15 @@ class NpcNew
|
|
|
1166
1258
|
unless @tiers["MIND"]["Awareness"]["skills"].key?("Reaction speed")
|
|
1167
1259
|
@tiers["MIND"]["Awareness"]["skills"]["Reaction speed"] = 0
|
|
1168
1260
|
end
|
|
1261
|
+
|
|
1262
|
+
# Ensure Social Knowledge attribute exists for Spoken Language
|
|
1263
|
+
@tiers["MIND"]["Social Knowledge"] ||= {"level" => 0, "skills" => {}}
|
|
1264
|
+
@tiers["MIND"]["Social Knowledge"]["skills"] ||= {}
|
|
1265
|
+
|
|
1266
|
+
# Ensure Spoken Language is at least 2 (native tongue)
|
|
1267
|
+
# All characters start with 2 in Spoken Language per character creation rules
|
|
1268
|
+
current_spoken = @tiers["MIND"]["Social Knowledge"]["skills"]["Spoken Language"] || 0
|
|
1269
|
+
@tiers["MIND"]["Social Knowledge"]["skills"]["Spoken Language"] = [current_spoken, 2].max
|
|
1169
1270
|
end
|
|
1170
1271
|
|
|
1171
1272
|
def apply_predetermined_stats
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: amar-tui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.1.
|
|
4
|
+
version: 2.1.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Geir Isene
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: "."
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-01-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rcurses
|
|
@@ -122,15 +122,11 @@ metadata:
|
|
|
122
122
|
changelog_uri: https://github.com/isene/Amar-Tools/blob/master/README.md
|
|
123
123
|
post_install_message: |2+
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
AMAR Tools
|
|
127
|
-
|
|
125
|
+
===========================================
|
|
126
|
+
AMAR RPG Tools v2.1.5 has been installed!
|
|
127
|
+
===========================================
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
Please install 'amar-rpg' instead:
|
|
131
|
-
gem install amar-rpg
|
|
132
|
-
|
|
133
|
-
To start the TUI application:
|
|
129
|
+
To start the application:
|
|
134
130
|
amar-tui.rb
|
|
135
131
|
|
|
136
132
|
For more information:
|
|
@@ -156,6 +152,6 @@ requirements: []
|
|
|
156
152
|
rubygems_version: 3.4.20
|
|
157
153
|
signing_key:
|
|
158
154
|
specification_version: 4
|
|
159
|
-
summary: AMAR Tools
|
|
155
|
+
summary: AMAR RPG Tools - Terminal UI and utilities for Amar RPG
|
|
160
156
|
test_files: []
|
|
161
157
|
...
|