Jump to content

R&D Dynamic Pod Placement


wghost81

Recommended Posts

I was assembling a fix for LW beta 9a and noticed that iTestPod has 'protectedwrite' flag set, which is wrong. I can confirm it has this flag in beta 9a too. There's no such flag in Random Pods original code, so this must be a typo, which can potentially cause a problem. iTestPod flags should be all zero.

 

I had to do this in order to alloy UPKmodder to be able to revert the change out (back to the vanilla hex).

 

The problem is that the BEFORE HEX is idential to the AFTER HEX except for the addition Core:Vector@Object@Core at the end. So when UPKmodder checks whether the BEFORE or AFTER hex is installed, it finds matching patterns for both after the install is made.

 

The workaround was to find some innocuous flag setting so that the main "body" of the AFTER hex (without the extra 4 bytes tagged onto mark the object as a vector) is different than the BEFORE HEX so that UPKmodder can detect the install state of the file. Since iTestPod is only used as a local variable, the protected write flag shouldn't impact it's use, and so far I haven't.

 

If you have a better suggestion for a flag to set that won't have any impact, I'm open to suggestions!

 

--------------------

 

I tend to be a bit more particular (perhaps overly so) about making sure that all of the modfiles are revertable and properly can be tested for current install status. One way that helps JL and me is when we coordinate our changes. Long War EW is up around 900+ modfiles now, so coordinating everything manually would be a huge pain.

 

So what we instead is exchange our patched UPKs and redirect UPKmodder to look at the alternate versions, then run test status. And inconsistencies will be marked as either "green" = missing install in other person's version, "red" = inconsistent modfile versions, or "yellow" = partially inconsistent. "blue" = files match, so we know we are synched up when all files test blue.

 

A bulk test-status for the entire Long War project takes me about 20 or seconds, which isn't bad for 900+ files, which includes all of the actionscript changes.

Link to comment
Share on other sites

  • Replies 60
  • Created
  • Last Reply

Top Posters In This Topic

Amineri, it has different type and different size. Doesn't UPKModder check for those?

 

I don't have a better suggestion for UPKModder as I'm not using it as extensively as you and jonnylump do. But I have some experience in programming and modding and can say this: if more than one person is involved in development process, you sure need a version control system. If you can batch-apply all 900+ modfiles to clean vanilla packages and get a working copy of the mod, the best way would be to use VCS to store and exchange those modfiles.

Edited by wghost81
Link to comment
Share on other sites

UPKmodder very rarely explicitly defines a new size for an object -- instead it works off of relative size increase/decrease compared to the BEFORE hex. So it doesn't check the size to determine before/after install status. It's only using the pattern matching of before/after hex, which is problematic when the either is a proper subset of the other. Hence my rather ugly workaround to change a flag to prevent that situation.

 

And yes, we really should properly use a VCS (X Marks The Spot and I used code.google and subversion when working on UPKmodder). I think the reason we're resistant to it is that it requires continual rebuilds of the upks, and since there's just the two of us we kind of muddle along. I guess it's mostly just inertia ... for about the first half of Long War EW development UPKmodder didn't have the batch apply/revert capabilities, so we sort of evolved a system and haven't bothered to change it.

 

The primary driver for getting the bulk install working was that UPKmodder still occasionally corrupts a UPK (I get it maybe once every 2 or 3 weeks), and manually installing a big chunk of files takes about an hour or two. The bulk installer takes about a minute.

 

So, mostly just lame excuses as to why we aren't using a full VCS :)

Link to comment
Share on other sites

it requires continual rebuilds of the upks

You can uninstall just changed parts and then install a new versions. UPKModder has uninstall feature, am I correct? And if you'll add vanilla object size info, you won't even need old modfile to perform an uninstall procedure.

 

The bulk installer takes about a minute.

Why worry about upk rebuilds then? :smile: Edited by wghost81
Link to comment
Share on other sites

  • 1 month later...

Based on some fairly minor bug reports from the Long War beta testers, I've made a couple of tweaks to the version 2 (the latest I've seen) for the pod randomization module.

 

The two issues are :

1) Command pods sometimes spawn on the roof of the UFO. This is a problem on some small scout UFOs when the player cannot get on the roof, and cannot get LOS to the outsider's spawn position. It makes the mission unbeatable in that case.

 

