diff --git a/src/GUI/QmlAircraftInfo.cxx b/src/GUI/QmlAircraftInfo.cxx
index c4a32298e..3bfec4828 100644
--- a/src/GUI/QmlAircraftInfo.cxx
+++ b/src/GUI/QmlAircraftInfo.cxx
@@ -30,7 +30,7 @@ public:
         globals->packageRoot()->addDelegate(this);
     }
 
-    ~Delegate()
+    ~Delegate() override
     {
         globals->packageRoot()->removeDelegate(this);
     }
@@ -135,6 +135,19 @@ static AircraftStateVec readAircraftStates(const SGPath& setXMLPath)
     return result;
 }
 
+static SGPropertyNode_ptr readAircraftAuthors(const SGPath& setXMLPath)
+{
+    SGPropertyNode_ptr root(new SGPropertyNode);
+    try {
+        readProperties(setXMLPath, root);
+    } catch (sg_exception&) {
+        return {}; // malformed include or XML, just bail
+    }
+
+    const auto authors = root->getNode("sim/authors");
+    return authors;
+}
+
 QString humanNameFromStateTag(const std::string& tag)
 {
     if (tag == "approach") return QObject::tr("On approach");
@@ -338,11 +351,37 @@ QString QmlAircraftInfo::description() const
 
 QString QmlAircraftInfo::authors() const
 {
+    SGPropertyNode_ptr structuredAuthors;
     if (_item) {
-        return resolveItem()->authors;
+        std::string path = pathOnDisk().toUtf8().toStdString();
+        structuredAuthors = readAircraftAuthors(SGPath::fromUtf8(path));
+        if (!structuredAuthors)
+            return resolveItem()->authors;
     } else if (_package) {
-        std::string authors = _package->getLocalisedProp("author", _variant);
-        return QString::fromStdString(authors);
+        if (_package->properties()->hasChild("authors")) {
+            structuredAuthors = _package->properties()->getChild("authors");
+        } else {
+            std::string authors = _package->getLocalisedProp("author", _variant);
+            return QString::fromStdString(authors);
+        }
+    }
+
+    if (structuredAuthors) {
+        // build formatted HTML based on authors data
+        QString html = "<ul>\n";
+        for (auto a : structuredAuthors->getChildren("author")) {
+            html += "<li>";
+            html += a->getStringValue("name");
+            if (a->hasChild("nick")) {
+                html += QStringLiteral(" '") + QString::fromStdString(a->getStringValue("nick")) + QStringLiteral("'");
+            }
+            if (a->hasChild("description")) {
+                html += QStringLiteral(" - <i>") +  QString::fromStdString(a->getStringValue("description")) + QStringLiteral("</i>");
+            }
+            html  += "</li>\n";
+        }
+        html += "<ul>\n";
+        return html;
     }
 
     return {};
diff --git a/src/Main/util.cxx b/src/Main/util.cxx
index b1ba57034..f20bae1f8 100644
--- a/src/Main/util.cxx
+++ b/src/Main/util.cxx
@@ -179,5 +179,31 @@ SGPath fgValidatePath (const SGPath& path, bool write)
     return SGPath();
 }
 
-// end of util.cxx
+std::string generateAuthorsText(SGPropertyNode* authors)
+{
+    std::string result;
+    for (auto a : authors->getChildren("author")) {
+        const std::string name = a->getStringValue("name");
+        if (name.empty())
+            continue;
 
+        if (!result.empty())
+            result += ", ";
+        result += a->getStringValue("name");
+    }
+    return result;
+}
+
+std::string flightgear::getAircraftAuthorsText()
+{
+    const auto authorsNode = fgGetNode("sim/authors");
+    if (authorsNode) {
+        // we have structured authors data
+        return generateAuthorsText(authorsNode);
+    }
+
+    // if we hit this point, there is no strucutred authors data
+    return fgGetString("/sim/author");
+}
+
+// end of util.cxx
diff --git a/src/Main/util.hxx b/src/Main/util.hxx
index e75c28462..c6816ef7d 100644
--- a/src/Main/util.hxx
+++ b/src/Main/util.hxx
@@ -54,4 +54,15 @@ SGPath fgValidatePath(const SGPath& path, bool write);
  */
 void fgInitAllowedPaths();
 
+namespace flightgear
+{
+    /**
+     * @brief getAircraftAuthorsText - get the aircraft authors as a single
+     * string value. This will combine the new (structured) authors data if
+     * present, otherwise just return the old plain string
+     * @return
+     */
+    std::string getAircraftAuthorsText();
+}
+
 #endif // __UTIL_HXX
diff --git a/src/Viewer/splash.cxx b/src/Viewer/splash.cxx
index 79152af1d..88cfa9f29 100644
--- a/src/Viewer/splash.cxx
+++ b/src/Viewer/splash.cxx
@@ -50,12 +50,13 @@
 #include <Main/fg_props.hxx>
 #include <Main/fg_os.hxx>
 #include <Main/locale.hxx>
+#include <Main/util.hxx>
 #include "splash.hxx"
 #include "renderer.hxx"
 
 #include <sstream>
 
-const char* LICENSE_URL_TEXT = "Licensed under the GNU GPL. See http://www.flightgear.org for more information";
+static const char* LICENSE_URL_TEXT = "Licensed under the GNU GPL. See http://www.flightgear.org for more information";
 
 class SplashScreenUpdateCallback : public osg::NodeCallback {
 public:
@@ -134,7 +135,7 @@ void SplashScreen::createNodes()
     geode->addDrawable(geometry);
 
     if (_legacySplashScreenMode) {
-        addText(geode, osg::Vec2(0.025, 0.025), 0.03,
+        addText(geode, osg::Vec2(0.025f, 0.025f), 0.03,
                 std::string("FlightGear ") + fgGetString("/sim/version/flightgear") +
                 std::string(" ") + std::string(LICENSE_URL_TEXT),
                 osgText::Text::LEFT_TOP,
@@ -145,15 +146,15 @@ void SplashScreen::createNodes()
 
         // order here is important so we can re-write first item with the
         // startup tip.
-        addText(geode, osg::Vec2(0.025, 0.15), 0.03, LICENSE_URL_TEXT,
+        addText(geode, osg::Vec2(0.025f, 0.15f), 0.03, LICENSE_URL_TEXT,
                 osgText::Text::LEFT_TOP,
                 nullptr,
                 0.6);
 
-        addText(geode, osg::Vec2(0.025, 0.025), 0.10, std::string("FlightGear ") + fgGetString("/sim/version/flightgear"), osgText::Text::LEFT_TOP);
+        addText(geode, osg::Vec2(0.025f, 0.025f), 0.10, std::string("FlightGear ") + fgGetString("/sim/version/flightgear"), osgText::Text::LEFT_TOP);
 
         if (!_aircraftLogoVertexArray) {
-            addText(geode, osg::Vec2(0.025, 0.935), 0.10,
+            addText(geode, osg::Vec2(0.025f, 0.935f), 0.10,
                     fgGetString("/sim/description"),
                     osgText::Text::LEFT_BOTTOM,
                     nullptr,
@@ -161,8 +162,9 @@ void SplashScreen::createNodes()
             _items.back().maxLineCount = 1;
         }
 
-        addText(geode, osg::Vec2(0.025, 0.940), 0.03,
-                fgGetString("/sim/author"),
+        const auto authors = flightgear::getAircraftAuthorsText();
+        addText(geode, osg::Vec2(0.025f, 0.940f), 0.03,
+                authors,
                 osgText::Text::LEFT_TOP,
                 nullptr,
                 0.6);
@@ -170,13 +172,13 @@ void SplashScreen::createNodes()
         _items.back().maxHeightFraction = 0.055;
     }
 
-    addText(geode, osg::Vec2(0.975, 0.935), 0.03,
+    addText(geode, osg::Vec2(0.975f, 0.935f), 0.03,
             "loading status",
             osgText::Text::RIGHT_BOTTOM,
             fgGetNode("/sim/startup/splash-progress-text", true),
             0.4);
 
-    addText(geode, osg::Vec2(0.975, 0.975), 0.03,
+    addText(geode, osg::Vec2(0.975f, 0.975f), 0.03,
             "spinner",
             osgText::Text::RIGHT_BOTTOM,
             fgGetNode("/sim/startup/splash-progress-spinner", true));
@@ -196,13 +198,13 @@ void SplashScreen::createNodes()
 
     _splashSpinnerVertexArray = new osg::Vec3Array;
     for (int i=0; i < 8; ++i) {
-        _splashSpinnerVertexArray->push_back(osg::Vec3(0.0, 0.0, -0.1));
+        _splashSpinnerVertexArray->push_back(osg::Vec3(0.0f, 0.0f, -0.1f));
     }
     geometry->setVertexArray(_splashSpinnerVertexArray);
 
     // QColor buttonColor(27, 122, 211);
     colorArray = new osg::Vec4Array;
-    colorArray->push_back(osg::Vec4(27 / 255.0, 122 / 255.0, 211 / 255.0, 0.75));
+    colorArray->push_back(osg::Vec4(27 / 255.0f, 122 / 255.0f, 211 / 255.0f, 0.75f));
     geometry->setColorArray(colorArray);
     geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
     geometry->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 8));