wghost81 Posted January 28, 2014 Share Posted January 28, 2014 Drakous79, interesting. I will try this. Link to comment Share on other sites More sharing options...
wghost81 Posted January 28, 2014 Share Posted January 28, 2014 Renaming tfc didn't worked. May be the problem is in some others packages map package is referring to, or may be it's in PersistentCookerData, I don't know. Link to comment Share on other sites More sharing options...
wghost81 Posted February 1, 2014 Share Posted February 1, 2014 (edited) Tried to add a new pods on maps dynamically, but failed. :sad: As I suspected, XComAlienPodManager does affects XComAlienPod map object. In fact, it initializes them before any actual deployment begins. I got crazy with battle init process and can't claim I understand it all, but that's what I found out so far. XGBattle has two states (amongst many others): Initing and Loading. First is used for creating a battle and second for loading a battle from save. Both states call for InitPlayers function which initializes all players. XGBattle_SP extends XGBattle for single player game. InitPlayers function spawns XComAlienPodManager class and calls for InitPods pods function, which iterates through all XComAlienPod objects and initializes them. If I understood correctly, it is done before Overmind initialization. XGAIPlayer spawns an Overmind, after AI player is created, and Overmind spawns XGDeployAI to perform actual deployment. I tried to spawn a new XComAlienPod Actor at different initialization states, but failed. My code works somehow, but no aliens are actually spawned at new point. In fact, no aliens are spawned at all. Either I'm doing everything wrong, or it has something to do with pod meshes, which are defined for map pods in map files directly and for which I use default values. My next step will be to understand how TheWorld.PersistentLevel object works and try to add new pods into maps directly. But it will be difficult. Now, some more info on map objects. Any scripted class which has "placeable" keyword can be placed on the map. That is how all pods, meld containers, radar arrays, salvage items, etc are placed on maps. XComAlienPod is a base class for all alien pods. It has three child classes: XComAlienPod_Abduction, XComAlienPod_Hunter and XComAlienPod_Terror. An example of XComAlienPod map object: 0x000037AF (14255): XComAlienPod'TheWorld.PersistentLevel.XComAlienPod_2' TypeRef: 0xFFFFFF40 -> XComAlienPod ParentClassRef: 0x00000000 -> OwnerRef: 0x00000770 -> PersistentLevel NameIdx: 0x00000E74 (Index) 0x00000003 (Numeric) -> XComAlienPod_2 ArchetypeRef: 0x00000000 -> ObjectFlagsH: 0x00000000 ObjectFlagsL: 0x02070001 0x00000001: Transactional 0x00010000: LoadForClient 0x00020000: LoadForServer 0x00040000: LoadForEdit 0x02000000: HasStack SerialSize: 0x00000166 (358) SerialOffset: 0x01D12B90 ExportFlags: 0x00000000 NetObjectCount: 0 GUID: 00000000000000000000000000000000 Unknown1: 0x00000000 UObject: PrevObjRef = 0xFFFFFF40 -> XComAlienPod Can't deserialize stack: skipping! UDefaultPropertiesList: UDefaultProperty: NameIdx: 0x000009F8 (Index) 0x00000000 (Numeric) -> PodIndex TypeIdx: 0x000006BA (Index) 0x00000000 (Numeric) -> IntProperty PropertySize: 0x00000004 ArrayIdx: 0x00000000 Integer: 0x00000002 = 2 UDefaultProperty: NameIdx: 0x0000073A (Index) 0x00000000 (Numeric) -> LoopType TypeIdx: 0x000002D7 (Index) 0x00000000 (Numeric) -> ByteProperty PropertySize: 0x00000008 ArrayIdx: 0x00000000 InnerNameIdx: 0x000004F7 (Index) 0x00000000 (Numeric) -> EPathLoopType Name: 0x000009BD (Index) 0x00000000 (Numeric) = PATH_TYPE_FORWARD_BACKWARD_LOOP UDefaultProperty: NameIdx: 0x000006FC (Index) 0x00000000 (Numeric) -> LightEnvironment TypeIdx: 0x000008FC (Index) 0x00000000 (Numeric) -> ObjectProperty PropertySize: 0x00000004 ArrayIdx: 0x00000000 Object: 0x000003D6 = DynamicLightEnvironmentComponent_3538 UDefaultProperty: NameIdx: 0x000008F2 (Index) 0x00000000 (Numeric) -> NumAliens_Min TypeIdx: 0x000006BA (Index) 0x00000000 (Numeric) -> IntProperty PropertySize: 0x00000004 ArrayIdx: 0x00000000 Integer: 0x00000003 = 3 UDefaultProperty: NameIdx: 0x000008F1 (Index) 0x00000000 (Numeric) -> NumAliens_Max TypeIdx: 0x000006BA (Index) 0x00000000 (Numeric) -> IntProperty PropertySize: 0x00000004 ArrayIdx: 0x00000000 Integer: 0x00000003 = 3 UDefaultProperty: NameIdx: 0x000009F9 (Index) 0x00000000 (Numeric) -> PodMesh TypeIdx: 0x000008FC (Index) 0x00000000 (Numeric) -> ObjectProperty PropertySize: 0x00000004 ArrayIdx: 0x00000000 Object: 0x00002FDD = StaticMeshComponent_371 UDefaultProperty: NameIdx: 0x000009BF (Index) 0x00000000 (Numeric) -> PathNodes TypeIdx: 0x0000017F (Index) 0x00000000 (Numeric) -> ArrayProperty PropertySize: 0x00000010 ArrayIdx: 0x00000000 NumElements = 0x00000003 = 3 ArrayInnerType = None PathNodes[0]: Unsafe guess: It's an Integer: 0x00003799 = 14233 or a Reference: 0x00003799 -> XComAlienPathNode_0 PathNodes[1]: Unsafe guess: It's an Integer: 0x000037A5 = 14245 or a Reference: 0x000037A5 -> XComAlienPathNode_2 PathNodes[2]: Unsafe guess: It's an Integer: 0x0000379A = 14234 or a Reference: 0x0000379A -> XComAlienPathNode_1 UDefaultProperty: NameIdx: 0x00000309 (Index) 0x00000000 (Numeric) -> CenterpieceMesh TypeIdx: 0x000008FC (Index) 0x00000000 (Numeric) -> ObjectProperty PropertySize: 0x00000004 ArrayIdx: 0x00000000 Object: 0x00002FDE = StaticMeshComponent_372 UDefaultProperty: NameIdx: 0x0000071A (Index) 0x00000000 (Numeric) -> Location TypeIdx: 0x00000C54 (Index) 0x00000000 (Numeric) -> StructProperty PropertySize: 0x0000000C ArrayIdx: 0x00000000 InnerNameIdx: 0x00000E19 (Index) 0x00000000 (Numeric) -> Vector Vector (X, Y, Z) = (0xC4164382, 0xC3D60B27, 0x43420622) = (-601.055, -428.087, 194.024) UDefaultProperty: NameIdx: 0x00000D1B (Index) 0x00000000 (Numeric) -> Tag TypeIdx: 0x000008D1 (Index) 0x00000000 (Numeric) -> NameProperty PropertySize: 0x00000008 ArrayIdx: 0x00000000 Name: 0x00000E74 (Index) 0x00000000 (Numeric) = XComAlienPod UDefaultProperty: NameIdx: 0x000008EA (Index) 0x00000000 (Numeric) -> None Stream relative position (debug info): 0x00000166 (358) Typically, map pods contain location data, patrol path data, meshes data. Special mission pods can force alien type via ForceAlienType (boolean) and AlienType variables. XComSpawnPoint class is used to mark positions of XCOM soldiers, civilians and dynamic aliens. XCOM soldiers and civilians use base XComSpawnPoint class and aliens use XComSpawnPoint_Alien class, which extends XComSpawnPoint class. Spawn points contain location data mostly. Edited February 1, 2014 by wghost81 Link to comment Share on other sites More sharing options...
Amineri Posted February 1, 2014 Author Share Posted February 1, 2014 (edited) I tried to spawn a new XComAlienPod Actor at different initialization states, but failed. My code works somehow, but no aliens are actually spawned at new point. In fact, no aliens are spawned at all. Either I'm doing everything wrong, or it has something to do with pod meshes, which are defined for map pods in map files directly and for which I use default values. Basically all of the initialization of meshes and other art assets is controlled through XGBattleDesc :BuildAlienContentBuildAlienContentFromLoadoutDetermineAlienPawnContentGenerateAliensInitAlienLoadoutInfosMapAlienToPawnIn particular InitAlienLoadoutInfos loops through all of the pods and adds the pod members info to m_arrTeamLoadoutInfos[PlayerIndex].m_arrUnits m_arrTeamLoadoutInfos is accessed through the accessor function XGBattleDesc.GetTeamLoadoutInfo. However it is never invoked visibly in XComGame.upk, so I can only suppose that it is called from a native function. I'd had occasional problems with not loading pawn meshes for aliens with early versions of the larger pods mod, and had to modify the InitAlienLoadoutInfos function, so it does actually have functionality. InitAlienLoadoutInfos is called from XGBattle_SP.InitDescription. InitDescription is the 3rd line in XGBattle.state'Initing', so it gets called quite early. This is how meshes are loaded for aliens defined in the strategy game, at least. If aliens defined in the maps files have to have their assets cooked into the map, that would be strange and awkward, but I suppose it could be. Edited February 1, 2014 by Amineri Link to comment Share on other sites More sharing options...
Amineri Posted February 1, 2014 Author Share Posted February 1, 2014 Regarding class'XComAlienPod' : For the most part these are accessed from the map via commands such as : foreach WorldInfo.AllActors(class'XComAlienPod', kPod) { arrPods.AddItem(kPod); } However, it is possible to spawn new objects of this type. In XComAlienPodManager.ConvertPodType (which converts between specialist version such as XComAlienPod_Abduction) is the code : kClassName = 'XComAlienPod'; kNewPodType = class'XComAlienPod'; // End:0xE1 if(kSpawn.kSpawnLoc.IsA(kClassName)) { return false; } ++ m_nReplacedPods; kPod = XComAlienPod(Spawn(kNewPodType,,, kSpawn.kSpawnLoc.Location, kSpawn.kSpawnLoc.Rotation,, true)); kPod.SetData(kSpawn.kSpawnLoc); m_arrSpawnList[iSpawnIdx].kSpawnLoc = kPod; which spawns a new XComAlienPod of a particular type and then replaces the old version within the XComAlienPodManager.m_arrSpawnList. An even more interesting example of creating a brand new XComAlienPod dynamically is in XComAlienPodManager.CheckAlienCounts if((iCurrTotal < XComTacticalGRI(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kBattle.m_kDesc.m_kAlienInfo.iNumAliens) && arrPathPods.Length > 0) { iRand = class'XComEngine'.static.SyncRand(arrPathPods.Length, (string(Name) @ string(GetStateName())) @ string(GetFuncName())); kPod = Spawn(class'XComAlienPod',,, arrPathPods[iRand].Location, arrPathPods[iRand].Rotation,, true); kPod.SetData(arrPathPods[iRand], false); kPod.m_kPathOrigin = arrPathPods[iRand]; kPod.NumAliens = Min(2, XComTacticalGRI(class'Engine'.static.GetCurrentWorldInfo().GRI).m_kBattle.m_kDesc.m_kAlienInfo.iNumAliens - iCurrTotal); kPod.Init(); kPodList.AddItem(kPod); arrPathPods.Remove(iRand, 1); iCurrTotal += kPod.NumAliens; SetDynamicAI(kPod); // [Loop Continue] goto J0x897; } This is a loop that can add multiple new class'XComAlienPod' objects, which are stored into the out parameter dynamic array kPodList. CheckAlienCounts is called from XComAlienPodManager.SpawnAllPodAliens. Presumably it is designed to dynamically create additional XComAlienPods in order to support more aliens. Link to comment Share on other sites More sharing options...
wghost81 Posted February 2, 2014 Share Posted February 2, 2014 Amineri, yes, I used the exact same examples to spawn new pods, but failed. As far as I can tell, none of those examples are actually used in game. BTW, the last one seems to attempt to spawn dynamic patrols. Since most of those function use min and max alien per pod values, defined in map packages, I suspect they are used for creating debug missions. Otherwise larger pods wouldn't work. Link to comment Share on other sites More sharing options...
wghost81 Posted February 2, 2014 Share Posted February 2, 2014 (edited) Seems, I finally found something. :smile: I skipped all the checks in XGAIPlayer.CreateSquad to call SpawnAliensFromList for regular missions. I also changed number of aliens to 10 from 4. I started a new Impossible game and got 8 totally randomly placed and already activated sectoids. It's not what I need, but at least it's a start. Now I need to understand how it can be re-purposed to create fully-functional alien pods, controlled by XComAlienPodManager. Hope it can be done. Edited February 2, 2014 by wghost81 Link to comment Share on other sites More sharing options...
wghost81 Posted February 2, 2014 Share Posted February 2, 2014 (edited) Turns out I was doing a right thing from the beginning, but I was simply doing it wrong. :smile: Now, that's a brand new pod, which falls into pod manager "jurisdiction": http://i.imgur.com/1yyNxFw.jpg It acts just like normal pod, only problem is: it is placed at the world center. :smile: I used a "borrowed" variable to pass new pod location to Spawn function, but it didn't worked. May be because it was borrowed, I don't know. But I intend to find out. :smile: Edited February 2, 2014 by wghost81 Link to comment Share on other sites More sharing options...
wghost81 Posted February 2, 2014 Share Posted February 2, 2014 (edited) Here it is :smile: http://i.imgur.com/fGzXCxR.jpg Turns out, there are XComNoSpawnVolume map objects, which define alien and civilian no spawn zones. And I managed to pick a test point right inside one of them. :smile: Randomly spawned individual aliens do not respect no spawn zones (at least as it seemed to me), but alien pods do. That's why my newly spawned pod ended up in center of the world: spawn point was invalid, so engine relocated new actor to default (0, 0, 0) point. Now, what exactly I did. I've added a test code into XGDeployAI.GetPossibleSpawns:vValidLoc = World().FindClosestValidLocation(vect(1391, 623, 64), false, false, true); kPod = Spawn(class'XComAlienPod',,, vValidLoc,,, true); kPod.Init(); m_arrPossibleSpawns.AddItem(kPod); Since XGDeployAI deploys whatever it can wherever it can :smile: it worked just fine: my new pod "placeholder" was successfully occupied, XComAlienPodManager successfully converted new pod into abduction pod and performed actual pod spawn. Level bounds are "known" to the World object, so my original plan was to add a number of random spawn points inside level, let the existing code sort them along with original ones, divide the whole set to iNumPods subsets and deploy all pods at random points inside subsets. This will ensure that pods will be spawned around the whole map and won't end up clustered in one corner. Edited February 2, 2014 by wghost81 Link to comment Share on other sites More sharing options...
Amineri Posted February 2, 2014 Author Share Posted February 2, 2014 Sounds like some quite excellent progress :) The above two posts represent adding additional pods that spawn during the XGBattle_SP.AlienPlayerDeferredInit(), correct? As best I can tell, in order to speed up loading times, only the human side pawns/units are loaded/created before presenting the "Start Mission" button to the player, with the alien side loading in the background in the first couple of seconds while the player is making the first move. Being able to add additional random pods (or replacing old pods with new randomized locations) will go a long way toward adding replayability to the maps. However what I'd also be interested in is a way to trigger aliens appearing during a mission, in a manner simlar to how the Mutons appear in the Slingshot Confounding Light mission. (I recognize that it's quite possible that the particle effects may be baked into the map instead of in a separate upk). Link to comment Share on other sites More sharing options...
Recommended Posts