diff --git a/binaries/data/mods/public/maps/scenario.rnc b/binaries/data/mods/public/maps/scenario.rnc index f4abc6c8f5..dd5f6b9ef4 100644 --- a/binaries/data/mods/public/maps/scenario.rnc +++ b/binaries/data/mods/public/maps/scenario.rnc @@ -103,6 +103,11 @@ Scenario = element Scenario { attribute group { xsd:positiveInteger }, attribute group2 { xsd:positiveInteger }? }? & + element Garrison { + element GarrisonedEntity { + attribute uid { xsd:positiveInteger } & + } & + } & element Actor { attribute seed { xsd:integer } }? diff --git a/binaries/data/mods/public/maps/scenario.rng b/binaries/data/mods/public/maps/scenario.rng index 947f019b14..4d80f3a9be 100644 --- a/binaries/data/mods/public/maps/scenario.rng +++ b/binaries/data/mods/public/maps/scenario.rng @@ -256,6 +256,17 @@ + + + + + + + + + + + diff --git a/binaries/data/mods/public/maps/skirmishes/Sicilia_Nomad.xml b/binaries/data/mods/public/maps/skirmishes/Sicilia_Nomad.xml index 0c3e92a81e..5cc8f25cbf 100644 --- a/binaries/data/mods/public/maps/skirmishes/Sicilia_Nomad.xml +++ b/binaries/data/mods/public/maps/skirmishes/Sicilia_Nomad.xml @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bc402fc30beea8e2aaf1c3ab1c3d94edbb4e6690623d4d2566fbc320f7a9cc47 -size 519678 +oid sha256:b7c9e45798b8cff82e56a25c3860e7764cb2ae702cd81e8913f33cd50382f867 +size 520558 diff --git a/binaries/data/mods/public/simulation/components/GarrisonHolder.js b/binaries/data/mods/public/simulation/components/GarrisonHolder.js index ef587b4586..7586b90569 100644 --- a/binaries/data/mods/public/simulation/components/GarrisonHolder.js +++ b/binaries/data/mods/public/simulation/components/GarrisonHolder.js @@ -690,6 +690,16 @@ GarrisonHolder.prototype.IsEjectable = function(entity) return MatchesClassList(entityClasses, ejectableClasses); }; +/** + * Sets the intitGarrison to the specified entities. Used by the mapreader. + * + * @param {number[]} entities - The entity IDs to garrison on init. + */ +GarrisonHolder.prototype.SetInitGarrison = function(entities) +{ + this.initGarrison = clone(entities); +}; + /** * Initialise the garrisoned units. */ diff --git a/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js b/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js index b32488a15e..5ef3827feb 100644 --- a/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js +++ b/binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js @@ -1,5 +1,3 @@ -Engine.RegisterInterface("GarrisonHolder"); - /** * Message of the form { "added": number[], "removed": number[] } * sent from the GarrisonHolder component to the current entity whenever the garrisoned units change. diff --git a/binaries/data/mods/public/simulation/helpers/Setup.js b/binaries/data/mods/public/simulation/helpers/Setup.js index 530b2900a6..ce5c49cf15 100644 --- a/binaries/data/mods/public/simulation/helpers/Setup.js +++ b/binaries/data/mods/public/simulation/helpers/Setup.js @@ -64,16 +64,6 @@ function LoadMapSettings(settings) if (settings.LockTeams && settings.LastManStanding) warn("Last man standing is only available in games with unlocked teams!"); - if (settings.Garrison) - for (let holder in settings.Garrison) - { - let cmpGarrisonHolder = Engine.QueryInterface(+holder, IID_GarrisonHolder); - if (!cmpGarrisonHolder) - warn("Map error in Setup.js: entity " + holder + " can not garrison units"); - else - cmpGarrisonHolder.initGarrison = settings.Garrison[holder]; - } - let cmpCeasefireManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_CeasefireManager); if (settings.Ceasefire) cmpCeasefireManager.StartCeasefire(settings.Ceasefire * 60 * 1000); diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp index 98bd89178b..df3abf3ab7 100644 --- a/source/graphics/MapReader.cpp +++ b/source/graphics/MapReader.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -41,6 +41,7 @@ #include "renderer/WaterManager.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpCinemaManager.h" +#include "simulation2/components/ICmpGarrisonHolder.h" #include "simulation2/components/ICmpObstruction.h" #include "simulation2/components/ICmpOwnership.h" #include "simulation2/components/ICmpPlayer.h" @@ -416,6 +417,7 @@ private: int el_tracks; int el_template, el_player; int el_position, el_orientation, el_obstruction; + int el_garrison; int el_actor; int at_x, at_y, at_z; int at_group, at_group2; @@ -465,6 +467,7 @@ void CXMLReader::Init(const VfsPath& xml_filename) EL(template); EL(player); EL(position); + EL(garrison); EL(orientation); EL(obstruction); EL(actor); @@ -946,6 +949,7 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time) CStrW TemplateName; int PlayerID = 0; + std::vector Garrison; CFixedVector3D Position; CFixedVector3D Orientation; long Seed = -1; @@ -994,6 +998,17 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time) ControlGroup = attrs.GetNamedItem(at_group).ToInt(); ControlGroup2 = attrs.GetNamedItem(at_group2).ToInt(); } + // + else if (element_name == el_garrison) + { + XMBElementList garrison = setting.GetChildNodes(); + Garrison.reserve(garrison.size()); + for (const XMBElement& garr_ent : garrison) + { + XMBAttributeList attrs = garr_ent.GetAttributes(); + Garrison.push_back(attrs.GetNamedItem(at_uid).ToInt()); + } + } // else if (element_name == el_actor) { @@ -1029,6 +1044,16 @@ int CXMLReader::ReadEntities(XMBElement parent, double end_time) if (cmpOwnership) cmpOwnership->SetOwner(PlayerID); + if (!Garrison.empty()) + { + CmpPtr cmpGarrisonHolder(sim, ent); + if (cmpGarrisonHolder) + cmpGarrisonHolder->SetInitEntities(Garrison); + else + LOGERROR("CXMLMapReader::ReadEntities() entity '%d' of player '%d' has no GarrisonHolder component and thus cannot garrison units.", ent, PlayerID); + Garrison.clear(); + } + CmpPtr cmpObstruction(sim, ent); if (cmpObstruction) { diff --git a/source/graphics/MapWriter.cpp b/source/graphics/MapWriter.cpp index fe2593b4b1..3eb35e04a8 100644 --- a/source/graphics/MapWriter.cpp +++ b/source/graphics/MapWriter.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -39,6 +39,7 @@ #include "renderer/WaterManager.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpCinemaManager.h" +#include "simulation2/components/ICmpGarrisonHolder.h" #include "simulation2/components/ICmpObstruction.h" #include "simulation2/components/ICmpOwnership.h" #include "simulation2/components/ICmpPosition.h" @@ -341,6 +342,19 @@ void CMapWriter::WriteXML(const VfsPath& filename, if (cmpOwnership) entityTag.Setting("Player", static_cast(cmpOwnership->GetOwner())); + CmpPtr cmpGarrisonHolder(sim, ent); + if (cmpGarrisonHolder) + { + XMLWriter_Element garrisonTag(xmlMapFile, "Garrison"); + std::vector garrison = cmpGarrisonHolder->GetEntities(); + for (const entity_id_t garr_ent_id : garrison) + { + XMLWriter_Element garrisonedEntityTag(xmlMapFile, "GarrisonedEntity"); + garrisonedEntityTag.Attribute("uid", static_cast(garr_ent_id)); + // ToDo: We can store turret position as well. + } + } + CmpPtr cmpPosition(sim, ent); if (cmpPosition) { diff --git a/source/simulation2/TypeList.h b/source/simulation2/TypeList.h index eff05ed289..6f157b8314 100644 --- a/source/simulation2/TypeList.h +++ b/source/simulation2/TypeList.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -98,6 +98,9 @@ COMPONENT(FoggingScripted) INTERFACE(Footprint) COMPONENT(Footprint) +INTERFACE(GarrisonHolder) +COMPONENT(GarrisonHolderScripted) + INTERFACE(GuiInterface) COMPONENT(GuiInterfaceScripted) diff --git a/source/simulation2/components/ICmpGarrisonHolder.cpp b/source/simulation2/components/ICmpGarrisonHolder.cpp new file mode 100644 index 0000000000..de3cbc1117 --- /dev/null +++ b/source/simulation2/components/ICmpGarrisonHolder.cpp @@ -0,0 +1,44 @@ +/* Copyright (C) 2020 Wildfire Games. +* This file is part of 0 A.D. +* +* 0 A.D. is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 of the License, or +* (at your option) any later version. +* +* 0 A.D. is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with 0 A.D. If not, see . +*/ + +#include "precompiled.h" + +#include "ICmpGarrisonHolder.h" + +#include "simulation2/scripting/ScriptComponent.h" +#include "simulation2/system/InterfaceScripted.h" + +BEGIN_INTERFACE_WRAPPER(GarrisonHolder) +END_INTERFACE_WRAPPER(GarrisonHolder) + +class CCmpGarrisonHolderScripted : public ICmpGarrisonHolder +{ +public: + DEFAULT_SCRIPT_WRAPPER(GarrisonHolderScripted) + + virtual std::vector GetEntities() const + { + return m_Script.Call >("GetEntities"); + } + + virtual void SetInitEntities(std::vector entities) + { + m_Script.CallVoid("SetInitGarrison", entities); + } +}; + +REGISTER_COMPONENT_SCRIPT_WRAPPER(GarrisonHolderScripted) diff --git a/source/simulation2/components/ICmpGarrisonHolder.h b/source/simulation2/components/ICmpGarrisonHolder.h new file mode 100644 index 0000000000..b89908f717 --- /dev/null +++ b/source/simulation2/components/ICmpGarrisonHolder.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2020 Wildfire Games. +* This file is part of 0 A.D. +* +* 0 A.D. is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 of the License, or +* (at your option) any later version. +* +* 0 A.D. is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with 0 A.D. If not, see . +*/ + +#ifndef INCLUDED_ICMPGARRISONHOLDER +#define INCLUDED_ICMPGARRISONHOLDER + +#include "simulation2/system/Interface.h" + +#include + +class ICmpGarrisonHolder : public IComponent +{ +public: + virtual std::vector GetEntities() const = 0; + + virtual void SetInitEntities(const std::vector entities) = 0; + + DECLARE_INTERFACE_TYPE(GarrisonHolder) +}; + +#endif // INCLUDED_ICMPGARRISONHOLDER