오픈 소스 모험: 에피소드 52: BATTLETECH 무기 데이터 내보내기
Hearts of Iron IV - Division Designer과 비슷한 작업을 했습니다. 불행하게도 전체 재작성 없이는 최신 HoI4 버전으로 업데이트할 수 없습니다.
수출업자
#!/usr/bin/env ruby
require "json"
require "memoist"
require "pathname"
require "pry"
class String
def camelize
gsub(/_([a-z])/) { $1.upcase }
end
end
class AmmoBox
extend Memoist
attr_reader :data, :path
def initialize(path)
@path = path
@data = JSON.parse(path.read)
end
memoize def id
@data["AmmoID"].sub(/\AAmmunition_/, "")
end
def tonnage
@data["Tonnage"]
end
def capacity
@data["Capacity"]
end
end
class Weapon
extend Memoist
attr_reader :game, :data, :path
def initialize(game, path)
@game = game
@path = path
@data = JSON.parse(path.read)
end
memoize def name
bonuses = [bonus_a, bonus_b].compact
if bonuses.empty?
base_name
else
"#{base_name} (#{bonuses.join(", ")})"
end
end
memoize def base_name
[
data["Description"]["Name"],
data["Description"]["UIName"],
].compact.last.gsub(" +", "+")
end
memoize def bonus_a
data["BonusValueA"] == "" ? nil : data["BonusValueA"].gsub(/[a-z]\K\./, "").gsub(/[\+\-]\K /, "")
end
memoize def bonus_b
data["BonusValueB"] == "" ? nil : data["BonusValueB"].gsub(/[a-z]\K\./, "").gsub(/[\+\-]\K /, "")
end
def category
@data["Category"]
end
def subtype
@data["WeaponSubType"]
end
def tonnage
@data["Tonnage"]
end
def damage
shots * base_damage
end
def base_damage
@data["Damage"]
end
def shots
@data["ShotsWhenFired"]
end
def heat
@data["HeatGenerated"]
end
def ammo_per_shot
@data["ShotsWhenFired"] * data["ProjectilesPerShot"]
end
def heat_tonnage
heat / 3.0
end
# 10 rounds of shootnig at target
def ammo_tonnage_per_shot
@game.ammo_weights.fetch(ammo_category) * ammo_per_shot
end
def total_tonnage
tonnage + heat_tonnage + ammo_tonnage
end
def ammo_category
@data["ammoCategoryID"] || @data["AmmoCategory"]
end
def purchasable?
@data["Description"]["Purchasable"]
end
def weapon_effect
@data["WeaponEffectID"]
end
def ignore?
[
category == "Melee",
name == "AI Laser",
subtype == "TAG",
subtype == "Narc",
subtype =~ /\ACOIL/,
weapon_effect == "WeaponEffect-Artillery_MechMortar",
weapon_effect == "WeaponEffect-Artillery_Thumper",
].any?
end
def min_range
@data["MinRange"]
end
def max_range
@data["MaxRange"]
end
def indirect_fire
@data["IndirectFireCapable"]
end
def as_json
{
name:,
tonnage:,
heat:,
shots:,
base_damage:,
ammo_tonnage_per_shot:,
min_range:,
max_range:,
indirect_fire:,
}.transform_keys(&:to_s).transform_keys(&:camelize)
end
end
class BattleTechGame
extend Memoist
def initialize(game_root, *dlc_roots)
@game_root = Pathname(game_root)
@dlc_roots = dlc_roots.map{|path| Pathname(path)}
end
memoize def data_root
@game_root + "BattleTech_Data/StreamingAssets/data"
end
def roots
[data_root, *@dlc_roots]
end
memoize def weapon_files
roots
.flat_map{|root| root.glob("weapon/*.json")}
.select{|n| n.basename.to_s != "WeaponTemplate.json"}
end
memoize def weapons
weapon_files.map{|path| Weapon.new(self, path)}
end
memoize def ammobox_files
roots
.flat_map{|root| root.glob("ammunitionBox/*.json")}
.select{|n| n.basename.to_s != "AmmoBoxTemplate.json"}
end
memoize def ammoboxes
ammobox_files.map{|path| AmmoBox.new(path)}
end
memoize def ammo_weights
# MG box occurs twice, but with same ratio
ammoboxes.to_h{|a| [a.id, a.tonnage.to_f/a.capacity]}.merge("NotSet" => 0.0)
end
def inspect
"BattechGame"
end
def as_json
weapons
.reject(&:ignore?)
.map(&:as_json)
end
end
game = BattleTechGame.new(*ARGV)
puts JSON.pretty_generate(game.as_json)
코드에는 주로 다음과 같은 몇 가지 흥미로운 사항이 있습니다.
as_json
객체를 JSON 가능 데이터로 변환하지만 최종 데이터String
(to_json
가 하듯이)를 생성하지 않으므로 구성 가능합니다{name:}
는 Ruby 2.x에서 {name: name}
또는 Ruby 1.x에서 {:name => name}
를 의미합니다. .transform_keys(&:camelize)
Hash
를 불쾌한 카멜 케이싱생성된 JSON
다음은 단편입니다.
[
{
"name": "AC/10",
"tonnage": 12,
"heat": 12,
"shots": 1,
"baseDamage": 60,
"ammoTonnagePerShot": 0.125,
"minRange": 0,
"maxRange": 450,
"indirectFire": false
},
...
{
"name": "LRM5++ (+2 Dmg)",
"tonnage": 2,
"heat": 6,
"shots": 5,
"baseDamage": 6,
"ammoTonnagePerShot": 0.041666666666666664,
"minRange": 180,
"maxRange": 630,
"indirectFire": true
},
...
{
"name": "M Pulse++ (-4 Heat, +1 Acc)",
"tonnage": 2,
"heat": 16,
"shots": 1,
"baseDamage": 50,
"ammoTonnagePerShot": 0.0,
"minRange": 0,
"maxRange": 270,
"indirectFire": false
},
...
]
여기에 필요한 필드를 추측하는 중입니다. 일부 필드를 추가하거나 변경해야 할 수도 있습니다.
소스 데이터가 JSON이기 때문에 모든 JSON을 수집하여 하나의 큰 JSON 배열에 넣고 사용할 수 있지만 이 패턴이 마음에 들지 않습니다.
지금까지의 이야기
All the code is on GitHub .
다음에 온다
다음 몇 개의 에피소드에서는 BATTLETECH 무기 데이터의 작은 Svelte 대화형 시각화를 만들 것입니다.
Reference
이 문제에 관하여(오픈 소스 모험: 에피소드 52: BATTLETECH 무기 데이터 내보내기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/taw/open-source-adventures-episode-52-battletech-weapons-data-exporter-5cg4텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)