Implement a basic encyclopedia page
Some checks failed
0ad-freebsd/pipeline/pr-main There was a failure building this commit
checkrefs / checkrefs (pull_request) Successful in 51s
pre-commit / build (pull_request) Successful in 1m6s
0ad-linux/pipeline/pr-main There was a failure building this commit
0ad-windows/pipeline/pr-main There was a failure building this commit
0ad-macos/pipeline/pr-main There was a failure building this commit

This commit is contained in:
Vantha 2024-08-29 12:49:56 +02:00
parent f2bef8388a
commit dfe5e5f369
86 changed files with 18142 additions and 234 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
binaries/data/mods/public/fonts/sans-18.png (Stored with Git LFS) Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
binaries/data/mods/public/fonts/sans-20.png (Stored with Git LFS) Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
binaries/data/mods/public/fonts/sans-bold-26.png (Stored with Git LFS) Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
binaries/data/mods/public/fonts/sans-italic-18.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -26,7 +26,9 @@ function loadCivFiles(selectableOnly)
const template = Engine.GetTemplate("special/players/" + data.Code);
data.Name = template.Identity.GenericName;
data.Emblem = "session/portraits/" + template.Identity.Icon;
data.History = template.Identity.History;
// The history text is pulled from the encyclopedia
data.History =
Engine.ReadJSONFile("gui/encyclopedia/articles/civilizations/" + data.Code + "/introduction.json").text;
civData[data.Code] = data;
}
@ -165,7 +167,8 @@ function GetTemplateDataHelper(template, player, auraTemplates, resources, modif
// @param {string} value_path - Route to the value within the template.
// @param {string} mod_key - Modification key, if not the same as the value_path.
// @param {number} default_value - A value to use if one is not specified in the template.
const getEntityValue = function(value_path, mod_key, default_value = 0) {
const getEntityValue = function(value_path, mod_key, default_value = 0)
{
return GetModifiedTemplateDataValue(template, value_path, mod_key, player, modifiers, default_value);
};
@ -220,7 +223,8 @@ function GetTemplateDataHelper(template, player, auraTemplates, resources, modif
ret.attack = {};
for (let type in template.Attack)
{
let getAttackStat = function(stat) {
let getAttackStat = function(stat)
{
return getEntityValue("Attack/" + type + "/" + stat);
};

View File

@ -0,0 +1,47 @@
class EncyclopediaPage
{
constructor()
{
// This.last… store various data about the last state of the page.
// The data is read directly by all classes and doesn't need to be passed between functions.
this.panel = "";
this.lastCategory = "";
this.lastCiv = "";
this.lastSubcategory = "";
this.civData = loadCivData(true, false);
this.gui = Engine.GetGUIObjectByName("encyclopedia");
const panelSize = this.gui.getComputedSize();
// This.gui covers the entire screen (therfore panelSize.top = 0).
const panelHeight = panelSize.bottom;
const letteringHeight = panelHeight * 0.088;
const letteringVerticalOffset = panelHeight * 0.024;
this.lettering = Engine.GetGUIObjectByName("lettering");
// The lettering image file has an aspect ration of 8:1.
// Its size is relative to the screen height to prevent it from taking up too much space on lower screen resolutions.
// We have to set its size in here to avoid distortion between different screen aspect ratios.
this.lettering.size = new GUISize(-(letteringHeight * 4), letteringVerticalOffset, letteringHeight * 4, letteringVerticalOffset + letteringHeight, 50, 0, 50, 0);
this.navigationPanel = new NavigationPanel(this);
this.introductionPanel = new IntroductionPanel(this);
this.selectionPanel = new SelectionPanel(this);
this.articlePanel = new ArticlePanel(this);
}
/**
* The introductionPanel, the selectionPanel, and the articlePanel lie above each other.
* This method is responsible for showing one and hiding the others.
*/
switchPanel(panel)
{
this.panel = panel;
this.introductionPanel.gui.hidden = panel != "introduction";
this.selectionPanel.gui.hidden = panel != "selection";
this.articlePanel.gui.hidden = panel != "article";
}
}
EncyclopediaPage.prototype.pathToArticles = "gui/encyclopedia/articles/";

View File

@ -0,0 +1,245 @@
var g_EncyclopediaStructure = {
"about": {
"title": "About this Encyclopedia"
},
"nature": {
"title": "Nature and Environment",
"subdirectories": {
"animals": {
"title": "Animals"
},
"vegetation": {
"title": "Vegetation"
},
"other": {
"title": "Other map items"
}
}
},
"ancient_world": {
"title": "The Ancient World",
"subdirectories": {
"warfare": {
"title": "Ancient warfare"
},
"society": {
"title": "Ancient society"
}
}
},
"civilizations": {
"title": "0 A.D.'s Civilizations",
"subdirectories": {
"athen": {
"title": "Athenians",
"subdirectories": {
"military": {
"title": "Athenian military"
},
"society": {
"title": "Athenian society"
},
"heroes": {
"title": "Athenian heroes"
}
}
},
"brit": {
"title": "Britons",
"subdirectories": {
"military": {
"title": "Briton military"
},
"society": {
"title": "Briton society"
},
"heroes": {
"title": "Briton heroes"
}
}
},
"cart": {
"title": "Carthaginians",
"subdirectories": {
"military": {
"title": "Carthaginian military"
},
"society": {
"title": "Carthaginian society"
},
"heroes": {
"title": "Carthaginian heroes"
}
}
},
"gaul": {
"title": "Gauls",
"subdirectories": {
"military": {
"title": "Gaul military"
},
"society": {
"title": "Gaul society"
},
"heroes": {
"title": "Gaul heroes"
}
}
},
"han": {
"title": "Han",
"subdirectories": {
"military": {
"title": "Han military"
},
"society": {
"title": "Han society"
},
"heroes": {
"title": "Han heroes"
}
}
},
"iber": {
"title": "Iberians",
"subdirectories": {
"military": {
"title": "Iberian military"
},
"society": {
"title": "Iberian society"
},
"heroes": {
"title": "Iberian heroes"
}
}
},
"kush": {
"title": "Kushites",
"subdirectories": {
"military": {
"title": "Kushite military"
},
"society": {
"title": "Kushite society"
},
"heroes": {
"title": "Kushite heroes"
}
}
},
"mace": {
"title": "Macedonians",
"subdirectories": {
"military": {
"title": "Macedonian military"
},
"society": {
"title": "Macedonian society"
},
"heroes": {
"title": "Macedonian heroes"
}
}
},
"maur": {
"title": "Mauryas",
"subdirectories": {
"military": {
"title": "Mauryan military"
},
"society": {
"title": "Mauryan society"
},
"heroes": {
"title": "Mauryan heroes"
}
}
},
"pers": {
"title": "Persians",
"subdirectories": {
"military": {
"title": "Persian military"
},
"society": {
"title": "Persian society"
},
"heroes": {
"title": "Persian heroes"
}
}
},
"ptol": {
"title": "Ptolemies",
"subdirectories": {
"military": {
"title": "Ptolemaic military"
},
"society": {
"title": "Ptolemaic society"
},
"heroes": {
"title": "Ptolemaic heroes"
}
}
},
"rome": {
"title": "Romans",
"subdirectories": {
"military": {
"title": "Roman military"
},
"society": {
"title": "Roman society"
},
"heroes": {
"title": "Roman heroes"
}
}
},
"sele": {
"title": "Seleucids",
"subdirectories": {
"military": {
"title": "Seleucid military"
},
"society": {
"title": "Seleucid society"
},
"heroes": {
"title": "Seleucid heroes"
}
}
},
"spart": {
"title": "Spartans",
"subdirectories": {
"military": {
"title": "Spartan military"
},
"society": {
"title": "Spartan society"
},
"heroes": {
"title": "Spartan heroes"
}
}
}
}
},
"wars_and_battles": {
"title": "Wars and Battles",
"subdirectories": {
"ancient_china": {
"title": "Ancient China"
},
"ancient_greece": {
"title": "Ancient Greece"
},
"hellenistic_age": {
"title": "The Hellenistic age"
}
}
}
};

View File

@ -0,0 +1 @@
Note: As the game of 0 A.D. itself, this encyclopedia is still a work in progress and considered incomplete. Essential topics have not been covered (yet).

View File

@ -0,0 +1,4 @@
{
"text": "This encyclopedia aims to explain the historical context of every unit, building, upgrade, and other items found in 0 A.D. as well as provide interesting and related background information. It features several hundreds of individually researched and verified articles with an average length of about 200 words each. They are written for players of any knowledge level, from novices to experienced historians. \n What are you waiting for? Dive deep into the fascinating world of ancient civilizations!",
"hideLearnMore": true
}

View File

@ -0,0 +1,4 @@
{
"text": "Ancient civilizations were generally in steady contact with surrounding peoples, both friends and foes. So it is no surprise that some civilizations shared similar beliefs, customs, technologies, and weapons. Primitive techniques and tools were oftentimes even invented on different sides of the planet entirely independently. Here you will find articles that cannot be assigned to a single civilization but instead spill over to several or even describe the ancient world in its very fundamentals.",
"learnMorePhrase": "Learn more about the fascinating topic of …"
}

View File

@ -0,0 +1 @@
Ancient civilizations were generally in steady contact with surrounding peoples, both friends and foes. So it is no surprise that some civilizations shared similar beliefs, customs, technologies, and weapons. Primitive techniques and tools were oftentimes even invented on different sides of the planet entirely independently. Here you will find articles that cannot be assigned to a single civilization but instead spill over to several or even describe the ancient world in its very fundamentals.

View File

@ -0,0 +1 @@
Learn more about the fascinating topic of …

View File

@ -0,0 +1,3 @@
{
"text":"The Greek city-state of Athens is remembered as a famed center for the arts, learning, and philosophy, as well as one of the earliest forms of democracy. That wasn't to say that they weren't warriors. Athens at its height had one of the most powerful navys in the ancient world and through conquering and colinizing built a vast empire.\nAncient Athens rose to an imperial power after defeating the invading Persians twice in the early fifth century BC, and fell in 330 BC, when they lost the Battle of Chaeronea to King Phillip II of Macedonia. While after that it never rose again to power, Athens still was renown for its learning and its scholars were well sought out as teachers."
}

View File

@ -0,0 +1,4 @@
{
"title": "Athenian Hoplite",
"content": "Ancient Athens' hoplites were drawn from the third-highest social class, the “Zeugitai”, people who earned or produced at least 200 medimnoi (an Ancient Greek unit of volume close to thirteen gallons or 50 liters) of goods per year. This was to ensure they would have the financial means to provide their own hoplite equipment, which was, for the average citizen, quite expensive.\n\nThe equipment consisted of a round convex shield, about 3 feet (1 meter) in diameter, which was reinforced with copper on the outside. The main weapon was a 7- to 9-foot (around 2.5 meters)-long spear, which had an iron spearhead on one end and a spike on the other end as a counterweight. They also carried a short sword as a secondary weapon. Besides perhaps a bronze helmet, a hoplite's body armor varied between individuals, depending on what they could afford. Some wore bronze breastplates and greaves, others only wore leather or linen armor. In total, a hoplite's equipment weighed up to 70 pounds (about 30 kilograms).\n\nIn Athens, only 18- to 20-year-olds were obligated to actively take part in military training. However, should war break out, men up to the age of 60 could be called up to serve in the Athenian army. This meant Athens' huge hoplite force, at its peak over 30,000 men strong, largely consisted of comparably inexperienced militias. Despite this, the Athenian army was known for their patriotic morale, with many soldiers willing to sacrifice their lives for the common good of Athens, and for their skilled commanders. So, it's no wonder they dominated Classical Ancient Greece."
}

View File

@ -0,0 +1,4 @@
{
"title": "Athenian Marine",
"content": "Besides ramming, boarding and taking over the enemy's ship was a common tactic in naval warfare. Consequently, each Athenian warship was garrisoned by a number of marines, depending on the circumstances. In addition to the 170 oarsmen on each trireme, around 15 to 30 marine soldiers were part of the ship's crew. It is estimated that around 2 out of 3 of those were naval hoplites (called “Epibatai”); the rest were archers; mostly mercenaries.\n\nThe “Epibatai” on the other hand, were Athenians. It seems like many of them were recruited from the fourth (and lowest) class of Athenian citizens and a good few also from the third social class (otherwise the primary pool for drafting hoplites into the land armies).\n\nAs mentioned above, the “Epibatai” also fought as hoplites, carrying a large round shield, a 2-meter-long spear, and a sword as a secondary weapon. Compared to those fighting on land, they were probably armored lighter to suit the need of moving between ships and swimming should they fall overboard."
}

View File

@ -0,0 +1,4 @@
{
"title": "Athenian Slinger Militia",
"content": "Throughout Ancient Greece, soldiers had to provide their own equipment. In wartime, people of the lowest social class in Athens who couldn't afford a hoplite's expensive equipment served either as oarsmen in the Athenian navy or as light infantrymen on land. The latter were called “Psiloi” (skirmishers) and were armed with different kinds of missile weapons, such as slings, bows, or javelins. It's said some would even just carry stones and throw them at the enemies. Their lack of body armor and shield left them vulnerable in close combat, but it also gave them an edge over the heavier-equipped but slower hoplites in speed and maneuverability.\n\nHowever, for a long time, Athens hired mercenaries instead of recruiting capable ranged infantry units themselves; most Athenian “Psiloi” were just militia and therefore lacked training and experience. Compared to hoplites, they only had little effect on the outcome of most battles, as they weren't part of the main phalanx formation. Instead, they carried out skirmishes, tried to disrupt the enemy's formation, guarded the army camp, scouted the terrain, and pursued fleeing enemies."
}

View File

@ -0,0 +1,4 @@
{
"title": "Athens Walls",
"content": "The idea to build Athens' walls was probably first proposed by the politician Themistocles after Athens was completely destroyed during the Second Persian Invasion. While the walls around the city were constructed right away, the famous Long Walls would not be until 20 years later, around 460 BC.\n\nThe two Long Walls were around 3.7 miles long (6 kilometers) and, stood parallel, at around 6500 feet (200 meters) apart. The Long walls protected the passage to Athens' port, Piraeus. Another wall further to the east was also constructed, leading towards another smaller port called Phaleron. This wall formed a triangle enclosed by the walls and the shore, and the space between was used for agriculture. The entire Athenian wall system was over 15 miles long (25 kilometers), around 9 feet wide (3 meters), and 30 feet high (9 meters) and became a majestic symbol for Athens' power and dominance.\n\nThe walls formed a key point in Athens's war strategy. They could avoid fighting enemies on land and instead rely on their powerful navy to engage in combat with them. And, in case of a siege, the city had coastal access in its walls, which meant all necessary food could be brought from the sea. \n\nThis strategy worked well, but only as long as Athenian ships were able to provide a constant inflow of food. For example, when the Athenian fleet was annihilated at Aegospotami (405 BC), the besieged city of Athens' was cut off from food supplies and had no choice but to surrender."
}

View File

@ -0,0 +1,4 @@
{
"title": "Barracks",
"content": "The Classical Athenian education and training system was meant to teach both physical and intellectual skills and to prepare students for times of peace and war. It was, however, exclusive to the sons of free Athenian citizens. Girls were tutored at home by either their mothers or private teachers.\n\nThere was no public education in Athens. Boys went to private schools, which were relatively inexpensive, so most boys could attend for at least a couple of years. There, they learned how to write and read, as well as mathematics, music, rhetoric, literature (reading famous and important works such as The Iliad and Odyssey), and politics. Physical training contained activities such as running, jumping, wrestling, and boxing at the gymnasium. For many boys, elementary education ended around the age of 15, and only those who could afford it stayed in school for a few more years.\n\nBetween the ages of 18 and 20, the young men underwent two years of mandatory military training called “ephebeia”. It included practicing hoplite combat, learning how to fight with a spear and shield as well as ranged weapons like bows, slings, and javelins. At a later stage in the “ephebeia”, the men were sent as patrolmen to guard forts around the city-state. At the age of 20, they were released but remained liable for military service until they were 60."
}

View File

@ -0,0 +1,4 @@
{
"title": "Cavalry Javelineer",
"content": "The Prodromoi were a light cavalry unit in the Athenian military, established in the early fourth century BC, maybe as part of Iphicrates' military reforms. They were recruited from the lowest social class of Athenian citizens who didn't have the financial means to buy their own equipment. Instead, their equipment was provided by their phlyarchs, the expected commanders of each cavalry division.\n\nThe Prodromoi were armed with javelins for ranged attacks, as well as swords for close-range combat. They wore bronze helmets, and some also had leather or linen armor. Horses had no horseshoes, bridles, stirrups, or saddles—just a piece of cloth draped over their backs. Scarce evidence suggests the total number of Prodromoi at 200, making up only a small part of the entire Athenian cavalry force.\n\nAs the name “Prodromoi” (“pre-cursors”, “runners-before”, “runners-ahead”) implies, they functioned as fast scouting units advancing ahead of the main army, gathering information about the enemy and the terrain. They also carried out skirmishes, harassing the enemy with their javelins.\n\nIt is assumed that the Prodromoi corps was abolished in the third century BC, as the term “Podromoi” was used to referring to aides of cavalry officers."
}

View File

@ -0,0 +1,4 @@
{
"title": "City Guard",
"content": "In Athens, only 18 to 20-year-olds were obligated to actively take part in military training. However, should war break out, men up to the age of 60 could be called up to serve in the Athenian army. This meant Athens' hoplite force largely consisted of militias who lacked training and experience.\n\nHowever, just as several other Greek city-states did, Athens maintained a small elite hoplite force of professional soldiers. They were called “Epilektoi” or “Logades” (both meaning “the chosen ones”). As the name implies, they were hand-picked for specific purposes. They could either be used to support the main hoplite body or carry out separate missions that required fighting expertise. The “Epilektoi” actually numbered only several hundred up to a thousand men and actually made up only a small percentage of Athens' large hoplite force, which was, at their peak, more than 30,000 men strong.\n\nThey were probably recruited from a bracket of wealthy Athenian citizens, as every soldier had to provide his own equipment, which not only consisted of a spear, a large round shield, and a short sword, which were quite expensive for the average citizen, but also heavier (and more expensive) armor than regular hopilites that provided better protection."
}

View File

@ -0,0 +1,4 @@
{
"title": "Cretan Mercenary Archer",
"content": "The Cretans were renowned for their great archery skills and thought to be one of the best light infantry in the entire world. Many served as mercenaries for various Greek city-states such as Athens and Sparta, often on board ships where skilled archers were especially sought after. Even in Alexander the Great's armies were Cretan archers present and played a decisive role in some battles. After Alexander’s death, they continued to stand in the ranks for various Hellenistic rulers. The Romans also recognized their value and recruited Cretan archers into their armies. More than a thousand years later, in 1453, mercenary Cretan archers were still standing in the ranks of the Eastern Roman Empire, defending the city of Constantinople against the Ottoman army under Mehmet II.\n\nGreek archers generally fought with little to no protection to increase their mobility and speed in skirmishes. However, Cretan archers carried a small round shield as well as a sword, which made them, unlike many other skirmishing units, capable of defending themselves in close combat. Over time, the label “Cretan archers” might have become also a collective term referring to soldiers of any ethnicity who were equipped in this characteristically Cretan style."
}

View File

@ -0,0 +1,4 @@
{
"title": "Dock",
"content": "Athens had a strong naval tradition. Seafaring was a big part of the Athenian culture. Athens' navy rose to power under the leadership of Themistocles. Following the Greek victory over Persian invaders at the Battle of Salamis in 480 BC, Athens dominated the Aegean Sea and controlled large territories in Ancient Greece. The navy was considered to be the largest and most powerful of its time. Athenian warships were well-designed and well-built, and crews consisted of professional rowers recruited from the lower classes. At best, Athens could deploy a massive fleet of more than 400 triremes. Athens also invested heavily in securing trade routes. As a result, they enjoyed a period of prosperity, economic growth, and the flourishing of not only Athenian but also Greek civilization and culture. This period during the 5th century BC is known as the Golden Age of Athens. \n\nHowever, Athens’ naval supremacy was challenged and eventually ended by Sparta in the Peloponnesian War. After this war, Athens never regained its former naval glory and influence."
}

View File

@ -0,0 +1,4 @@
{
"title": "Greek Cavalry",
"content": "The second-highest social class in Ancient Athens was the “hippeis”, the cavalrymen. They formed a corps of about 1000 heavy cavalry troops, similar to cavalry units in other Greek city states. Even though these citizen soldiers received some equipment money from the state, they had to cover most of the incurring expenses - from horses, to grooms, to their own equipment - by themselves, which could get very expensive.\n\nTheir armor was pretty ordinary for a Greek cavalry; it usually consisted of an iron helmet, a coat of mail, a kilt fringed with metal flaps, cuisses, and leather leggings. They wielded a straight, double-edged sword and a spear that could be thrown like a javelin or used as a lance in close-range combat. Horses had no horseshoes, bridles, stirrups, or saddles—just a piece of cloth draped over their backs.\n\nAlthough they enjoyed elite status in the Athenian army, the cavalry posed a comparably insignificant factor in most battles, they generally avoided direct engagement with the enemy's line. Instead, they served as a mobile and versatile support force; skirmishing, scouting, or pursuing fleeing enemies."
}

View File

@ -0,0 +1,4 @@
{
"title": "Scythian Archer",
"content": "Everything we know about the Scythian Archers in Athens comes from ancient Greek literature and artwork. Although the evidence is scarce, it is enough to safely assume that they did indeed exist.\n\nAccording to some sources, the state of Athens purchased Scythian slaves in the early 5th century and assigned them under the command of the eleven elected magistrates of Athens. In many texts, the Scythian Archers were called “speusinioi”, named after a certain “Speusis” or “Speusinos”, allegedly the founder of this Scythian force. The number of these Scythian Archers in Athens changed over time, ranging from 300 to over 1000. It was their duty to ensure public safety, enforce laws, arrest troublemakers, and guard the city of Athens itself. The Scythian Archers sort of acted like a police force in Athens.\n\nThe Scythians were a nomadic people who inhabited the vast steppe of Eurasia. While the Greeks esteemed their horsemanship and archery skills, they also regarded them as very barbarous, uncivilized, and cruel. The reason Athens employed such foreigners might be that, due to the xenophobia present in ancient Greek society, the Scythians intimidated the Athenian people more than a police force composed of locals would have.\n\nIt is doubtful that the Scythians were equipped with bows in the narrow and crowded streets of Athens. Moreover, the terms “Scythians” and “archers” might have been generic labels for any exotic foreigners. Any, as the Greeks called them, “barbaroi” (meaning exactly what it sounds like), not necessarily referring to actual Scythians or archers. Therefore, the Scythian Archers might very well neither have actually been Scythians nor archers."
}

View File

@ -0,0 +1,4 @@
{
"title": "Stable",
"content": "Because cavalry in Ancient Greece played an insignificant role in most battles, the Athenians, for a long time, saw no need to create a competitive force of cavalry. Instead, they relied on allies to provide horsemen or hired mercenaries. However, in the 5th century BC, the Athenians finally recognized the value of home-grown cavalry, maybe after having themselves faced the skilled Persian horsemen in the Greco-Persian wars, and started recruiting.\n\nEach of the ten Athenian tribes was obligated to provide their own cavalry squadron, each under the command of their—in true democratic fashion—yearly elected leader called the phylarch. The phylarchs themselves were commanded by the two—again, in true democratic fashion—yearly elected Athenian cavalry commanders called hipparchs.\n\nBack then, the biggest struggle of raising cavalry lied in financing. Soldiers had to purchase their own equipment, and horses were very expensive, some costing multiple times the yearly income of an average worker. That's why the Athenian state issued what we today would describe as establishment loans to financially facilitate entry into the cavalry corps. There was also a “horse insurance” system in place for those whose horses had died in battle.\n\nAs a result of the effort and money the Athenian state had invested in expanding their cavalry, by the year 431 BC, the number of Athenian cavalrymen had grown to 1000 heavy cavalry and 200 mounted bowmen and was, at the time, one of the largest cavalry forces in Greece."
}

View File

@ -0,0 +1,4 @@
{
"title": "Thracian Peltast",
"content": "Peltasts were a type of Greek light infantry unit originating from Thrace, often fighting as mercenaries for various Greek city-states. They were named after their uniquely crescent-shaped shield (pelte). It was not only smaller than a hoplite's shield, but also thinner and lighter due to it being covered in hide rather than bronze. They wore minimal armor and carried a short sword, in addition to several javelins. Peltasts often used the so-called ankyle, a leather thong attached to the javelin. It was looped over two fingers and slipped off when thrown, extending the leverage and therefore increasing the javelin's momentum and the distance it would travel.\n\nThe introduction of peltasts into ancient Greece brought a small, but trendsetting revolution on the battlefields: They essentially fought as a mixture between ranged and melee troops which in some way hit the Achilles heel of traditional Greek warfare. Because of their stronger protection, peltasts outmatched other ranged units like javelineers or archers. On the flipside, they were still agile enough to outmaneuver and exhaust the heavily-armored hoplites: throwing javelins at them from a safe distance, evading the hoplites' charges, regrouping and attacking again."
}

View File

@ -0,0 +1,3 @@
{
"text": "The Britons were the Celtic tribes of the British Isles. Using chariots, longswordsmen and powerful melee soldiers, they staged fearsome revolts against Rome to protect their customs and interests. Also, they built thousands of unique structures such as hill forts, crannogs and brochs."
}

View File

@ -0,0 +1,3 @@
{
"text": "Carthage, a city-state in modern-day Tunisia, was a formidable force in the western Mediterranean, eventually taking over much of North Africa and modern-day Spain in the third century BC. The sailors of Carthage were among the fiercest contenders on the high seas, and masters of naval trade. They deployed towered War Elephants on the battlefield to fearsome effect, and had defensive walls so strong, they were never breached."
}

View File

@ -0,0 +1,3 @@
{
"text": "The Gauls were the Celtic tribes of continental Europe. Dominated by a priestly class of Druids, they featured a sophisticated culture of advanced metalworking, agriculture, trade and even road engineering. With heavy infantry and cavalry, Gallic warriors valiantly resisted Caesar's campaign of conquest and Rome's authoritarian rule."
}

View File

@ -0,0 +1,3 @@
{
"text": "The Han dynasty was the second dynasty of imperial China. Founded by a commoner Liu Bang, the empire lasted from 202 BC to AD 220 with a short break in AD 9 when Wang Mang took the throne. Making it the longest imperial dynasty in Chinese history. The Han dynasty was a period of relative peace, as well as cultural and technological growth, and for that reason is considered “the first golden age of China”. The name of today's largest ethnic group in the world, the Han Chinese, derives from this very period."
}

View File

@ -0,0 +1,3 @@
{
"text": "The Iberians were a people of mysterious origins and language, with a strong tradition of horsemanship and metalworking. A relatively peaceful culture, they usually fought in other's battles only as mercenaries. However, they proved tenacious when Rome sought to take their land and freedom from them, and employed pioneering guerrilla tactics and flaming javelins as they fought back."
}

View File

@ -0,0 +1,4 @@
{
"text": "0 A.D. features 13 different civilizations based off the world's greatest peoples from the timeframe of 500 BC to AD 500, taken from their height of power. Each brings unique historical units, buildings, technologies, and heroes. You will encounter everything from the advanced Carthaginian quinqueremes via the infamous Roman legionaries to the deadly Chinese crossbowmen. Learning about a civilization's history can help to understand and make use of its strengths and weaknesses.",
"hideLearnMore": true
}

View File

@ -0,0 +1,3 @@
{
"text": "The Kingdom of Kush was an ancient African kingdom situated on the confluences of the Blue Nile, White Nile and River Atbara in what is now the Republic of Sudan. The Kushite era of rule in the region was established after the Bronze Age collapse of the New Kingdom of Egypt, and it was centered at Napata in its early phase. They invaded Egypt in the 8th century BC, and the Kushite emperors ruled as Pharaohs of the Twenty-fifth dynasty of Egypt for a century, until they were expelled by the Assyrians. Kushite culture was influenced heavily by the Egyptians, with Kushite pyramid building and monumental temple architecture still extent. The Kushites even worshipped many Egyptian gods, including Amun. During Classical antiquity, the Kushite imperial capital was at Meroe. In early Greek geography, the Meroitic kingdom was known as Aethiopia. The Kushite kingdom persisted until the 4th century AD, when it weakened and disintegrated due to internal rebellion, eventually succumbing to the rising power of Axum."
}

View File

@ -0,0 +1,3 @@
{
"text": "Macedonia was an ancient Greek kingdom, centered in the northeastern part of the Greek peninsula. Under the leadership of Alexander the Great, Macedonian forces and allies took over most of the world they knew, including Egypt, Persia and parts of the Indian subcontinent, allowing a diffusion of Hellenic and eastern cultures for years to come."
}

View File

@ -0,0 +1,3 @@
{
"text": "Founded in 322 BC by Chandragupta Maurya, the Mauryan Empire was the first to rule most of the Indian subcontinent, and was one of the largest and most populous empires of antiquity. Its military featured bowmen who used the long-range bamboo longbow, fierce female warriors, chariots, and thousands of armored war elephants. Its philosophers, especially the famous Acharya Chanakya, contributed to such varied fields such as economics, religion, diplomacy, warfare, and good governance. Under the rule of Ashoka the Great, the empire saw 40 years of peace, harmony, and prosperity."
}

View File

@ -0,0 +1,3 @@
{
"text": "The Persian Empire, when ruled by the Achaemenid dynasty, was one of the greatest empires of antiquity, stretching at its zenith from the Indus Valley in the east to Greece in the west. The Persians were the pioneers of empire-building of the ancient world, successfully imposing a centralized rule over various peoples with different customs, laws, religions and languages, and building a cosmopolitan army made up of contingents from each of these nations."
}

View File

@ -0,0 +1,3 @@
{
"text": "The Ptolemaic dynasty was a Macedonian Greek royal family which ruled the Ptolemaic Empire in Egypt during the Hellenistic period. Their rule lasted for 275 years, from 305 BC to 30 BC. They were the last dynasty of ancient Egypt."
}

View File

@ -0,0 +1,3 @@
{
"text": "The Romans controlled one of the largest empires of the ancient world, stretching at its peak from southern Scotland to the Sahara Desert, and containing between 60 million and 80 million inhabitants, one quarter of the Earth's population at that time. Rome also remained one of the strongest nations on earth for almost 800 years. The Romans were the supreme builders of the ancient world, excelled at siege warfare and had an exquisite infantry and navy."
}

View File

@ -0,0 +1,3 @@
{
"text": "The Macedonian-Greek dynasty that ruled most of Alexander's former empire."
}

View File

@ -0,0 +1,3 @@
{
"text": "Sparta was a prominent city-state in Ancient Greece, and its dominant military power starting in the 7th century BC. It peaked after the Peloponnesian Wars in the late fifth century BC but declined soon after, ending when they lost to Thebes in the battle of Leuctra in 371 BC.\nSpartan culture was obsessed with military training and excellence, all Spartan boys were drafted into rigorous training at age seven, and their military service lasted until they were sixty. All trades were done by their serfs, the Helots.\nSpartans lived a strict and minimalistic lifestyle, separate from many of the other civilizations, due to reforms such as iron money, which were given by Lycurgus, the legendary Spartan lawgiver."
}

View File

@ -0,0 +1,4 @@
{
"text": "From the craggy mountains of Greece to the lush bamboo China, 0 A.D. features a wide range of terrain and animals that live in them. It would be wise to familiarize yourself with the biome you are fighting in, in order to best exploit the resources.",
"learnMorePhrase": "Learn more about the diverse realm of …"
}

View File

@ -0,0 +1,4 @@
{
"text": "For almost as long as people have walked the earth, there had also been war. Be it over land, wealth, or just because they don't like each other, people have had \"reasons\" to fight each other. And the wars weren't just minor squabbles, the outcome of a battle could change the fate of the two civilizations, or even the world.",
"learnMorePhrase": "Learn more about pivotal conflicts in …"
}

View File

@ -0,0 +1 @@
For almost as long as people have walked the earth, there had also been war. Be it over land, wealth, or just because they don't like each other, people have had "reasons" to fight each other. And the wars weren't just minor squabbles, the outcome of a battle could change the fate of the two civilizations, or even the world.

View File

@ -0,0 +1 @@
Learn more about pivotal conflicts in …

View File

@ -0,0 +1,5 @@
function init()
{
var g_Encyclopedia = new EncyclopediaPage();
g_Encyclopedia.introductionPanel.open("about");
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<objects>
<script directory="gui/common/"/>
<script directory="gui/encyclopedia/"/>
<script directory="gui/encyclopedia/panels/"/>
<script directory="gui/reference/common/Dropdowns/"/>
<object name="encyclopedia">
<object name="background" type="image" sprite="BeigeBackground"/>
<!-- the lettering is placed outside the centralSection so it can be horizontally centered on the entire screen -->
<object name="lettering" type="image" sprite="stretched:encyclopedia/lettering.png"/>
<object name="centralSection" size="12%+115 0 80%+33 100%">
<object size="40 11%+60 100%-20 100%-70">
<include file="gui/encyclopedia/panels/articlepanel.xml"/>
<include file="gui/encyclopedia/panels/selectionpanel.xml"/>
<include file="gui/encyclopedia/panels/introductionpanel.xml"/>
</object>
</object>
<object name="leftSection" size="0 0 12%+115 100%">
<include file="gui/encyclopedia/panels/navigationpanel.xml"/>
</object>
</object>
</objects>

View File

@ -0,0 +1,21 @@
class ArticlePanel
{
constructor(page)
{
this.page = page;
this.gui = Engine.GetGUIObjectByName("articlePanel");
this.title = Engine.GetGUIObjectByName("articleTitle");
this.textField = Engine.GetGUIObjectByName("articleTextField");
}
open(file)
{
this.page.switchPanel("article");
const json = Engine.ReadJSONFile(file);
this.title.caption = json.title;
// The line breaks are added for aesthetic reasons.
this.textField.caption = "\n" + json.content + "\n";
}
}

View File

@ -0,0 +1,115 @@
const subcategoryButtonHeight = 35;
const subcategoryButtonDist = 25;
class IntroductionPanel
{
constructor(page)
{
this.page = page;
this.gui = Engine.GetGUIObjectByName("introductionPanel");
this.title = Engine.GetGUIObjectByName("introductionTitle");
this.text = Engine.GetGUIObjectByName("introductionText");
this.civEmblem = Engine.GetGUIObjectByName("civEmblem");
this.learnMore = Engine.GetGUIObjectByName("learnMore");
this.textAddition = Engine.GetGUIObjectByName("civilizationsTextAddition");
this.disclaimer = Engine.GetGUIObjectByName("disclaimer");
this.disclaimer.caption = Engine.TranslateLines(Engine.ReadFile(this.page.pathToArticles + "about/disclaimer.txt"));
this.buttons = Engine.GetGUIObjectByName("subcategoryButtons").children;
const panelSize = this.gui.getComputedSize();
const panelWidth = panelSize.right - panelSize.left;
const panelHeight = panelSize.bottom - panelSize.top;
const civEmblemRadius = panelHeight * 0.12 - 34;
this.civEmblem.size = new GUISize(-civEmblemRadius, 50 - civEmblemRadius * 2, civEmblemRadius, 50, 50, 0, 50, 0);
// On smaller screen sizes we can only fit two buttons in the available horizontal space (otherwise they will be to narrow for their captions).
const buttonsPerLine = panelWidth > 720 ? 3 : 2;
// SubcategoryButtons are horiontal, only three fit into a line (therefore the modulo).
// Their width is determined by screen resolution.
this.buttons.forEach((button, i) => {
button.size = new GUISize(
subcategoryButtonDist / 2, Math.floor(i / buttonsPerLine) * (subcategoryButtonHeight + subcategoryButtonDist / 2),
-(subcategoryButtonDist / 2), Math.floor(i / buttonsPerLine) * (subcategoryButtonHeight + subcategoryButtonDist / 2) + subcategoryButtonHeight,
(i % buttonsPerLine) * (100 / buttonsPerLine), 0, ((i % buttonsPerLine) + 1) * (100 / buttonsPerLine), 0
);
});
this.civDropdown = new CivSelectDropdown(this.page.civData);
this.civDropdown.registerHandler((civ => {
if (civ)
this.open("civilizations", civ);
}).bind(this));
this.civDropdown.civSelection.style = "BrownDropDown";
this.civDropdown.civSelectionHeading.hidden = true;
}
setupButtons(subcategoryData)
{
if (this.page.lastCategory == "civilizations" && !this.page.lastCiv)
{
this.page.introductionPanel.civDropdown.civSelection.selected = -1;
// If no civilization is selected, all subcategoryButtons have to be hidden.
subcategoryData = {};
}
const subcategories = Object.keys(subcategoryData);
this.buttons.forEach((button, i) => {
const subcategory = subcategories[i];
button.hidden = !subcategory;
if (button.hidden)
return;
button.caption = subcategoryData[subcategory].title;
button.onPress = () => {
this.page.selectionPanel.open(this.page.lastCategory, this.page.lastCiv || "", subcategory);
};
});
if (this.buttons.length < subcategories.length)
error("GUI page has space for " + this.buttons.length + " subcategory buttons, but " + subcategories.length + " items are provided!");
}
open(category, civ)
{
this.page.switchPanel("introduction");
this.page.lastCategory = category;
this.page.lastCiv = civ;
this.disclaimer.hidden = category != "about";
this.textAddition.hidden = (category != "civilizations" || !!civ);
this.civDropdown.civSelection.hidden = category != "civilizations";
if (category == "civilizations" && civ)
{
this.openCiv(civ);
return;
}
const targetDir = this.page.pathToArticles + category + "/";
this.civEmblem.hidden = true;
this.title.caption = g_EncyclopediaStructure[category].title;
const json = Engine.ReadJSONFile(targetDir + "introduction.json");
this.text.caption = json.text;
this.learnMore.hidden = !!json.hideLearnMore;
this.learnMore.caption = json.learnMorePhrase || this.defaultLearnMorePhrase;
this.setupButtons(g_EncyclopediaStructure[category].subdirectories || {}, category);
}
openCiv(civ)
{
this.learnMore.hidden = false;
this.civEmblem.hidden = false;
this.civEmblem.children[1].sprite = "stretched:" + this.page.civData[civ].Emblem;
this.title.caption = g_EncyclopediaStructure.civilizations.subdirectories[civ].title;
this.text.caption = Engine.ReadJSONFile(this.page.pathToArticles + "civilizations/" + civ + "/introduction.json").text;
this.setupButtons(g_EncyclopediaStructure.civilizations.subdirectories[civ].subdirectories, "civilizations", civ);
}
}
IntroductionPanel.prototype.defaultLearnMorePhrase = "Learn more about the …";

View File

@ -0,0 +1,117 @@
const navigationButtons = [
{
"caption": "Structure Tree",
"onPress": pageLoop.bind(null, "page_structree.xml")
},
{
"caption": "Civilisation Overview",
"onPress": pageLoop.bind(null, "page_civinfo.xml")
},
{
"caption": "Main Menu",
"onPress": () => {
Engine.SwitchGuiPage("page_pregame.xml");
}
}
];
const categoryButtonHeight = 35;
const categoryButtonDist = 5;
const categoryPanelAbsoluteMargin = -60;
const categoryPanelRelativeMargin = 100 / 3;
const navigationButtonHeight = 30;
const navigationButtonDist = 5;
const navigationButtonPadding = 17;
class NavigationPanel
{
constructor(page)
{
this.page = page;
this.gui = Engine.GetGUIObjectByName("navigationPanel");
this.categoryButtons = Engine.GetGUIObjectByName("categoryButtons").children;
this.navigationButtons = Engine.GetGUIObjectByName("navigationButtons").children;
this.heading = Engine.GetGUIObjectByName("categoryButtonHeading");
this.categoryPanel = Engine.GetGUIObjectByName("categoryPanel");
this.mainMenuButton = Engine.GetGUIObjectByName("mainMenuButton");
/**
* Margin describes the space surrounding the panel on the outside, padding on the inside.
* The panel is placed to the left edge of the screen (this.gui.getComputedSize().left = 0) therefore 'right' determines the width.
*/
this.categoryPanelMargin = this.gui.getComputedSize().right * 0.3 - 52;
this.categoryPanelPadding = this.categoryPanelMargin / 2;
this.setupCategoryButtons(Object.keys(g_EncyclopediaStructure));
this.setupNavigationButtons(navigationButtons);
}
setupCategoryButtons(items)
{
if (!items.length)
return;
// The heading is placed above the buttons and outside of the buttonPanel.
this.heading.size = new GUISize(0, -(categoryButtonHeight + categoryButtonDist), 0, -categoryButtonDist, 0, 0, 100, 0);
this.categoryPanel.size = new GUISize(this.categoryPanelMargin, 0, -this.categoryPanelMargin,
items.length * categoryButtonHeight + (items.length - 1) * categoryButtonDist + 2 * this.categoryPanelPadding, 0, 25, 100, 25);
this.categoryButtons.forEach((button, i) => {
const item = items[i];
button.hidden = !item;
if (button.hidden)
return;
button.caption = g_EncyclopediaStructure[item].title;
button.size = new GUISize(
this.categoryPanelPadding, i * (categoryButtonHeight + categoryButtonDist) + this.categoryPanelPadding,
-this.categoryPanelPadding, i * (categoryButtonHeight + categoryButtonDist) + categoryButtonHeight + this.categoryPanelPadding,
0, 0, 100, 0);
button.onPress = () => {
this.page.lastCiv = "";
this.page.introductionPanel.open(item, this.page.lastCiv, false);
this.selectCategoryButton(item);
};
});
if (this.categoryButtons.length < items.length)
error("GUI page has space for " + this.categoryButtons.length + " category buttons, but " + items.length + " items are provided!");
}
setupNavigationButtons(items)
{
if (!items.length)
return;
// The navigationButtons are anchored to the bottom, and are drawn from the bottom up for simplicity.
// We therefore need to loop throught the items from back to front (since the first item is supposed to be at the top).
this.navigationButtons.forEach((button, i) => {
const item = items[items.length - i - 1];
button.hidden = !item;
if (button.hidden)
return;
button.caption = item.caption;
button.onPress = item.onPress.bind(this);
button.size = new GUISize(
navigationButtonPadding,
-(i * (navigationButtonHeight + navigationButtonDist) + navigationButtonHeight + navigationButtonPadding),
-navigationButtonPadding,
-(i * (navigationButtonHeight + navigationButtonDist) + navigationButtonPadding),
0, 100, 100, 100);
});
if (this.categoryButtons.length < items.length)
error("GUI page has space for " + this.categoryButtons.length + " category buttons, but " + items.length + " items are provided!");
}
selectCategoryButton(category)
{
for (const button of this.categoryButtons)
{
button.sprite = button.caption == category ? "StoneButtonOver" : "StoneButton";
}
}
}

View File

@ -0,0 +1,46 @@
class SelectionPanel
{
constructor(page)
{
this.page = page;
this.gui = Engine.GetGUIObjectByName("selectionPanel");
this.title = Engine.GetGUIObjectByName("selectionTitle");
this.warning = Engine.GetGUIObjectByName("selectionWarning");
this.warning.hidden = true;
this.selection = Engine.GetGUIObjectByName("selectionList");
this.list = [];
}
setupList(targetdir)
{
this.list = Engine.ListDirectoryFiles(targetdir, "*.json", false);
this.warning.hidden = this.list.length != 0;
this.selection.list = this.list.map(file => {
return Engine.ReadJSONFile(file).title;
});
// A double-click opens the article.
this.selection.selected = -1;
let selected = this.selection.selected;
this.selection.onSelectionChange = () => {
if (this.selection.selected == selected && selected != -1)
this.page.articlePanel.open(this.list[selected]);
selected = this.selection.selected;
};
}
open(category, civ, subcategory)
{
this.page.switchPanel("selection");
this.page.lastSubcategory = subcategory;
this.title.caption =
civ ?
g_EncyclopediaStructure.civilizations.subdirectories[civ].subdirectories[subcategory].title :
g_EncyclopediaStructure[category].subdirectories[subcategory].title;
const targetPath = this.page.pathToArticles + category + "/" + (civ ? civ + "/" : "") + subcategory;
this.setupList(targetPath);
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<object name="articlePanel">
<object name="articleOuterFrame" type="image" sprite="WideOrnateFrame"/>
<!-- The outerFrame uses the WideOrnateFrame sprite whose horizontal and vertical textures have different widths (22px vs 23px).
What follows is the space inside the outerFrame. -->
<object name="articlePanelContent" size="23 22 100%-23 100%-22">
<object name="articleTitle" type="text" font="sans-bold-26" textcolor="blackbrown" text_valign="center" text_align="center" size="90 45 100%-90 90"/>
<object name="articleTextField" scroll_top="true" scrollbar="true" scrollbar_style="BrownGoldenScrollBar" type="text" font="sans-18" textcolor="blackbrown" text_align="left" size="40 120 100%-20 100%-30"/>
<object name="articleOrnament" type="image" sprite="TextOrnament" size="2 120 100%-2 100%-30" ghost="true"/>
</object>
</object>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<object name="introductionPanel">
<object size="16 16 100%-16 100%-16">
<include file="gui/reference/common/Dropdowns/CivSelectDropdown.xml"/>
</object>
<object name="introductionFrame" type="image" sprite="MediumOrnateFrame"/>
<object name="introductionTitle" type="text" font="sans-bold-24" textcolor="blackbrown" size="50%-200 10% 50%+200 10%+30" text_valign="center" text_align="center"/>
<object name="introductionTitleSeperator" type="image" sprite="BrownSeparator" size="20% 18% 80% 18%+2"/>
<object name="introductionText" scroll_top="true" font="sans-20" textcolor="blackbrown" type="text" scrollbar="true" scrollbar_style="BrownScrollBar" size="50 25% 100%-30 70%-50" />
<object name="civilizationsTextAddition" type="text" font="sans-20" size="50 70% 100%-30 70%+100">
<translatableAttribute id="caption">The question is…\n[font="sans-bold-22"]Who will you choose to lead to victory?[/font]</translatableAttribute>
</object>
<object name="disclaimer" type="text" font="sans-italic-18" textcolor="blackbrown" text_align="center" text_valign="bottom" size="50 25% 100%-30 93%" ghost="true"/>
<object name="civEmblem" type="image" size="50%-35 -25 50%+35 45">
<object name="civEmblemFrame" type="image" sprite="stretched:encyclopedia/frames/medium/circle.png" size="-10 -10 100%+10 100%+10" ghost="true"/>
<object name="civEmblemTexture" type="image"/>
<object name="civEmblemOver" type="button" sprite="color:transparent" sprite_over="stretched:session/portraits/emblems/states/hover.png" sprite_pressed="stretched:session/portraits/emblems/states/hover.png"/>
</object>
<object name="learnMore" type="text" size="50 70% 100% 80%" font="sans-20" textcolor="blackbrown"/>
<object name="subcategoryButtons" size="60 79% 100%-60 100%">
<repeat count="4">
<object name="subcategoryButton[n]" type="button" style="BrownButton"/>
</repeat>
</object>
</object>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<object name="navigationPanel">
<object name="rightShading" type="image" size ="100%-20 0 100%+100 100%" sprite="stretched:global/modern/item-shading-right.png"/>
<object name="navigationPanelBackground" type="image" sprite="DarkTilesBackgroundLeft"/>
<object name="logo" size="50%-110 30 50%+110 130" type="image" sprite="0ADLogo"/>
<object name="categoryPanel" type="image" style="TranslucentPanelThinBorder">
<object name="categoryButtonHeading" type="text" style="ModernLabelText">
<translatableAttribute id="caption">Choose a category:</translatableAttribute>
</object>
<object name="categoryButtons">
<repeat count="7">
<object name="categoryButton[n]" type="button" style="StoneButton"/>
</repeat>
</object>
</object>
<object name="navigationButtons">
<repeat count="4">
<object name="navigationButton[n]" type="button" style="ModernButtonRed"/>
</repeat>
</object>
</object>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<object name="selectionPanel">
<object name="selectionFrame" type="image" sprite="MediumOrnateFrame"/>
<object name="selectionTitle" type="text" ghost="true" font="sans-bold-24" textcolor="blackbrown" size="50%-150 10% 50%+150 10%+50" text_align="center"/>
<object name="selectionTitleSeperator" type="image" sprite="BrownSeparator" size="20% 18% 80% 18%+2"/>
<object name="selectionWarning" type="text" ghost="true" font="sans-italic-20" textcolor="blackbrown" size="100 25%+30 100%-100 25%+80" text_align="center">
<translatableAttribute id="caption">No articles have been written about this topic yet.</translatableAttribute>
</object>
<object name="selectionListCorners" ghost="true">
<object name="selectionListCornerRight" type="image" sprite="BrownCornerRight" size="100%-188 100%-188 100%-60 100%-60"/>
<object name="selectionListCornerLeft" type="image" sprite="BrownCornerLeft" size="60 100%-188 188 100%-60"/>
</object>
<object name="selectionList" type="list" size="100 25% 100%-85 100%-100" buffer_zone="20"
font="sans-bold-18"
textcolor="blackbrown"
textcolor_selected="mattbrown"
scrollbar="true"
scrollbar_style="BrownScrollBar"
sprite_selectarea="WideBrownBorderOver"
text_align="center"
sound_selected="audio/interface/ui/ui_button_click.ogg">
</object>
</object>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<setup>
<scrollbar name="BrownScrollBar"
width="15"
minimum_bar_size="15"
maximum_bar_size="15"
show_edge_buttons="false"
sprite_bar_vertical="BrownScrollSlider"
sprite_back_vertical="BrownScrollBack"
/>
<scrollbar name="BrownGoldenScrollBar"
width="15"
minimum_bar_size="15"
maximum_bar_size="15"
show_edge_buttons="false"
sprite_bar_vertical="GoldenScrollSlider"
sprite_back_vertical="BrownScrollBack"
/>
<color name="blackbrown">29 15 5</color>
<color name="mattbrown">122 95 75</color>
</setup>

View File

@ -0,0 +1,260 @@
<?xml version="1.0" encoding="utf-8"?>
<sprites>
<!--
==========================================
BACKGROUND SPRITES
==========================================
-->
<sprite name="DarkTilesBackgroundLeft">
<image texture="global/tile/stone_background.png"
real_texture_placement="28 0 292 264"
texture_size="0 0 240 240"
/>
<image backcolor="230 190 80"
size="100%-3 0 100% 100%"
/>
</sprite>
<sprite name="LightBrownBackground">
<image backcolor="mattbrown"/>
</sprite>
<sprite name="BeigeDropdownBackground">
<image texture="encyclopedia/backgrounds/beige.png"
real_texture_placement="0 0 1024 2048"
/>
<image backcolor="255 240 203 70"/>
</sprite>
<sprite name="BeigeBackground">
<image texture="encyclopedia/backgrounds/beige.png"
real_texture_placement="0 0 2048 2048"
/>
</sprite>
<!--
==========================================
DECORATIONS
==========================================
-->
<sprite name="WideOrnateFrame">
<!-- edges -->
<image texture="encyclopedia/frames/wide/top-edge.png"
texture_size="0 0 128 32"
size="32 0 100%-32 32"
/>
<image texture="encyclopedia/frames/wide/vertical-edge.png"
texture_size="0 0 32 128"
size="100%-32 32 100% 100%"
/>
<image texture="encyclopedia/frames/wide/bottom-edge.png"
texture_size="0 0 128 32"
size="32 100%-32 100%-32 100%"
/>
<image texture="encyclopedia/frames/wide/vertical-edge.png"
texture_size="32 0 0 128"
size="0 32 32 100%-32"
/>
<!-- corners -->
<image texture="encyclopedia/frames/wide/top-corner.png"
size="0 0 32 32"
/>
<image texture="encyclopedia/frames/wide/top-corner.png"
texture_size="32 0 0 32"
size="100%-32 0 100% 32"
/>
<image texture="encyclopedia/frames/wide/bottom-corner.png"
texture_size="32 0 0 32"
size="100%-32 100%-32 100% 100%"
/>
<image texture="encyclopedia/frames/wide/bottom-corner.png"
size="0 100%-32 32 100%"
/>
</sprite>
<sprite name="MediumOrnateFrame">
<!-- edges -->
<image texture="encyclopedia/frames/medium/horizontal-edge.png"
texture_size="0 0 128 16"
size="16 100%-16 100%-16 100%"
/>
<image texture="encyclopedia/frames/medium/vertical-edge.png"
texture_size="16 128 0 0"
size="100%-16 16 100% 100%"
/>
<image texture="encyclopedia/frames/medium/vertical-edge.png"
texture_size="0 0 16 128"
size="0 16 16 100%-16"
/>
<image texture="encyclopedia/frames/medium/horizontal-edge.png"
texture_size="0 16 128 0"
size="16 0 100%-16 16"
/>
<!-- corners -->
<image texture="encyclopedia/frames/medium/corner.png"
texture_size="0 16 16 0"
size="0 0 16 16"
/>
<image texture="encyclopedia/frames/medium/corner.png"
texture_size="16 16 0 0"
size="100%-16 0 100% 16"
/>
<image texture="encyclopedia/frames/medium/corner.png"
texture_size="16 0 0 16"
size="100%-16 100%-16 100% 100%"
/>
<image texture="encyclopedia/frames/medium/corner.png"
size="0 100%-16 16 100%"
/>
</sprite>
<sprite name="TextOrnament">
<!-- overlay -->
<effect add_color="mattbrown"/>
<!-- edges -->
<image backcolor="mattbrown" size="58 100%-2 100%-58 100%"/>
<image backcolor="mattbrown" size="58 0 100%-58 2"/>
<!-- decorations -->
<image texture="encyclopedia/ornament_deco_bottom.png"
size="100%-64 100%-19 100% 100%+13"
/>
<image texture="encyclopedia/ornament_deco_bottom.png"
size="0 100%-19 64 100%+13"
texture_size="64 0 0 32"
/>
<image texture="encyclopedia/ornament_deco_top.png"
size="4 -21 68 11"
texture_size="64 0 0 32"
/>
<image texture="encyclopedia/ornament_deco_top.png"
size="100%-68 -21 100%-4 11"
/>
</sprite>
<!--
==========================================
SCROLLBARS
==========================================
-->
<sprite name="BrownScrollBack">
<image texture="encyclopedia/scrollbar/brown-scrollback.png"
size="50%-4 -20 50%+4 100%+20"
/>
</sprite>
<sprite name="BrownScrollSlider">
<image texture=