2) Pods were sometimes spawning within LOS of the XCOM squad, and moving the person with sight of the aliens would immediately trigger them on the first turn.

 

---------------

 

Issue #1 required the most in-depth code change. The core issue is that the iTestPod was being used as an iterated random spawn point for both regular pod spawnpoints as well as the commander pod, but the iTestPod.Z position was not being reset for the commander spawnpoint -- it was using the last randomized Z position from the previous regular pod. Setting the Z value to 0 resulted in the outsider spawning under the floor in the CrashedSmallScout Nuked City map, so I used the vanilla commander Z location + 128 (2 meters), similar to what the XComAlienPod.GetDistributedPointAround function does. The inserted code looks like :

            foreach WorldInfo.AllActors(class'XComAlienPod', kPod)
            {
                if(kPod.bCommanderPod)
                {
                    iTestPod.Z = kPod.Location.Z;
                }                
            }            
            iTestPod.Z += 128.0;

Issue #2 was partly because we are using a larger distributed pod radius for larger pods, but also because the point m_vPlayerSpawn in

                if(VSizeSq(iTestPod - m_vPlayerSpawn) < 5914624.0)

is defined via :

m_vPlayerSpawn = arrSpawns[1].Location

That is it is only 1 of the 6 possible XCOM starting spawnpoints (#1 in the array 0 to 5). Since other soldier might spawn up to 6 meters away, the keep away radius of 30 meters sometimes allowed aliens to spawn within sight of one of the other soldiers.

 

To fix these, I increased the keepaway from the covert operative from 30 meters to 32 meters (to handle the increased pod distributed distance), and the keepaway for the squad from 30 meters to 38 meters (to handle both the increased pod distributed distance and the other XCOM soldier spawnpoints).

 

-------------------------

 

The complete hex for the UPKmodder file with all changes :

 

 

 

MODFILEVERSION=4
UPKFILE=XComGame.upk
GUID=1C 18 A1 1A 2B C3 34 4E 8B 2C 72 33 CD 16 7E 3E // XComGame_EW_patch3.upk
FUNCTION=GetPossibleSpawns@XGDeployAI
RESIZE=5B0

[BEFORE_HEX]
[HEADER]
C0 02 00 00 E0 01 00 00
[/HEADER]
[CODE]
2F 19 01 A6 F9 FF FF 30 00 00 00 00 00 00 61 30 20 32 42 00 00 00 73 BA 00 00 4A 16 45 00 
	//foreach WorldInfo.AllActors(class'XComAlienPod', kPod)

55 00 72 BA 00 00 0A 00 00 73 BA 00 00 16 
	//arrPods.AddItem(kPod)

31 
//
	
30

0f 00 70 BA 00 00 25 
	//iPod = 0

07 72 01 96 00 70 BA 00 00 36 00 72 BA 00 00 16 
	//if(iPod < arrPods.Length)

0F 00 73 BA 00 00 10 00 70 BA 00 00 00 72 BA 00 00 
	//kPod = arrPods[iPod]

07 EB 00 82 81 19 1B 25 63 00 00 00 00 00 00 16 0A 00 D7 BF 00 00 00 1B C6 29 00 00 00 00 00 00 16 16 18 23 00 F2 19 00 73 BA 00 00 0A 00 F6 3F 00 00 00 2D 01 F6 3F 00 00 28 16 16 
	//if(!OVERMIND().Enabled() && kPod.bUse == false)

55 00 71 BA 00 00 0A 00 00 73 BA 00 00 16 
	//arrRemove.AddItem(kPod)

06 64 01 
	//goto J0x164

07 13 01 F2 19 00 73 BA 00 00 0A 00 F6 3F 00 00 00 2D 01 F6 3F 00 00 28 16 
	//if(kPod.bUse == false)

06 64 01 
	//goto J0x164

07 64 01 81 19 00 73 BA 00 00 0B 00 56 40 00 00 00 1B 3E 45 00 00 00 00 00 00 25 16 16 
	//if(!kPod.IsInGroup(0))

55 01 34 BA 00 00 0A 00 00 73 BA 00 00 16 
	//m_arrBackupSpawns.AddItem(kPod)

55 00 71 BA 00 00 0A 00 00 73 BA 00 00 16 
	//arrRemove.AddItem(kPod)

A5 00 70 BA 00 00 16 
	//++ iPod

06 51 00 
	//goto J0x51

58 00 71 BA 00 00 00 73 BA 00 00 00 4A A0 01 
	//foreach arrRemove(kPod,)

56 00 72 BA 00 00 0A 00 00 73 BA 00 00 16 
	//arrPods.RemoveItem(kPod)

31
	//IN(1/1)
	
30
	//IP(1/1)
	
58 00 72 BA 00 00 00 73 BA 00 00 00 4A A9 02 
	//foreach arrPods(kPod,)

0F 00 6F BA 00 00 25 
	//iTestPod = 0

07 7F 02 96 00 6F BA 00 00 36 01 36 BA 00 00 16 
	//if(iTestPod < m_arrPossibleSpawns.Length)

07 71 02 B0 E4 D8 19 00 73 BA 00 00 09 00 94 F8 FF FF 00 01 94 F8 FF FF 01 32 BA 00 00 16 16 E4 D8 19 10 00 6F BA 00 00 01 36 BA 00 00 09 00 94 F8 FF FF 00 01 94 F8 FF FF 01 32 BA 00 00 16 16 16 
	//if(VSizeSq(kPod.Location - m_vPlayerSpawn) < VSizeSq(m_arrPossibleSpawns[iTestPod].Location - m_vPlayerSpawn))

57 01 36 BA 00 00 13 00 00 6F BA 00 00 00 73 BA 00 00 16 
	//m_arrPossibleSpawns.InsertItem(iTestPod, kPod)

0F 00 6F BA 00 00 1D FF FF FF FF 
	//iTestPod = -1

06 7F 02 
	//goto J0x27F

A5 00 6F BA 00 00 16 
	//++ iTestPod

06 C3 01 
	//goto J0x1C3

07 A8 02 9B 00 6F BA 00 00 1D FF FF FF FF 16 
	//if(iTestPod != -1)

55 01 36 BA 00 00 0A 00 00 73 BA 00 00 16 
	//m_arrPossibleSpawns.AddItem(kPod)

31
	IN(1/1)
	
30
	IP(1/1)
	
0F 01 35 BA 00 00 01 36 BA 00 00 
	//m_arrOriginalSpawns = m_arrPossibleSpawns

04 0B 
	//return

53 
//	
[/CODE]
[/BEFORE_HEX]



ALIAS=numPods:1A 2C 00 00 <.iPod>       // num pods
ALIAS=numSecL:1A 2C 01 00 <.iPod>       // num sectors on the larger side
ALIAS=numSecS:1A 2C 02 00 <.iPod>       // num sectors on the smaller side
ALIAS=mapNumX:1A 2C 03 00 <.iPod>       // map X length in tiles
ALIAS=mapNumY:1A 2C 04 00 <.iPod>       // map Y length in tiles
ALIAS=mapNumZ:1A 2C 11 00 <.iPod>       // map Z length in tiles
ALIAS=stepX:1A 2C 05 00 <.iPod>         // X step in tiles
ALIAS=stepY:1A 2C 06 00 <.iPod>         // Y step in tiles
ALIAS=randX:1A 2C 07 00 <.iPod>         // X randomization interval in tiles
ALIAS=randY:1A 2C 08 00 <.iPod>         // Y randomization interval in tiles
ALIAS=startX:1A 2C 09 00 <.iPod>        // X start point in tiles
ALIAS=startY:1A 2C 0A 00 <.iPod>        // Y start point in tiles
ALIAS=pointFound:1A 2C 0B 00 <.iPod>    // found spawn point flag
ALIAS=commandFound:1A 2C 0C 00 <.iPod>  // found command point flag
ALIAS=UFOIdx:1A 2C 0D 00 <.iPod>        // UFO volume index
ALIAS=TileX:1A 2C 0E 00 <.iPod>
ALIAS=TileY:1A 2C 0F 00 <.iPod>
ALIAS=TileZ:1A 2C 10 00 <.iPod>

[AFTER_HEX]
[HEADER]
7C 0A 00 00 90 07 00 00
[/HEADER]
[CODE]
//numPods = m_kSquad.arrPods.Length
0F 1A 2C 00 00 70 BA 00 00 36 35 42 00 00 00 43 00 00 00 00 00 01 38 BA 00 00 

//if (numPods < 5)
07 5E 00 96 1A 2C 00 00 70 BA 00 00 2C 05 16 

    //numSecL = 3;
    0F 1A 2C 01 00 70 BA 00 00 2C 03

    //numSecS = 2;
    0F 1A 2C 02 00 70 BA 00 00 2C 02

//goto (else)
06 B0 00 

	//else if (numPods < 7)
	07 92 00 96 1A 2C 00 00 70 BA 00 00 2C 07 16

	    //numSecL = 3;
	    0F 1A 2C 01 00 70 BA 00 00 2C 03

	    //numSecS = 3;
	    0F 1A 2C 02 00 70 BA 00 00 2C 03

	//goto (else)
	06 B0 00

	    //numSecL = 4;
	    0F 1A 2C 01 00 70 BA 00 00 2C 04

	    //numSecS = 3;
	    0F 1A 2C 02 00 70 BA 00 00 2C 03

//mapNumX = World().NumX;
0F 1A 2C 03 00 70 BA 00 00 19 1B A1 7F 00 00 00 00 00 00 16 09 00 30 0D 00 00 00 01 30 0D 00 00 

//mapNumY = World().NumY;
0F 1A 2C 04 00 70 BA 00 00 19 1B A1 7F 00 00 00 00 00 00 16 09 00 2F 0D 00 00 00 01 2F 0D 00 00 

//mapNumZ = World().NumZ;
0F 1A 2C 11 00 70 BA 00 00 19 1B A1 7F 00 00 00 00 00 00 16 09 00 2E 0D 00 00 00 01 2E 0D 00 00 

//if (mapNumX > mapNumY)
07 A2 01 97 1A 2C 03 00 70 BA 00 00 1A 2C 04 00 70 BA 00 00 16 

	//stepX = mapNumX / numSecL;
	0F 1A 2C 05 00 70 BA 00 00 91 1A 2C 03 00 70 BA 00 00 1A 2C 01 00 70 BA 00 00 16 

	//stepY = mapNumY / numSecS;
	0F 1A 2C 06 00 70 BA 00 00 91 1A 2C 04 00 70 BA 00 00 1A 2C 02 00 70 BA 00 00 16 

//goto (else)
06 F0 01 

	//stepX = mapNumX / numSecS;
	0F 1A 2C 05 00 70 BA 00 00 91 1A 2C 03 00 70 BA 00 00 1A 2C 02 00 70 BA 00 00 16 

	//stepY = mapNumY / numSecL;
	0F 1A 2C 06 00 70 BA 00 00 91 1A 2C 04 00 70 BA 00 00 1A 2C 01 00 70 BA 00 00 16 

//randX = (stepX * 3) / 4;
0F 1A 2C 07 00 70 BA 00 00 91 90 1A 2C 05 00 70 BA 00 00 2C 03 16 2C 04 16 

//randY = (stepY * 3) / 4;
0F 1A 2C 08 00 70 BA 00 00 91 90 1A 2C 06 00 70 BA 00 00 2C 03 16 2C 04 16 

//startX  = (stepX - randX) / 2;
0F 1A 2C 09 00 70 BA 00 00 91 93 1A 2C 05 00 70 BA 00 00 1A 2C 07 00 70 BA 00 00 16 2C 02 16 

//if (startX < mapNumX) // x loop
07 72 05 96 1A 2C 09 00 70 BA 00 00 1A 2C 03 00 70 BA 00 00 16 

	//startY = (stepY - randY) / 2;
	0F 1A 2C 0A 00 70 BA 00 00 91 93 1A 2C 06 00 70 BA 00 00 1A 2C 08 00 70 BA 00 00 16 2C 02 16 

	//if (startY < mapNumY) // y loop
	07 55 05 96 1A 2C 0A 00 70 BA 00 00 1A 2C 04 00 70 BA 00 00 16 

		//pointFound = 0;
		0F 1A 2C 0B 00 70 BA 00 00 2C 00 

		//if (pointFound < 10) // 10 attempts to find good spawn point
		07 C4 04 96 1A 2C 0B 00 70 BA 00 00 2C 0A 16 

			//++pointFound;
			A3 1A 2C 0B 00 70 BA 00 00 16 

			//iTestPod = World().FindClosestValidLocation(World().GetPositionFromTileCoordinates(iPod[ 9] + Rand(randX),startY + Rand(randY), Rand(mapNumZ)),false, false, true);
			0F 00 6F BA 00 00 19 1B A1 7F 00 00 00 00 00 00 16 73 00 AC D2 00 00 00 1B 29 33 00 00 00 00 00 00 19 1B A1 7F 00 00 00 00 00 00 16 50 00 BC 0C 00 00 00 1B DD 3A 00 00 00 00 00 00 92 1A 2C 09 00 70 BA 00 00 A7 1A 2C 07 00 70 BA 00 00 16 16 92 1A 2C 0A 00 70 BA 00 00 A7 1A 2C 08 00 70 BA 00 00 16 16 A7 1A 2C 11 00 70 BA 00 00 16 16 28 28 27 16 

			//World().GetFloorTileForPosition(iTestPod, TileX, TileY, TileZ, true)
			19 1B A1 7F 00 00 00 00 00 00 16 38 00 C4 0C 00 00 00 1B E8 38 00 00 00 00 00 00 00 6F BA 00 00 1A 2C 0E 00 70 BA 00 00 1A 2C 0F 00 70 BA 00 00 1A 2C 10 00 70 BA 00 00 27 16 

			//iTestPod = World().GetPositionFromTileCoordinates(TileX, TileY, TileZ)
			0F 00 6F BA 00 00 19 1B A1 7F 00 00 00 00 00 00 16 2E 00 BC 0C 00 00 00 1B DD 3A 00 00 00 00 00 00 1A 2C 0E 00 70 BA 00 00 1A 2C 0F 00 70 BA 00 00 1A 2C 10 00 70 BA 00 00 16 

			//if(VSizeSq(iTestPod - m_vPlayerSpawn) < 5914624.0) // far from player (38m)  // 4AB48000 
			07 44 04 B0 E4 D8 00 6F BA 00 00 01 32 BA 00 00 16 16 1E 00 80 B4 4A 16 

				//goto loop3  break
				06 D1 02

			//if(XGBattle_SPCovertOpsExtraction(BATTLE()) != none) // far from covert operative (32m) // 4A800000
			07 B5 04 77 2E 1F B4 00 00 1B 3C 08 00 00 00 00 00 00 16 2A 16 

				//if(VSizeSq(iTestPod - XGBattle_SPCovertOpsExtraction(BATTLE()).ChooseCovertOperativeSpawnPoint().Location) < 4194304.0)
				07 B5 04 B0 E4 D8 00 6F BA 00 00 19 19 2E 1F B4 00 00 1B 3C 08 00 00 00 00 00 00 16 0A 00 FF B3 00 00 00 1C 00 B4 00 00 16 09 00 94 F8 FF FF 00 01 94 F8 FF FF 16 16 1E 00 00 80 4A 16 

					//goto loop3   break
					06 D1 02 

			//pointFound = 0; // found good spawn point
			0F 1A 2C 0B 00 70 BA 00 00 2C 00 

		//if (pointFound == 0) // if found good spawn point
		07 38 05 9A 1A 2C 0B 00 70 BA 00 00 2C 00 16 

			//kPod = Spawn(class'XComAlienPod',,, iTestPod,,, true)
			0F 00 73 BA 00 00 1C 12 FC FF FF 20 32 42 00 00 4A 4A 00 6F BA 00 00 4A 4A 27 4A 16 

			//kPod.Init()
			19 00 73 BA 00 00 0A 00 00 00 00 00 00 1B 8D 41 00 00 00 00 00 00 16 

			//arrPods.AddItem(kPod)
			55 00 72 BA 00 00 0A 00 00 73 BA 00 00 16 

		//startY += stepY;
		A1 1A 2C 0A 00 70 BA 00 00 1A 2C 06 00 70 BA 00 00 16

		//while loop
		06 A5 02 

	//startX += stepX;
	A1 1A 2C 09 00 70 BA 00 00 1A 2C 05 00 70 BA 00 00 16

	//goto loop1;
	06 5D 02 

//if(((BattleDesc().m_iMissionType == 8) || BattleDesc().m_iMissionType == 10) || BattleDesc().m_eUFOType == 9) // eMission_AlienBase || eMission_Final || eShip_UFOEthereal
07 FE 05 84 84 9A 19 1B 3F 08 00 00 00 00 00 00 16 09 00 B2 B4 00 00 00 01 B2 B4 00 00 2C 08 16 18 24 00 9A 19 1B 3F 08 00 00 00 00 00 00 16 09 00 B2 B4 00 00 00 01 B2 B4 00 00 2C 0A 16 16 18 28 00 9A 38 3A 19 1B 3F 08 00 00 00 00 00 00 16 09 00 AF B4 00 00 00 01 AF B4 00 00 38 3A 24 09 16 16 

    //commandFound = 0;
    0F 1A 2C 0C 00 70 BA 00 00 2C 00

//else
06 C9 09 //[@missionCheckEnd]

	//if((BattleDesc().m_iMissionType == 3) || BattleDesc().m_iMissionType == 4)   // eMission_Crash || eMission_LandedUFO
	07 BA 09 84 9A 19 1B 3F 08 00 00 00 00 00 00 16 09 00 B2 B4 00 00 00 01 B2 B4 00 00 2C 03 16 18 24 00 9A 19 1B 3F 08 00 00 00 00 00 00 16 09 00 B2 B4 00 00 00 01 B2 B4 00 00 2C 04 16 16 

	    //UFOIdx = OVERMIND().m_kLayout.GetUFOVolumeIndex();
		0F 1A 2C 0D 00 70 BA 00 00 19 19 1B 25 63 00 00 00 00 00 00 16 09 00 16 BF 00 00 00 01 16 BF 00 00 0A 00 AB BC 00 00 00 1B F2 3B 00 00 00 00 00 00 16 

	    //arrRemove = OVERMIND().m_kLayout.GetBuildingByIndex(UFOIdx).rectBuilding;
		0F 00 71 BA 00 00 35 90 AF 00 00 91 AF 00 00 00 00 19 19 1B 25 63 00 00 00 00 00 00 16 09 00 16 BF 00 00 00 01 16 BF 00 00 16 00 AE BC 00 00 00 1B CA 37 00 00 00 00 00 00 1A 2C 0D 00 70 BA 00 00 16 

		//arrRemove = ScaleRect(arrRemove, 0.750)
		0F 00 71 BA 00 00 1B 14 6B 00 00 00 00 00 00 00 71 BA 00 00 1E 00 00 40 3F 16 

		//iTestPod.X = arrRemove.fLeft + (FRand() * (RectWidth(arrRemove)))
		0F 35 0C FD FF FF 16 F9 FF FF 00 00 00 6F BA 00 00 AE 35 00 FD FF FF 0F F9 FF FF 00 01 00 71 BA 00 00 AB C3 16 1B 56 68 00 00 00 00 00 00 00 71 BA 00 00 16 16 16 

		//iTestPod.Y = arrRemove.fTop + (FRand() * (RectHeight(arrRemove)))
		0F 35 0B FD FF FF 16 F9 FF FF 00 00 00 6F BA 00 00 AE 35 FE FC FF FF 0F F9 FF FF 00 01 00 71 BA 00 00 AB C3 16 1B 50 68 00 00 00 00 00 00 00 71 BA 00 00 16 16 16 

		//foreach WorldInfo.AllActors(class'XComAlienPod', kPod)
		2F 19 01 A6 F9 FF FF 83 00 00 00 00 00 00 61 30 20 32 42 00 00 00 73 BA 00 00 4A 16 51 08 

			//if(kPod.bCommanderPod)
			07 50 08 19 00 73 BA 00 00 0A 00 EC 3F 00 00 00 2D 01 EC 3F 00 00 

				//iTestPod.Z = kPod.Location.Z
				0F 35 0A FD FF FF 16 F9 FF FF 00 00 00 6F BA 00 00 35 0A FD FF FF 16 F9 FF FF 00 00 19 00 73 BA 00 00 09 00 94 F8 FF FF 00 01 94 F8 FF FF

			//IN
			31

			//IP
			30

		//iTestPod.Z += 128.0  // reset Z to zero to prevent command pod from appearing on roof  //     43000000
		B8 35 0A FD FF FF 16 F9 FF FF 00 00 00 6F BA 00 00 1E 00 00 00 43 16 

		//iTestPod = World().FindClosestValidLocation(iTestPod, false, false, true)
		0F 00 6F BA 00 00 19 1B A1 7F 00 00 00 00 00 00 16 16 00 AC D2 00 00 00 1B 29 33 00 00 00 00 00 00 00 6F BA 00 00 28 28 27 16 

		//World().GetFloorTileForPosition(iTestPod, TileX, TileY, TileZ, true)
		19 1B A1 7F 00 00 00 00 00 00 16 38 00 C4 0C 00 00 00 1B E8 38 00 00 00 00 00 00 00 6F BA 00 00 1A 2C 0E 00 70 BA 00 00 1A 2C 0F 00 70 BA 00 00 1A 2C 10 00 70 BA 00 00 27 16 

		//iTestPod = World().GetPositionFromTileCoordinates(TileX, TileY, TileZ)
		0F 00 6F BA 00 00 19 1B A1 7F 00 00 00 00 00 00 16 2E 00 BC 0C 00 00 00 1B DD 3A 00 00 00 00 00 00 1A 2C 0E 00 70 BA 00 00 1A 2C 0F 00 70 BA 00 00 1A 2C 10 00 70 BA 00 00 16 

		//kPod = Spawn(class'XComAlienPod',,, iTestPod,,, true)
		0F 00 73 BA 00 00 1C 12 FC FF FF 20 32 42 00 00 4A 4A 00 6F BA 00 00 4A 4A 27 4A 16 

		//kPod.Init()
		19 00 73 BA 00 00 0A 00 00 00 00 00 00 1B 8D 41 00 00 00 00 00 00 16 

		//arrPods.AddItem(kPod)
		55 00 72 BA 00 00 0A 00 00 73 BA 00 00 16 

		//commandFound = 1;
		0F 1A 2C 0C 00 70 BA 00 00 2C 01

	//goto (else)
	06 C9 09 //[@missionCheckEnd]

		//commandFound = 1;
		0F 1A 2C 0C 00 70 BA 00 00 2C 01

//if (commandFound == 0) // extract original commander pod from map
07 53 0A 9A 1A 2C 0C 00 70 BA 00 00 2C 00 16 

	//foreach WorldInfo.AllActors(class'XComAlienPod', kPod)
	2F 19 01 A6 F9 FF FF 5A 00 00 00 00 00 00 61 30 20 32 42 00 00 00 73 BA 00 00 4A 16 52 0A 

		//if(kPod.bCommanderPod)
		07 51 0A 19 00 73 BA 00 00 0A 00 EC 3F 00 00 00 2D 01 EC 3F 00 00 

			//arrPods.AddItem(kPod)
			55 00 72 BA 00 00 0A 00 00 73 BA 00 00 16 

			//commandFound = 1;
			0F 1A 2C 0C 00 70 BA 00 00 2C 01 

		//IN
		31

		//IP
		30

//m_arrPossibleSpawns = arrPods
0F 01 36 BA 00 00 00 72 BA 00 00 

//m_arrOriginalSpawns = m_arrPossibleSpawns
0F 01 35 BA 00 00 01 36 BA 00 00 

//return;
04 0B 

//null ops
//0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 0B 

//EOS
53

[/CODE]
[/AFTER_HEX] 

 

 

Link to comment
Share on other sites

To fix these, I increased the keepaway from the covert operative from 30 meters to 32 meters (to handle the increased pod distributed distance), and the keepaway for the squad from 30 meters to 38 meters (to handle both the increased pod distributed distance and the other XCOM soldier spawnpoints).

This leaves a very small available area for enemy spawns on small maps and on Covert Ops maps. I think being able to activate a pod from the very start is lesser evil in this case.

 

Thanks for finding an error in command pod placement code! Will fix it for Random Pods mod too.

Link to comment
Share on other sites

  • 1 month later...

A small progress report on Council missions randomization.

 

I've managed to replace original set of alien drop-down points with randomly generated drop-down points. Here's PatchUPK/PatcherGUI modfile:

 

UPK_FILE=XComGame.upk

//change ThisObj local var type to XComWorldData
OBJECT=SeqAct_SpawnAlien.Activated.ThisObj
REL_OFFSET=40
OBJIDX=XComWorldData

//convert SpawnObj local var to vector
EXPORT_ENTRY=SeqAct_SpawnAlien.Activated.SpawnObj
OBJIDX=Core.StructProperty
OBJECT=SeqAct_SpawnAlien.Activated.SpawnObj
REL_OFFSET=40
OBJIDX=Core.Object.Vector


OBJECT=SeqAct_SpawnAlien.Activated:AUTO

ALIAS=numX:19 00 <.ThisObj> 09 00 <XComWorldData.NumX> 00 01 <XComWorldData.NumX>
ALIAS=numY:19 00 <.ThisObj> 09 00 <XComWorldData.NumY> 00 01 <XComWorldData.NumY>
ALIAS=numZ:19 00 <.ThisObj> 09 00 <XComWorldData.NumZ> 00 01 <XComWorldData.NumZ>

[REPLACEMENT_CODE]
//if(!bEnabled)
07 [@NotEnabled] 81 2D 01 <@bEnabled> 16

	//return
	04 0B
	
[#NotEnabled]

//get XComWorldData object
//ThisObj = class'XComWorldData'.static.GetWorldData()
0F 00 <.ThisObj> 12 20 <Class.XComWorldData> 0A 00 <XComWorldData.GetWorldData.ReturnValue> 00 1B <GetWorldData> 16

//SpawnedUnit = none
0F 01 <@SpawnedUnit> 2A

//OutputLinks[1].bHasImpulse = false
14 2D 35 <Engine.SequenceOp.SeqOpOutputLink.bHasImpulse> <Engine.SequenceOp.SeqOpOutputLink> 00 01 10 26 01 <Engine.SequenceOp.OutputLinks> 28

//m_kDropIn = new class'XGAISpawnMethod_DropIn'
0F 01 <@m_kDropIn> 11 0B 0B 0B 20 <Class.XGAISpawnMethod_DropIn> 0B

//m_kDropIn.InitDropIn(iDropHeight, bUseOverwatch, bTriggerOverwatch, bPlaySound, bRevealSpawn, bSpawnImmediately, ForceAlienType, kAdditionalSound, self)
19 01 <@m_kDropIn> 59 00 <NullRef> 00 1B <InitDropIn> 01 <@iDropHeight> 2D 01 <@bUseOverwatch> 2D 01 <@bTriggerOverwatch> 2D 01 <@bPlaySound> 2D 01 <@bRevealSpawn> 2D 01 <@bSpawnImmediately> 01 <@ForceAlienType> 01 <@kAdditionalSound> 17 4A 16

//SpawnObj = ThisObj.FindClosestValidLocation(ThisObj.GetPositionFromTileCoordinates(Rand(numX), Rand(numY), numZ - 1), false, true, false);
0F 00 <.SpawnObj>
19
00 <.ThisObj> <%s141> <XComWorldData.FindClosestValidLocation.ReturnValue> 00 1B <FindClosestValidLocation>
    19
    00 <.ThisObj> <%s107> <XComWorldData.GetPositionFromTileCoordinates.ReturnValue> 00 1B <GetPositionFromTileCoordinates>
        A7 <!numX> 16
        A7 <!numY> 16
        93 <!numZ> 26 16
    16
    28 27 28
16

//SpawnPt = Spawn(class'XComSpawnPoint_Alien',,,SpawnObj,,, true)
0F 00 <.SpawnPt> 1C <Engine.Actor.Spawn> 20 <Class.XComSpawnPoint_Alien> 4A 4A 00 <.SpawnObj> 4A 4A 27 4A 16

//m_kDropIn.AddSpawnPoint(SpawnPt)
19 01 <@m_kDropIn> 14 00 <NullRef> 00 1B <AddSpawnPoint> 00 <.SpawnPt> 4A 16

//if(bSpawnImmediately)
07 [@NotImmediately] 2D 01 <@bSpawnImmediately>

	//m_kDropIn.CheckContentLoaded()
	19 01 <@m_kDropIn> 0A 00 <NullRef> 00 1B <CheckContentLoaded> 16

[#NotImmediately]

//OutputLinks[0].bHasImpulse = true
14 2D 35 <Engine.SequenceOp.SeqOpOutputLink.bHasImpulse> <Engine.SequenceOp.SeqOpOutputLink> 00 01 10 25 01 <Engine.SequenceOp.OutputLinks> 27

//ActivateOutputLink(0)
1C <Engine.SequenceOp.ActivateOutputLink> 25 16

//return
04 0B

//EOS
53

 

 

Placement is completely random with this new code, i.e. ThinMen can drop right in the middle of your squad or at the farthest map edge. Drop-downs are triggered by VIP movement as usual.

 

This code is compatible with vanilla game, Random Pods mod, Long War and existing saves.

 

Ideas on how to improve drop-downs placement are welcomed. :smile:

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...