Fixed Timing / Data Update Logic / Low Health Overlay Issues / Comparison Node and Math Node issues.
This commit is contained in:
@ -1,47 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Standardized Flyff Character Status Node:
|
||||
- Polls an API for character stats and updates values dynamically.
|
||||
- Uses a global update timer for processing.
|
||||
- Immediately transmits updated values to connected nodes.
|
||||
"""
|
||||
|
||||
from OdenGraphQt import BaseNode
|
||||
from Qt import QtCore, QtGui
|
||||
from Qt import QtCore
|
||||
import requests
|
||||
import traceback
|
||||
|
||||
def get_draw_stat_port(color, border_color=None, alpha=127):
|
||||
"""
|
||||
Returns a custom port painter function that draws a circular port with a
|
||||
semi-transparent fill and then draws text (port label and current value)
|
||||
next to it.
|
||||
"""
|
||||
if border_color is None:
|
||||
border_color = color
|
||||
|
||||
def painter_func(painter, rect, info):
|
||||
painter.save()
|
||||
pen = QtGui.QPen(QtGui.QColor(*border_color))
|
||||
pen.setWidth(1.8)
|
||||
painter.setPen(pen)
|
||||
semi_transparent_color = QtGui.QColor(color[0], color[1], color[2], alpha)
|
||||
painter.setBrush(semi_transparent_color)
|
||||
painter.drawEllipse(rect)
|
||||
port = info.get('port')
|
||||
if port is not None:
|
||||
node = port.node()
|
||||
stat = port.name()
|
||||
value = node.values.get(stat, "N/A") if hasattr(node, 'values') else "N/A"
|
||||
text_rect = rect.adjusted(rect.width() + 4, 0, rect.width() + 70, 0)
|
||||
painter.setPen(QtGui.QColor(0, 0, 0))
|
||||
painter.drawText(text_rect, QtCore.Qt.AlignVCenter | QtCore.Qt.AlignLeft,
|
||||
f"{stat}: {value}")
|
||||
painter.restore()
|
||||
return painter_func
|
||||
|
||||
class CharacterStatusNode(BaseNode):
|
||||
class FlyffCharacterStatusNode(BaseNode):
|
||||
__identifier__ = 'bunny-lab.io.flyff_character_status_node'
|
||||
NODE_NAME = 'Flyff - Character Status'
|
||||
|
||||
def __init__(self):
|
||||
super(CharacterStatusNode, self).__init__()
|
||||
|
||||
# Define exact expected keys to avoid transformation mismatches
|
||||
super(FlyffCharacterStatusNode, self).__init__()
|
||||
self.values = {
|
||||
"HP: Current": "N/A", "HP: Total": "N/A",
|
||||
"MP: Current": "N/A", "MP: Total": "N/A",
|
||||
@ -49,97 +25,60 @@ class CharacterStatusNode(BaseNode):
|
||||
"EXP": "N/A"
|
||||
}
|
||||
|
||||
# Add output ports
|
||||
self.add_output("HP: Current", painter_func=get_draw_stat_port((217, 36, 78)))
|
||||
self.add_output("HP: Total", painter_func=get_draw_stat_port((217, 36, 78)))
|
||||
self.add_output("MP: Current", painter_func=get_draw_stat_port((35, 124, 213)))
|
||||
self.add_output("MP: Total", painter_func=get_draw_stat_port((35, 124, 213)))
|
||||
self.add_output("FP: Current", painter_func=get_draw_stat_port((36, 197, 28)))
|
||||
self.add_output("FP: Total", painter_func=get_draw_stat_port((36, 197, 28)))
|
||||
self.add_output("EXP", painter_func=get_draw_stat_port((52, 195, 250)))
|
||||
for stat in self.values.keys():
|
||||
self.add_output(stat)
|
||||
|
||||
self.set_name("Flyff - Character Status (API Disconnected)")
|
||||
# Removed self-contained polling timer; global timer now drives updates.
|
||||
|
||||
# Start polling timer
|
||||
self.timer = QtCore.QTimer()
|
||||
self.timer.timeout.connect(self.poll_api)
|
||||
self.timer.start(500)
|
||||
|
||||
def poll_api(self):
|
||||
"""
|
||||
Polls the API endpoint to retrieve the latest character stats and updates
|
||||
the node's internal values.
|
||||
"""
|
||||
def process_input(self):
|
||||
try:
|
||||
response = requests.get("http://127.0.0.1:5000/data", timeout=1)
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
|
||||
if isinstance(data, dict):
|
||||
try:
|
||||
for key, value in data.items():
|
||||
# Ensure the keys match the expected ones exactly
|
||||
formatted_key = {
|
||||
"hp_current": "HP: Current",
|
||||
"hp_total": "HP: Total",
|
||||
"mp_current": "MP: Current",
|
||||
"mp_total": "MP: Total",
|
||||
"fp_current": "FP: Current",
|
||||
"fp_total": "FP: Total",
|
||||
"exp": "EXP"
|
||||
}.get(key, key) # Use mapping or fallback to raw key
|
||||
|
||||
if formatted_key in self.values:
|
||||
mapping = {
|
||||
"hp_current": "HP: Current",
|
||||
"hp_total": "HP: Total",
|
||||
"mp_current": "MP: Current",
|
||||
"mp_total": "MP: Total",
|
||||
"fp_current": "FP: Current",
|
||||
"fp_total": "FP: Total",
|
||||
"exp": "EXP"
|
||||
}
|
||||
updated = False
|
||||
for key, value in data.items():
|
||||
if key in mapping:
|
||||
formatted_key = mapping[key]
|
||||
if str(value) != self.values.get(formatted_key, None):
|
||||
self.values[formatted_key] = str(value)
|
||||
else:
|
||||
print(f"[WARNING] Unexpected API key: {key} (not mapped)")
|
||||
|
||||
updated = True
|
||||
if updated:
|
||||
self.set_name("Flyff - Character Status (API Connected)")
|
||||
self.update()
|
||||
self.transmit_data()
|
||||
|
||||
except Exception as e:
|
||||
print("[ERROR] Error processing API response data:", e)
|
||||
print("[ERROR] Stack Trace:\n", traceback.format_exc())
|
||||
else:
|
||||
print("[ERROR] Unexpected API response format (not a dict):", data)
|
||||
self.set_name("Flyff - Character Status (API Disconnected)")
|
||||
|
||||
else:
|
||||
print(f"[ERROR] API request failed with status code {response.status_code}")
|
||||
self.set_name("Flyff - Character Status (API Disconnected)")
|
||||
|
||||
except Exception as e:
|
||||
self.set_name("Flyff - Character Status (API Disconnected)")
|
||||
print("[ERROR] Error polling API in CharacterStatusNode:", str(e))
|
||||
print("[ERROR] Stack Trace:\n", traceback.format_exc())
|
||||
|
||||
def transmit_data(self):
|
||||
"""
|
||||
Sends the updated character stats to connected nodes.
|
||||
"""
|
||||
for stat, value in self.values.items():
|
||||
try:
|
||||
port = self.get_output(stat)
|
||||
|
||||
if port is None:
|
||||
print(f"[ERROR] Port '{stat}' not found in node outputs. Skipping...")
|
||||
continue
|
||||
|
||||
if port.connected_ports():
|
||||
for connected_port in port.connected_ports():
|
||||
connected_node = connected_port.node()
|
||||
if hasattr(connected_node, 'receive_data'):
|
||||
try:
|
||||
connected_node.receive_data(value, stat)
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error transmitting data to {connected_node}: {e}")
|
||||
print("[ERROR] Stack Trace:\n", traceback.format_exc())
|
||||
else:
|
||||
print(f"[WARNING] Connected node {connected_node} does not have receive_data method.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error while handling port {stat}: {e}")
|
||||
print("[ERROR] Stack Trace:\n", traceback.format_exc())
|
||||
port = self.get_output(stat)
|
||||
if port and port.connected_ports():
|
||||
for connected_port in port.connected_ports():
|
||||
connected_node = connected_port.node()
|
||||
if hasattr(connected_node, 'receive_data'):
|
||||
try:
|
||||
connected_node.receive_data(value, stat)
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Error transmitting data to {connected_node}: {e}")
|
||||
print("[ERROR] Stack Trace:\n", traceback.format_exc())
|
||||
|
||||
def receive_data(self, data, source_port_name=None):
|
||||
# This node only transmits data; it does not receive external data.
|
||||
pass
|
||||
|
Reference in New Issue
Block a user