Jump to content

R&D on four enhancements


johnnylump

Recommended Posts

This thread will attempt to develop four modifications to X-com to create a more interesting game. If we can get them working, I intend to use them in my Long War mod, but I expect they may be useful for other mods, as well. These are probably more complicated than simply switching a value or sign in a function, and I hope some of you more skilled than I with rescripting are willing and able to collaborate. I'll update each post as I find things that will move the ball forward. Please help!

#1
Each interceptor or firestorm kill gives that ship a +2% chance to hit in future interceptions
Purpose: To improve the interception game by allowing individual craft to gain experience that makes them more effective; this will create more interesting strategic decisions as players must weigh when to commit their best fighters

pseudocode: tohit = tohit + (2 * this interceptor's kills)

relevant variable: XGShip_Interceptor.m_iConfirmedKills (int)
relevant function:
XComStrategyGame, XGInterceptionEngagement, function UpdateWeapons

Here's the code that fires a ship's weapon:

if(Rand(100) <= akShipWeapons[iWeapon].iToHit)
{
kCombatExchange.bHit = true;
kCombatExchange.iDamage = GetShipDamage(akShipWeapons[iWeapon], kCombatExchange);
}


This code seems to be in play for both UFOs and interceptors.
At this point, I'm unclear if iToHit just references the default weapons table, or if it is a separately held variable that can be changed.

The first challenge here is finding enough bytes in the (fortunately long) function to add three mathematical operations and two variable references. The second is ensuring interceptor kills is an accessible variable inside this function. More specific pseudocode would be

if Rand (100) <= akShipWeapons[iWeapon].iToHit + (shipnum * shipkills * 2)

It looks like the UFO is always ship number 0 in an interception, so the bonus would always be 0, while the interceptor is always ship number 1, so the bonus would be shipkills * 2.

 

VERDICT: This works! I'll make available the rescripted updateweapons function; just pm me.

Edited by johnnylump
Link to comment
Share on other sites

  • Replies 44
  • Created
  • Last Reply

Top Posters In This Topic

#2 Randomize grenade / explosives damage
Purpose: Grenades are a "sure thing" to hit a target; the risk-reward fun will increase if they don't always do the same damage.

pseudocode: GrenadeDamage = GrenadeDamage -1 + random (3)

 

UPDATED VERDICT: THIS WORKS!

 

Thanks and full credit to Amineri for solving this one.

 

A simple hex changes does this! It puts explosives (grenades and rockets) in the same category as other weapons, applying a range of damage. Damage roulette also reportedly affects these classes of weapons as well.

 

In XComGame.upk, class XGTacticalGameCore, function CalcOverallDamage()

 

Original: 07 9F 00 1B 8C 71 00 00 00 00 00 00 00 F3 76 00 00 2C 09 16 04 00 EE 76 00 00
Replace: 07 9F 00 9A 00 F3 76 00 00 2C 08 16 04 00 EE 76 00 00 0B 0B 0B 0B 0B 0B 0B 0B
Edited by johnnylump
Link to comment
Share on other sites

#3 Give weaker aliens more hit points after a certain point in the game
Purpose: Sectoids, Thin Men, Floaters and Chrysallids are too easy to kill once you develop experienced troopers carrying plasma weapons. To keep a greater variety of threatening aliens in the mid and late game, why not buff these critters after a certain amount of time has passed to give them a fighting chance?

(Several options here; you might make "officers" and only buff the leader of a pod, but not the subordinates)

Pseudocode: If GetMonth() >= 6 && AlienType = sectoid, thin men, floater or chyrsallid then hp += 2

-Sectoid is Alien 4, Floater 5, Thinman 6, Chrysalid 13
-XComStrategyGame.XGStrategyAI.BuildPod modifies individual aliens in pods, but I'm not sure if you can change hit points here
- Have not found where data from DGC.ini is read into variables
- XComGame.XGUnit.SpawnPawn is a possibility, but it prolly won't work, as there are multiple function calls to XGUnitNativeBase.GetUnitMaxHP in various other functions
- GetUnitNativeBase.GetUnitMaxHP is a native simulated function, which I don't know how to edit (I think native means C++ script, possibly in the .exe, and simulated means something to do with multiplayer)

If I can find the bytes, may attempt a simpler change in SpawnPawn, something like MaxHealth = MaxHealth + GetMonth div 4, so all aliens get an extra hit point every four months.

VERDICT: I think this won't work. Hit Points are assigned in XGUnit.SpawnPawn in XComGame. But GetMonth() doesn't appear in XComGame at all, and using its bytecode from XComStrategyGame calls a different function. There's no way to tell anything in XComGame how much time has passed in the strategy game, so it may not be possible to level up aliens based on time that has passed.

 

Update: We're trying to upgrade aliens midgame using the ground mission count as the temporally relevant variable, and giving damage reduction or regeneration abilities as an alternative to more hit points. Stay tuned.

Edited by johnnylump
Link to comment
Share on other sites

#4 Alien Fighters

Purpose: Make alien scouts more of a threat in mid and late game by giving them the double plasma cannon previously found only on bigger ships

Pseudocode: If GetMonth () >= 6 and ship = small scout or large scout then weapon = double plasma cannon

 

No joy here so far. A GetMonth() call in UpdateShips is the apparent cause of a crash during save game load. I would note that GetMonth() isn't used anywhere in XGItemTree. Hmm, I wonder, though, if some of the ever-had-item triggers might work instead. However, we still don't know whether UpdateShips would be called more than once.

 

Update: Progress! Game.GetAct() works in the UpdateShips () function, so I've seen large scouts with varying weapons depending on what Act the game is in. Further testing underway.

 

Verdict: It works! By rescripting BuildShips AND including a call in another regularly-called function (in my case, ShouldHunt, which I've also rescripted and had some bytes to spare), I've seen UFOs upgrade after certain conditions are met. Instead of using GetAct() I used EverHadItem(), which checks if you've ever had a particular item in your inventory. I used alien corpses, which means I can calibrate alien UFO upgrades to GetMonth(), as certain aliens appear in certain months. Here's the function I'm using:

 

function UpdateShips()
{
    UpdateShip(2, 2000, 10, 8, 0, 0);
    UpdateShip(1, 1500, 10, 2500, 5, 0);
    UpdateShip(3, 3500, 15, 3500, 25, 16);
    UpdateShip(4, 3500, 40, 800, 0, 7);
    UpdateShip(5, 3000, 30, 2000, 0, 7);
    UpdateShip(6, 2000, 25, 3000, 30, 0);
    UpdateShip(7, 2000, 20, 2800, 20, 0);
    UpdateShip(8, 3000, 35, 3700, 50, 20);
    UpdateShip(9, 3500, 60, 2500, 64, 25);
    BuildShipWeapons();                                    
    // End:0x146
    if(STORAGE().EverHadItem(151))
    {
        BuildShip(5, m_strSizeMedium, 80, 9);
    }                                    
    // End:0x191
    if(STORAGE().EverHadItem(147))
    {
        BuildShip(4, m_strSizeSmall, 79, 8, 8);                
    }                        
    // End:0x21C
    if(STORAGE().EverHadItem(189))
    {
        UpdateShip(5, 3000, 30, 2000, 30, 7);                        
        UpdateShip(6, 2000, 25, 3500, 35, 7);                                
        BuildShipWeapon(9, -1, 101, 1.0, 900, 20, 40);
    }                                                                                       
    UpdateAllShipTemplates();
    //return;    
}

 

A small scout with two Plasma Cannon I is a sight to see.

 

Rewriting this script alone, however, will create some problems, as it's only called on game load, so the player would have to exit the game and come back. Putting a call in ShouldHunt() means it will be called fairly regularly when UFOs are zipping around.

Edited by johnnylump
Link to comment
Share on other sites

Add #4

 

In theory, it needs extra conditional in BuildShips() fuction, but there's no space.

if (GetMonth () >= 6)
{
BuildShip(4, m_strSizeSmall, 79, 9, 8);
}
else
{
BuildShip(4, m_strSizeSmall, 79, 8);
}

In UpdateShips() function is Large Scout's Code the same for all difficulties (if you haven't modded it). Required space could be freed by deleting UpdateShip(4, 1500, 20, 800, 0, 7); from all cases and putting it before the switch along with the conditional. But dunno about updating m_arrShips array.

 

 

Add #1-#3

 

Nice ideas, that would be cool to script. But with bytecode, it is pain :(

Link to comment
Share on other sites

Now that you've got the capability to add more UFO encounters in the game, I love the idea of being able to work with the interceptors more so I love these ideas. It'd be so cool if you could customize the interceptors (add decals, color, items) and have them level up and gain perks just like your soldiers do, however I know that is beyond our capabilities at present.

 

#1 is a step in the right direction though!

 

Also I like #3 a lot, especially because I'm tired of going on late game council missions with 100% thinmen that are incredibly weak. The proper solution would be to have council missions level up enemies as the months go by, but I can settle for stronger thinmen lol.

Link to comment
Share on other sites

Add #4

 

In theory, it needs extra conditional in BuildShips() fuction, but there's no space.

if (GetMonth () >= 6)
{
BuildShip(4, m_strSizeSmall, 79, 9, 8);
}
else
{
BuildShip(4, m_strSizeSmall, 79, 8);
}

In UpdateShips() function is Large Scout's Code the same for all difficulties (if you haven't modded it). Required space could be freed by deleting UpdateShip(4, 1500, 20, 800, 0, 7); from all cases and putting it before the switch along with the conditional. But dunno about updating m_arrShips array.

 

 

Add #1-#3

 

Nice ideas, that would be cool to script. But with bytecode, it is pain :(

 

@ Drak

 

When is a class' INIT function called? Only at the game start? On loading?

 

PLEASE prove me wrong, but I think UpdateShips() is only called from XGItemTree's Init function. If so, this wouldn't work. (Or, weirdly, only after you reload a game.)

 

@ Graa

 

I'll have to look, but it may be easier to edit alien rosters for council missions than to make certain species tougher. I'd prefer to make certain aliens tougher, though, just so we can keep more variety in the late game. (My mod usually has 12 missions a month, so variety would keep the late game missions more interesting). Hit points is looking very difficult unless there is a breakthrough in editing native functions; an alternative is to jack up their defense rating and make them harder to hit in the first place.

Edited by johnnylump
Link to comment
Share on other sites

When is a class' INIT function called? Only at the game start? On loading?

 

PLEASE prove me wrong, but I think UpdateShips() is only called from XGItemTree's Init function. If so, this wouldn't work. (Or, weirdly, only after you reload a game.)

I guess it's called, when the class is loaded. Maybe on a transition between tactical and strategic layer. I don't know UnrealScript well to confirm it.

Link to comment
Share on other sites

When is a class' INIT function called? Only at the game start? On loading?

 

PLEASE prove me wrong, but I think UpdateShips() is only called from XGItemTree's Init function. If so, this wouldn't work. (Or, weirdly, only after you reload a game.)

I guess it's called, when the class is loaded. Maybe on a transition between tactical and strategic layer. I don't know UnrealScript well to confirm it.

 

Thinking about it more, I would guess it's called whenever the class is created, but when is that? If you're correct, then this would very likely work. I'll have to give it a try.

Link to comment
Share on other sites

When is a class' INIT function called? Only at the game start? On loading?

 

PLEASE prove me wrong, but I think UpdateShips() is only called from XGItemTree's Init function. If so, this wouldn't work. (Or, weirdly, only after you reload a game.)

I haven't been following this discussion, so I'm not sure if this is what you mean or if it will be useful... :)

 

It looks like the XGItemTree > Init() function is called from XGFacility_Engineering > Init(), which is called from XGHeadQuaters > CreateFacilities().

 

XGFacility_Engineering

function Init(bool bLoadingFromSave)
{
   BaseInit();
   m_kItems = Spawn(class'XGItemTree');
   m_kItems.Init();
   // End:0x6a
   if(m_arrMusingTracker.Length == 0)
   {
       m_arrMusingTracker.Add(6);
   }
}

 

UpdateShips() is called from XGItemTree > Init() > BuildShips() as you mentioned, but it's also called from XGStrategy > ChangeDifficulty().

 

There's a different UpdateShips() function in XGGeoscape as well, which I think is only called from XGGeoscape > GameTick().

 

:)

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...