-
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A python script to generate ship view
- Loading branch information
Showing
2 changed files
with
325 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"general": {}, | ||
|
||
"graphics": { | ||
"resolution_x": 2560, | ||
"resolution_y": 1600, | ||
"screen": 0 | ||
}, | ||
|
||
"components": { | ||
"drive": { | ||
"non_combat_mode_multiplier": 100 | ||
} | ||
}, | ||
|
||
"constants": { | ||
"megajoules_multiplier": 100 | ||
}, | ||
|
||
"advanced": {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,304 @@ | ||
import locale | ||
import math | ||
import json | ||
|
||
|
||
newline = "#n#" | ||
red = "#c1:.3:.3#" | ||
green = "#c0:1:.5#" | ||
light_grey = "#c.75:.9:1#" | ||
grey = "#c.6:.7:.8#" | ||
light_yellow = "#c.675:.925:.825#" | ||
end_color = "#-c" | ||
|
||
non_combat_speed_multiplier = 1 | ||
megajoules_multiplier = 1 | ||
|
||
llama_begin = {} | ||
|
||
with open('config.json', 'r') as file: | ||
data = json.load(file) | ||
non_combat_speed_multiplier = data['components']['drive']['non_combat_mode_multiplier'] | ||
megajoules_multiplier = data['constants']['megajoules_multiplier'] | ||
|
||
with open('units/units.json', 'r') as file: | ||
data = json.load(file) | ||
|
||
for ship in data: | ||
if ship['Key'] == 'Llama.begin': | ||
llama_begin = ship | ||
break | ||
|
||
|
||
# Format large number | ||
def lnum(ship_stats, key, divider = 1.0): | ||
num = float(ship_stats[key])/divider | ||
num = '{:n}'.format(num) | ||
return num | ||
|
||
def get(ship_stats, key): | ||
return ship_stats[key] | ||
|
||
def get_bool(ship_stats, key): | ||
s = ship_stats[key] | ||
if(s == 'TRUE' or s=='1'): | ||
return True | ||
return False | ||
|
||
def get_int(ship_stats, key): | ||
return int(ship_stats[key]) | ||
|
||
def get_dbl(ship_stats, key, divider = 1.0): | ||
fl = float(ship_stats[key])/divider | ||
#s = f"{key} {fl}" | ||
#print(s) | ||
return fl | ||
|
||
def get_fmt_dbl(ship_stats, key, divider = 1.0): | ||
return "{:.2f}".format(float(ship_stats[key])) | ||
|
||
def fmt_dbl(dbl): | ||
return "{:.2f}".format(dbl) | ||
|
||
def near_equal(a,b): | ||
return a-b < 0.01 and b-a < 0.01 | ||
|
||
def get_notes(ship_stats): | ||
text = f"{green}[NOTES]{newline}{newline}" | ||
text += f"{grey}#-c{ship_stats['Textual_Description']}{newline}{newline}" | ||
return text | ||
|
||
def get_variant(key): | ||
# TODO: refactor with dict and for/each | ||
if key.endswith('blank'): | ||
return '' | ||
if key.endswith('begin'): | ||
return 'Variant: #-cStock (Refurbished)' | ||
if key.endswith('stock'): | ||
return 'Variant: #-cStock' | ||
if key.endswith('civvie'): | ||
return 'Variant: #-cCivilian' | ||
if key.endswith('milspec'): | ||
return 'Variant: #-cMilspec' | ||
return '' | ||
|
||
def get_itts(itts): | ||
if(itts=='1'): | ||
return 'yes' | ||
return 'no' | ||
|
||
def get_iff(iff): | ||
if iff=='0': return 'none' | ||
if iff=='1': return 'friend/foe' | ||
if iff=='2': return 'object recognition' | ||
return iff | ||
|
||
# General | ||
def get_general(ship_stats): | ||
text = f"{green}[GENERAL INFORMATION]{newline}" | ||
text += f"#-c{newline}{light_grey}Model: #-c{ship_stats['Name']}{light_grey} {get_variant(ship_stats['Key'])}{newline}" | ||
text += f"{light_grey}Mass: #-c{lnum(ship_stats,'Mass')} metric tons{newline}" | ||
text += f"{light_grey}Hold volume: #-c{lnum(ship_stats,'Hold_Volume')} cubic meters{newline}" | ||
text += f"{light_grey}Upgrade volume: #-c{lnum(ship_stats,'Upgrade_Storage_Volume')} cubic meters{newline}" | ||
text += f"{light_grey}Fuel capacity: #-c{lnum(ship_stats,'Fuel_Capacity')} metric tons of Lithium-6{newline}{newline}" | ||
return text | ||
|
||
# Flight Characteristics | ||
def get_flight(ship_stats): | ||
mass = get_dbl(ship_stats,'Mass') | ||
moment = get_dbl(ship_stats,'Moment_Of_Inertia') | ||
divider = 9.8 * mass | ||
divider_maneuver = moment * 180 / math.pi | ||
yaw = get_dbl(ship_stats,'Maneuver_Yaw', divider_maneuver) | ||
pitch = get_dbl(ship_stats,'Maneuver_Pitch', divider_maneuver) | ||
roll = get_dbl(ship_stats,'Maneuver_Roll', divider_maneuver) | ||
|
||
forward = get_dbl(ship_stats,'Forward_Accel', divider) | ||
retro = get_dbl(ship_stats,'Retro_Accel', divider) | ||
|
||
lateral = (get_dbl(ship_stats,'Left_Accel', divider) + get_dbl(ship_stats,'Right_Accel', divider))/2 | ||
vertical = (get_dbl(ship_stats,'Top_Accel', divider) + get_dbl(ship_stats,'Bottom_Accel', divider))/2 | ||
|
||
afterburner = get_dbl(ship_stats,'Afterburner_Accel', divider) | ||
|
||
text = f"{green}[FLIGHT CHARACTERISTICS]{newline}" | ||
|
||
if(yaw == pitch and yaw == roll): | ||
text += f"#-c{newline}{light_grey}Turning response: #-c{fmt_dbl(yaw)} radians/second²{newline}" | ||
text += f"{grey} (yaw, pitch, roll)#-c{newline}" | ||
else: | ||
text += f"#-c{newline}{light_grey} yaw #-c{fmt_dbl(yaw)} radians/second²{newline}" | ||
text += f"#-c{newline}{light_grey} pitch #-c{fmt_dbl(pitch)} radians/second²{newline}" | ||
text += f"#-c{newline}{light_grey} roll #-c{fmt_dbl(roll)} radians/second²{newline}" | ||
|
||
text += f"{light_grey}Fore acceleration: #-c{fmt_dbl(forward)} gravities{newline}" | ||
text += f"{light_grey}Aft acceleration: #-c{fmt_dbl(retro)} gravities{newline}" | ||
|
||
if(lateral == vertical): | ||
text += f"{light_grey}Orthogonal acceleration: #-c{fmt_dbl(lateral)} gravities{newline}" | ||
text += f"{grey}(vertical and lateral axes)#-c{newline}" | ||
else: | ||
text += f"{light_grey} Lateral acceleration #-c{fmt_dbl(lateral)} gravities{newline}" | ||
text += f"{grey} Vertical acceleration #-c{fmt_dbl(vertical)} gravities{newline}" | ||
text += f"{light_grey}Forward acceleration with overthrust: #-c{fmt_dbl(afterburner)} gravities{newline}{newline}" | ||
return text | ||
|
||
def get_governor(ship_stats): | ||
divider = 180 / math.pi | ||
speed = get_int(ship_stats, 'Default_Speed_Governor') | ||
afterburner = get_int(ship_stats, 'Afterburner_Speed_Governor') | ||
|
||
yaw = get_dbl(ship_stats, 'Yaw_Governor',divider) | ||
#yaw_right = get_dbl(ship_stats, 'Yaw_Governor_Right') | ||
#yaw_left = get_dbl(ship_stats, 'Yaw_Governor_Left') | ||
|
||
pitch = get_dbl(ship_stats, 'Pitch_Governor',divider) | ||
#pitch_down = get_dbl(ship_stats, 'Pitch_Governor_Up') | ||
#pitch_up = get_dbl(ship_stats, 'Pitch_Governor_Down') | ||
|
||
roll = get_dbl(ship_stats, 'Roll_Governor',divider) | ||
#roll_right = get_dbl(ship_stats, 'Roll_Governor_Right') | ||
#roll_left = get_dbl(ship_stats, 'Roll_Governor_Left') | ||
|
||
text = f"{green}[GOVERNOR SETTINGS]{newline}#-c{newline}" | ||
text += f"{light_grey}Max combat speed: #-c{speed} m/s{newline}" | ||
text += f"{light_grey}Max overdrive combat speed: #-c{afterburner} m/s{newline}" | ||
text += f"{light_grey}Max non-combat speed: #-c{speed * non_combat_speed_multiplier} m/s{newline}" | ||
text += f"{light_grey}Max turn rates:#-c{newline}" | ||
text += f"{light_yellow} - yaw: #-c{fmt_dbl(yaw)} radians/second{newline}" | ||
text += f"{light_yellow} - pitch: #-c{fmt_dbl(pitch)} radians/second{newline}" | ||
text += f"{light_yellow} - roll: #-c{fmt_dbl(roll)} radians/second{newline}{newline}" | ||
return text | ||
|
||
def get_radar(ship_stats): | ||
radar_range = lnum(ship_stats,'Radar_Range',1000) | ||
max_cone = get_dbl(ship_stats,'Max_Cone', 180 / math.pi) | ||
tracking_cone = get_dbl(ship_stats,'Tracking_Cone', 180 / math.pi) | ||
lock_cone = get_dbl(ship_stats,'Lock_Cone', 180 / math.pi) | ||
itts = ship_stats['ITTS'] | ||
iff = ship_stats['Radar_Color'] | ||
|
||
text = f"{green}[TARGETTING SUBSYSTEM]{newline}#-c{newline}" | ||
text += f"{light_grey}Tracking range: #-c{radar_range} km{newline}" | ||
|
||
if(near_equal(max_cone,math.pi)): | ||
text += f"{light_grey}Tracking cone: #-cOmni-directional{newline}" | ||
else: | ||
text += f"{light_grey}Tracking cone: #-c{fmt_dbl(max_cone * 2)} radians{newline}" | ||
text += f"{light_grey} (planar angle: 2 pi means full space)#-c{newline}" | ||
text += f"{light_grey}Assisted targeting cone: #-c{fmt_dbl(tracking_cone * 2)} radians{newline}" | ||
text += f"{light_grey}Missile locking cone: #-c{fmt_dbl(lock_cone * 2)} radians{newline}" | ||
text += f"{light_grey}ITTS (Intelligent Target Tracking System) support: #-c{get_itts(itts)}{newline}" | ||
text += f"{light_grey}AFHH (Advanced Flag & Hostility Heuristics) support: #-c{get_iff(iff)} {newline}{newline}" | ||
return text | ||
|
||
def get_energy_spec_and_jump(ship_stats): | ||
reactor = get_dbl(ship_stats,'Reactor_Recharge',1/megajoules_multiplier) | ||
energy = get_dbl(ship_stats,'Primary_Capacitor',1/megajoules_multiplier) | ||
ftl_energy = get_dbl(ship_stats,'Warp_Capacitor',1/megajoules_multiplier) | ||
spec_cost = get_dbl(ship_stats,'Warp_Usage_Cost',1/megajoules_multiplier) | ||
|
||
jump_drive_installed = get_bool(ship_stats,'Jump_Drive_Present') | ||
jump_delay = get_dbl(ship_stats,'Jump_Drive_Delay') | ||
jump_cost = get_dbl(ship_stats,'Outsystem_Jump_Cost',1/megajoules_multiplier) | ||
|
||
|
||
text = f"{green}[ENERGY SUBSYSTEM]{newline}#-c{newline}" | ||
text += f"{light_grey}Recharge: #-c{reactor} MJ/s{newline}" | ||
text += f"{light_grey}Main capacitor: #-c{energy} MJ{newline}" | ||
text += f"{light_grey}SPEC capacitor: #-c{ftl_energy}0 MJ{newline}{newline}" | ||
|
||
text += f"{green}[SPEC SUBSYSTEM]{newline}#-c{newline}" | ||
text += f"{light_grey}Active SPEC Energy Requirements: #-c{spec_cost} MJ/s{newline}{newline}" | ||
|
||
text += f"{green}[JUMP SUBSYSTEM]{newline}#-c{newline}" | ||
if(jump_drive_installed): | ||
text += f"{light_grey}Energy cost for jumpnode travel: #-c{jump_cost} MJ{newline}" | ||
text += f"{light_grey}Delay: #-c{jump_delay} seconds{newline}{newline}" | ||
else: | ||
text += f"{red}No outsystem jump drive present{end_color}{newline}{newline}" | ||
|
||
return text | ||
|
||
def get_durability(ship_stats): | ||
armor = [ | ||
('Fore-starboard-high','Armor_Front_Top_Right'), | ||
('Aft-starboard-high','Armor_Back_Top_Right'), | ||
('Fore-port-high','Armor_Front_Top_Left'), | ||
('Aft-port-high','Armor_Back_Top_Left'), | ||
('Fore-starboard-low','Armor_Front_Bottom_Right'), | ||
('Aft-starboard-low','Armor_Back_Bottom_Right'), | ||
('Fore-port-low','Armor_Front_Bottom_Left'), | ||
('Aft-port-low','Armor_Back_Bottom_Left'), | ||
] | ||
|
||
shield4 = [ | ||
('Port','Shield_Front_Bottom_Left'),('Starboard','Shield_Front_Bottom_Right'),('Fore','Shield_Front_Top_Right'),('Aft','Shield_Back_Top_Left'), | ||
] | ||
|
||
shield2 = [ | ||
('Fore','Shield_Front_Top_Right'),('Aft','Shield_Back_Top_Left'), | ||
] | ||
|
||
# This is a kludge. Should go away when we refactor units.json and unit_csv.cpp | ||
shield_stat = {} | ||
num_emitters = 0 | ||
for pair in shield4: | ||
if ship_stats[pair[1]] == '': | ||
continue | ||
value = get_dbl(ship_stats,pair[1]) | ||
if value > 0: | ||
num_emitters += 1 | ||
|
||
|
||
hull = lnum(ship_stats,'Hull') | ||
shield_recharge = lnum(ship_stats,'Shield_Recharge') | ||
|
||
text = f"{green}[DURABILITY STATISTICS]{newline}#-c{newline}" | ||
text += f"{light_grey}Sustainable Hull Damage: #-c{hull} MJ{newline}{newline}" | ||
|
||
text += f"{light_grey}Armor#-c{newline}" | ||
for pair in armor: | ||
armor_stat = lnum(ship_stats, pair[1]) | ||
text += f"{light_yellow} - {pair[0]}: #-c{armor_stat} MJ{newline}" | ||
|
||
text += f"{newline}{light_grey}Shields#-c{newline}" | ||
text += f"{light_grey}Shield recharge: #-c{shield_recharge} MJ/s{newline}" | ||
if num_emitters == 0: | ||
text += f"{red}No shielding.{end_color}{newline}{newline}" | ||
elif num_emitters == 2: | ||
text += f"{light_grey}Number of shield emitter: 2{end_color}{newline}" | ||
for pair in shield2: | ||
shield_stat = lnum(ship_stats, pair[1]) | ||
text += f"{light_yellow} - {pair[0]}: #-c{shield_stat} MJ{newline}" | ||
else: | ||
text += f"{light_grey}Number of shield emitter: 4{end_color}{newline}" | ||
for pair in shield4: | ||
shield_stat = lnum(ship_stats, pair[1]) | ||
text += f"{light_yellow} - {pair[0]}: #-c{shield_stat} MJ{newline}" | ||
|
||
return text | ||
|
||
|
||
|
||
def get_ship_description(ship_stats): | ||
locale.setlocale(locale.LC_ALL, '') | ||
|
||
text = get_notes(ship_stats) | ||
text += get_general(ship_stats) | ||
text += get_flight(ship_stats) | ||
text += get_governor(ship_stats) | ||
text += get_radar(ship_stats) | ||
text += get_energy_spec_and_jump(ship_stats) | ||
text += get_durability(ship_stats) | ||
|
||
return text | ||
|
||
# Test function | ||
# Useful to check python script for correctness before running VS | ||
|
||
t = get_ship_description(llama_begin) | ||
t = t.replace('#n#','\n') | ||
print(t) | ||
|
||
|