summaryrefslogtreecommitdiffhomepage
path: root/Stars45/MissionTemplate.cpp
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2022-04-01 21:23:39 +0200
committerAki <please@ignore.pl>2022-04-01 21:23:39 +0200
commit3c487c5cd69c53d6fea948643c0a76df03516605 (patch)
tree72730c7b8b26a5ef8fc9a987ec4c16129efd5aac /Stars45/MissionTemplate.cpp
parent8f353abd0bfe18baddd8a8250ab7c4f2d1c83a6e (diff)
downloadstarshatter-3c487c5cd69c53d6fea948643c0a76df03516605.zip
starshatter-3c487c5cd69c53d6fea948643c0a76df03516605.tar.gz
starshatter-3c487c5cd69c53d6fea948643c0a76df03516605.tar.bz2
Moved Stars45 to StarsEx
Diffstat (limited to 'Stars45/MissionTemplate.cpp')
-rw-r--r--Stars45/MissionTemplate.cpp844
1 files changed, 0 insertions, 844 deletions
diff --git a/Stars45/MissionTemplate.cpp b/Stars45/MissionTemplate.cpp
deleted file mode 100644
index 54efbe6..0000000
--- a/Stars45/MissionTemplate.cpp
+++ /dev/null
@@ -1,844 +0,0 @@
-/* Starshatter: The Open Source Project
- Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
- Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
- Copyright (c) 1997-2006, Destroyer Studios LLC.
-
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Mission Template classes
-*/
-
-#include "MissionTemplate.h"
-#include "MissionEvent.h"
-#include "StarSystem.h"
-#include "Galaxy.h"
-#include "Callsign.h"
-#include "Campaign.h"
-#include "Combatant.h"
-#include "CombatGroup.h"
-#include "CombatUnit.h"
-#include "Starshatter.h"
-#include "Ship.h"
-#include "ShipDesign.h"
-#include "Element.h"
-#include "Instruction.h"
-#include "Random.h"
-
-#include "Game.h"
-#include "DataLoader.h"
-#include "ParseUtil.h"
-
-// +--------------------------------------------------------------------+
-
-MissionTemplate::MissionTemplate(int identity, const char* fname, const char* pname)
-: Mission(identity, fname, pname)
-{
-}
-
-MissionTemplate::~MissionTemplate()
-{
- callsigns.destroy();
- aliases.destroy();
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MissionTemplate::AddElement(MissionElement* elem)
-{
- if (elem) {
- elements.append(elem);
- aliases.append(new MissionAlias(elem->Name(), elem));
- }
-}
-
-bool
-MissionTemplate::MapElement(MissionElement* elem)
-{
- bool result = false;
-
- if (elem && !elem->GetCombatUnit()) {
- if (elem->IsDropship()) {
- Text callsign = MapCallsign(elem->Name(), elem->GetIFF());
-
- if (callsign.length())
- elem->SetName(callsign);
- }
-
- ListIter<Instruction> obj = elem->Objectives();
- while (++obj) {
- Instruction* i = obj.value();
- if (strlen(i->TargetName())) {
- // find a callsign, only if one already exists:
- Text callsign = MapCallsign(i->TargetName(), -1);
- if (callsign.length())
- i->SetTarget(callsign.data());
- }
- }
-
- ListIter<Instruction> nav = elem->NavList();
- while (++nav) {
- Instruction* i = nav.value();
- if (strlen(i->TargetName())) {
- // find a callsign, only if one already exists:
- Text callsign = MapCallsign(i->TargetName(), -1);
- if (callsign.length())
- i->SetTarget(callsign.data());
- }
- }
-
- CombatGroup* g = FindCombatGroup(elem->GetIFF(), elem->GetDesign());
-
- if (g) {
- CombatUnit* u = g->GetNextUnit();
-
- if (u) {
- elem->SetCombatGroup(g);
- elem->SetCombatUnit(u);
- }
- }
-
- if (elem->GetCombatUnit()) {
- MissionElement* cmdr = FindElement(elem->Commander());
- if (cmdr)
- elem->SetCommander(cmdr->Name());
-
- MissionElement* sqdr = FindElement(elem->Squadron());
- if (sqdr)
- elem->SetSquadron(sqdr->Name());
-
- if (!elem->IsDropship()) {
- aliases.append(new MissionAlias(elem->Name(), elem));
- elem->SetName(elem->GetCombatUnit()->Name());
- }
-
- result = true;
- }
- }
-
- return result;
-}
-
-Text
-MissionTemplate::MapShip(Text name)
-{
- Text result = name;
- int len = name.length();
-
- if (len) {
- MissionElement* elem = 0;
-
- // single ship from an element (e.g. "Alpha 1")?
- if (isdigit(name[len-1]) && isspace(name[len-2])) {
- Text elem_name = name.substring(0, len-2);
-
- elem = FindElement(elem_name);
- if (elem)
- result = elem->Name() + name.substring(len-2, 2);
- }
-
- // full element name
- // (also used to try again if single-ship search fails)
- if (!elem) {
- elem = FindElement(name);
-
- if (elem)
- result = elem->Name();
- }
- }
-
- return result;
-}
-
-// +--------------------------------------------------------------------+
-
-bool
-MissionTemplate::MapEvent(MissionEvent* event)
-{
- bool result = false;
-
- if (event) {
- event->event_ship = MapShip(event->event_ship);
- event->event_source = MapShip(event->event_source);
- event->event_target = MapShip(event->event_target);
- event->trigger_ship = MapShip(event->trigger_ship);
- event->trigger_target = MapShip(event->trigger_target);
-
- result = true;
- }
-
- return result;
-}
-
-// +--------------------------------------------------------------------+
-
-Text
-MissionTemplate::MapCallsign(const char* name, int iff)
-{
- for (int i = 0; i < callsigns.size(); i++) {
- if (callsigns[i]->Name() == name)
- return callsigns[i]->Callsign();
- }
-
- if (iff >= 0) {
- const char* callsign = Callsign::GetCallsign(iff);
- MissionCallsign* mc = new MissionCallsign(callsign, name);
- callsigns.append(mc);
-
- return mc->Callsign();
- }
-
- return name;
-}
-
-// +--------------------------------------------------------------------+
-
-static void SelectCombatGroups(CombatGroup* g, const ShipDesign* d, List<CombatGroup>& list)
-{
- if (g->IntelLevel() <= Intel::RESERVE)
- return;
-
- if (g->GetUnits().size() > 0) {
- for (int i = 0; i < g->GetUnits().size(); i++) {
- CombatUnit* u = g->GetUnits().at(i);
- if (u->GetDesign() == d && u->Count() - u->DeadCount() > 0) {
- list.append(g);
- }
- }
- }
-
- ListIter<CombatGroup> subgroup = g->GetComponents();
- while (++subgroup)
- SelectCombatGroups(subgroup.value(), d, list);
-}
-
-CombatGroup*
-MissionTemplate::FindCombatGroup(int iff, const ShipDesign* d)
-{
- CombatGroup* result = 0;
- Campaign* campaign = Campaign::GetCampaign();
- List<CombatGroup> group_list;
- static int combat_group_index = 0;
-
- if (campaign) {
- ListIter<Combatant> combatant = campaign->GetCombatants();
- while (++combatant) {
- if (combatant->GetIFF() == iff) {
- ::SelectCombatGroups(combatant->GetForce(), d, group_list);
- }
- }
-
- if (group_list.size() > 0)
- result = group_list[combat_group_index++ % group_list.size()];
- }
-
- return result;
-}
-
-// +--------------------------------------------------------------------+
-
-MissionElement*
-MissionTemplate::FindElement(const char* n)
-{
- Text name = n;
-
- ListIter<MissionCallsign> c_iter = callsigns;
- while (++c_iter) {
- MissionCallsign* c = c_iter.value();
- if (c->Name() == name) {
- name = c->Callsign();
- break;
- }
- }
-
- ListIter<MissionAlias> a_iter = aliases;
- while (++a_iter) {
- MissionAlias* a = a_iter.value();
- if (a->Name() == name)
- return a->Element();
- }
-
- ListIter<MissionElement> e_iter = elements;
- while (++e_iter) {
- MissionElement* elem = e_iter.value();
- if (elem->Name() == name)
- return elem;
- }
-
- return 0;
-}
-
-// +--------------------------------------------------------------------+
-
-bool
-MissionTemplate::Load(const char* fname, const char* pname)
-{
- ok = false;
-
- if (fname)
- strcpy_s(filename, fname);
-
- if (pname)
- strcpy_s(path, pname);
-
- if (!filename[0]) {
- Print("\nCan't Load Mission Template, script unspecified.\n");
- return ok;
- }
-
- Print("\nLoad Mission Template: '%s'\n", filename);
-
- int max_ships = (int) 1e6;
-
- DataLoader* loader = DataLoader::GetLoader();
- bool old_fs = loader->IsFileSystemEnabled();
- BYTE* block = 0;
-
- loader->UseFileSystem(true);
- loader->SetDataPath(path);
- loader->LoadBuffer(filename, block, true);
- loader->SetDataPath(0);
- loader->UseFileSystem(old_fs);
-
- Parser parser(new BlockReader((const char*) block));
-
- Term* term = parser.ParseTerm();
-
- if (!term) {
- Print("ERROR: could not parse '%s'\n", filename);
- return ok;
- }
- else {
- TermText* file_type = term->isText();
- if (!file_type || file_type->value() != "MISSION_TEMPLATE") {
- Print("ERROR: invalid MISSION TEMPLATE file '%s'\n", filename);
- term->print(10);
- return ok;
- }
- }
-
- ok = true;
-
- char target_name[256];
- char ward_name[256];
-
- target_name[0] = 0;
- ward_name[0] = 0;
-
- do {
- delete term; term = 0;
- term = parser.ParseTerm();
-
- if (term) {
- TermDef* def = term->isDef();
- if (def) {
- Text defname = def->name()->value();
-
- if (defname == "name")
- GetDefText(name, def, filename);
-
- else if (defname == "type") {
- char typestr[64];
- GetDefText(typestr, def, filename);
- type = TypeFromName(typestr);
- }
-
- else if (defname == "system") {
- char sysname[64];
- GetDefText(sysname, def, filename);
-
- Campaign* campaign = Campaign::GetCampaign();
-
- if (campaign) {
- Galaxy* galaxy = Galaxy::GetInstance();
-
- if (galaxy) {
- star_system = galaxy->GetSystem(sysname);
- }
- }
- }
-
- else if (defname == "degrees")
- GetDefBool(degrees, def, filename);
-
- else if (defname == "region")
- GetDefText(region, def, filename);
-
- else if (defname == "objective")
- GetDefText(objective, def, filename);
-
- else if (defname == "sitrep")
- GetDefText(sitrep, def, filename);
-
- else if (defname == "start")
- GetDefTime(start, def, filename);
-
- else if (defname == "team")
- GetDefNumber(team, def, filename);
-
- else if (defname == "target")
- GetDefText(target_name, def, filename);
-
- else if (defname == "ward")
- GetDefText(ward_name, def, filename);
-
- else if ((defname == "alias")) {
- if (!def->term() || !def->term()->isStruct()) {
- Print("WARNING: alias struct missing in '%s'\n", filename);
- ok = false;
- }
- else {
- TermStruct* val = def->term()->isStruct();
- ParseAlias(val);
- }
- }
-
- else if ((defname == "callsign")) {
- if (!def->term() || !def->term()->isStruct()) {
- Print("WARNING: callsign struct missing in '%s'\n", filename);
- ok = false;
- }
- else {
- TermStruct* val = def->term()->isStruct();
- ParseCallsign(val);
- }
- }
-
- else if (defname == "optional") {
- if (!def->term() || !def->term()->isStruct()) {
- Print("WARNING: optional group struct missing in '%s'\n", filename);
- ok = false;
- }
- else {
- TermStruct* val = def->term()->isStruct();
- ParseOptional(val);
- }
- }
-
- else if (defname == "element") {
- if (!def->term() || !def->term()->isStruct()) {
- Print("WARNING: element struct missing in '%s'\n", filename);
- ok = false;
- }
- else {
- TermStruct* val = def->term()->isStruct();
- MissionElement* elem = ParseElement(val);
- if (MapElement(elem)) {
- AddElement(elem);
- }
- else {
- Print("WARNING: failed to map element %s '%s' in '%s'\n",
- elem->GetDesign() ? elem->GetDesign()->name : "NO DSN",
- elem->Name().data(),
- filename);
- val->print();
- Print("\n");
- delete elem;
- ok = false;
- }
- }
- }
-
- else if (defname == "event") {
- if (!def->term() || !def->term()->isStruct()) {
- Print("WARNING: event struct missing in '%s'\n", filename);
- ok = false;
- }
- else {
- TermStruct* val = def->term()->isStruct();
- MissionEvent* event = ParseEvent(val);
-
- if (MapEvent(event))
- AddEvent(event);
- }
- }
- } // def
- } // term
- }
- while (term);
-
- loader->ReleaseBuffer(block);
-
- if (ok) {
- CheckObjectives();
-
- if (target_name[0])
- target = FindElement(target_name);
-
- if (ward_name[0])
- ward = FindElement(ward_name);
-
- Print("Mission Template Loaded.\n\n");
- }
-
- return ok;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MissionTemplate::ParseAlias(TermStruct* val)
-{
- Text name;
- Text design;
- Text code;
- Text elem_name;
- int iff = -1;
- int player = 0;
- RLoc* rloc = 0;
- bool use_loc = false;
- Vec3 loc;
-
- for (int i = 0; i < val->elements()->size(); i++) {
- TermDef* pdef = val->elements()->at(i)->isDef();
- if (pdef) {
- Text defname = pdef->name()->value();
- defname.setSensitive(false);
-
- if (defname == "name")
- GetDefText(name, pdef, filename);
-
- else if (defname == "elem")
- GetDefText(elem_name, pdef, filename);
-
- else if (defname == "code")
- GetDefText(code, pdef, filename);
-
- else if (defname == "design")
- GetDefText(design, pdef, filename);
-
- else if (defname == "iff")
- GetDefNumber(iff, pdef, filename);
-
- else if (defname == "loc") {
- loc;
- GetDefVec(loc, pdef, filename);
- use_loc = true;
- }
-
- else if (defname == "rloc") {
- if (pdef->term()->isStruct()) {
- rloc = ParseRLoc(pdef->term()->isStruct());
- }
- }
-
- else if (defname == "player") {
- GetDefNumber(player, pdef, filename);
-
- if (player && !code.length())
- code = "player";
- }
- }
- }
-
- MissionElement* elem = 0;
-
- // now find element and create alias:
- if (name.length()) {
- for (int i = 0; i < aliases.size(); i++)
- if (aliases[i]->Name() == name)
- return;
-
- // by element name?
- if (elem_name.length()) {
- elem = FindElement(elem_name);
- }
-
- // by special code?
- else if (code.length()) {
- code.toLower();
- Campaign* campaign = Campaign::GetCampaign();
-
- if (code == "player") {
- for (int i = 0; !elem && i < elements.size(); i++) {
- MissionElement* e = elements[i];
- if (e->Player() > 0) {
- elem = e;
- }
- }
- }
-
- else if (campaign && code == "player_carrier") {
- CombatGroup* player_group = campaign->GetPlayerGroup();
-
- if (player_group) {
- CombatGroup* carrier = player_group->FindCarrier();
-
- if (carrier) {
- elem = FindElement(carrier->Name());
- }
- }
- }
-
- else if (campaign && code == "player_squadron") {
- CombatGroup* player_group = player_squadron;
-
- if (!player_group)
- player_group = campaign->GetPlayerGroup();
-
- if (player_group &&
- (player_group->Type() == CombatGroup::INTERCEPT_SQUADRON ||
- player_group->Type() == CombatGroup::FIGHTER_SQUADRON ||
- player_group->Type() == CombatGroup::ATTACK_SQUADRON)) {
- elem = FindElement(player_group->Name());
- }
- }
-
- else if (campaign && code == "strike_target") {
- CombatGroup* player_group = campaign->GetPlayerGroup();
-
- if (player_group) {
- CombatGroup* strike_target = campaign->FindStrikeTarget(player_group->GetIFF(), player_group);
-
- if (strike_target) {
- elem = FindElement(strike_target->Name());
- }
- }
- }
- }
-
- // by design and team?
- else {
- MissionElement* first_match = 0;
-
- for (int i = 0; !elem && i < elements.size(); i++) {
- MissionElement* e = elements[i];
- if (e->GetIFF() == iff && design == e->GetDesign()->name) {
- // do we already have an alias for this element?
- bool found = false;
- for (int a = 0; !found && a < aliases.size(); a++)
- if (aliases[a]->Element() == e)
- found = true;
-
- if (!found)
- elem = e;
-
- else if (!first_match)
- first_match = e;
- }
- }
-
- if (first_match && !elem)
- elem = first_match;
- }
-
- if (elem) {
- if (rloc) elem->SetRLoc(*rloc);
- else if (use_loc) elem->SetLocation(loc);
-
- delete rloc;
-
- aliases.append(new MissionAlias(name, elem));
- }
- else {
- ::Print("WARNING: Could not resolve mission alias '%s'\n", (const char*) name);
- ok = false;
- }
- }
-
- if (!elem || !ok) return;
-
- // re-parse the struct, dealing with stuff
- // that needs to be attached to the element:
- for (int i = 0; i < val->elements()->size(); i++) {
- TermDef* pdef = val->elements()->at(i)->isDef();
- if (pdef) {
- Text defname = pdef->name()->value();
- defname.setSensitive(false);
-
- if (defname == "objective") {
- if (!pdef->term() || !pdef->term()->isStruct()) {
- Print("WARNING: order struct missing for element '%s' in '%s'\n", (const char*) elem->Name(), filename);
- ok = false;
- }
- else {
- TermStruct* val = pdef->term()->isStruct();
- Instruction* obj = ParseInstruction(val, elem);
- elem->Objectives().append(obj);
- }
- }
-
- else if (defname == "instr") {
- Text* obj = new Text;
- if (GetDefText(*obj, pdef, filename))
- elem->Instructions().append(obj);
- }
-
- else if (defname == "order" || defname == "navpt") {
- if (!pdef->term() || !pdef->term()->isStruct()) {
- Print("WARNING: order struct missing for element '%s' in '%s'\n", (const char*) elem->Name(), filename);
- ok = false;
- }
- else {
- TermStruct* val = pdef->term()->isStruct();
- Instruction* npt = ParseInstruction(val, elem);
- elem->NavList().append(npt);
- }
- }
-
- else if (defname == "loadout") {
- if (!pdef->term() || !pdef->term()->isStruct()) {
- Print("WARNING: loadout struct missing for element '%s' in '%s'\n", (const char*) elem->Name(), filename);
- ok = false;
- }
- else {
- TermStruct* val = pdef->term()->isStruct();
- ParseLoadout(val, elem);
- }
- }
- }
- }
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MissionTemplate::ParseCallsign(TermStruct* val)
-{
- Text name;
- int iff = -1;
-
- for (int i = 0; i < val->elements()->size(); i++) {
- TermDef* pdef = val->elements()->at(i)->isDef();
- if (pdef) {
- Text defname = pdef->name()->value();
- defname.setSensitive(false);
-
- if (defname == "name")
- GetDefText(name, pdef, filename);
-
- else if (defname == "iff")
- GetDefNumber(iff, pdef, filename);
- }
- }
-
- if (name.length() > 0 && iff >= 0)
- MapCallsign(name, iff);
-}
-
-// +--------------------------------------------------------------------+
-
-bool
-MissionTemplate::ParseOptional(TermStruct* val)
-{
- int n = 0;
- int min = 0;
- int max = 1000;
- int skip = 0;
- int total = val->elements()->size();
-
- for (int i = 0; i < val->elements()->size(); i++) {
- TermDef* pdef = val->elements()->at(i)->isDef();
- if (pdef) {
- Text defname = pdef->name()->value();
- defname.setSensitive(false);
-
- if (defname == "min") {
- GetDefNumber(min, pdef, filename);
- total--;
- }
-
- else if (defname == "max") {
- GetDefNumber(max, pdef, filename);
- total--;
- }
-
-
- else if ((defname == "optional")) {
- bool select;
-
- if (n >= max)
- select = false;
- else if (total - n - skip <= min)
- select = true;
- else
- select = RandomChance();
-
- if (select) {
- if (!pdef->term() || !pdef->term()->isStruct()) {
- Print("WARNING: optional group struct missing in '%s'\n", filename);
- ok = false;
- skip++;
- }
- else {
- TermStruct* val = pdef->term()->isStruct();
- if (ParseOptional(val))
- n++;
- else
- skip++;
- }
- }
- else {
- skip++;
- }
- }
-
- else if (defname == "element") {
- bool select;
-
- if (n >= max)
- select = false;
- else if (total - n - skip <= min)
- select = true;
- else
- select = RandomChance();
-
- if (select) {
- if (!pdef->term() || !pdef->term()->isStruct()) {
- Print("WARNING: element struct missing in '%s'\n", filename);
- ok = false;
- skip++;
- }
- else {
- TermStruct* es = pdef->term()->isStruct();
- MissionElement* elem = ParseElement(es);
- if (MapElement(elem)) {
- AddElement(elem);
- n++;
- }
- else {
- delete elem;
- skip++;
- }
- }
- }
- else {
- skip++;
- }
- }
- }
- }
-
- return n > 0 && n >= min;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MissionTemplate::CheckObjectives()
-{
- ListIter<MissionElement> iter = elements;
- while (++iter) {
- MissionElement* elem = iter.value();
-
- ListIter<Instruction> obj = elem->Objectives();
- while (++obj) {
- Instruction* o = obj.value();
- Text tgt = o->TargetName();
-
- MissionElement* tgt_elem = 0;
-
- if (tgt.length()) {
- tgt_elem = FindElement(tgt);
-
- if (!tgt_elem)
- obj.removeItem();
- else
- o->SetTarget(tgt_elem->Name());
- }
- }
- }
-}