Fallout Tactics utility FTSE - Fallout Tactics Scripting Engine (0.55a)

I'll make sure to include these changes (starting inventory patch, high-res patch) as options in the hex patch JSON config file (along with the background music one). The high-res patch will be enabled by default, and the inventory and music disabled by default but able to be turned on just from setting the 'enabled' flag.

And a big thank you to DDTerr - those offsets are certain to come in handy when I start the entity and inventory features! :)
 
Updated to 0.32a. The biggest change in this version is to provide a more complete fix for the burst attack bug (the hex edit left some cases where the bug could trigger). In addition, the behavior of burst attacks is now in the Lua scripts, so it can be modified to change how the bullet spread is assigned to each eligible target.

Other changes include adding the hex patches in the JSON file for the high-res patch, the color fix on random encounters, and an optional patch to blank the starting inventory (thanks to DDTerr for the patch info).

Next up is more customization options for more attack types - cone (shotgun), radial (explosions), and spray (seems to not be used in the vanilla game?); plus customization of chance-to-hit, critical chance, critical effects, and damage calculation.
 
No starting inventory patch: I still think it would be better to have only a short hex patch done by FTSE to remove the call to that auto-equipping routine or just insert a return command at the beginning of that routine instead of zeroing the path strings to those ent files - even if it works now.
It would be more elegant, simpler and without possible side-effects. But I know it's a lot of work and we have raised too many bugs to fix and requests to investigate.
Melindil, I want to thank you for your effort and wish you enough free time and enthusiasm to continue your work....
 
No starting inventory patch: I still think it would be better to have only a short hex patch done by FTSE to remove the call to that auto-equipping routine or just insert a return command at the beginning of that routine instead of zeroing the path strings to those ent files - even if it works now.
It would be more elegant, simpler and without possible side-effects. But I know it's a lot of work and we have raised too many bugs to fix and requests to investigate.

Agreed. I'll likely add a scripting hook to the routine that creates the player entity, so that a mod can change the starting items from the script, and have the default behavior only trigger when that script is undefined. But I want to have some of the other inventory and entity functionality in first, so the hex patch is good for the short term.

Melindil, I want to thank you for your effort and wish you enough free time and enthusiasm to continue your work....

Thank you! My enthusiasm is still as high as it was when I started - there's a lot of areas I haven't even started looking into yet, but want to. Just wish I had more than a couple hours a week to work on it ... :)
 
Citing other modding gurus:

Re 1) So the bug is in the level editor, it should take over the tagname of the just inserted entity from its ent file. Then you would have a possibility to rename it or leave the imported default one. Might be an easy fix?

Re 2) It's probably too complicated to fix that.

Re 1) This would be great, really great. Even geting rid of tagname rewrite all together would be nice in my opinion, because it prevent un ecessary errors and duplicated items (some with tatnames, some without.

Re 2) Thanks for the explanation, I understand it better now. Yess I think nothing can be done easily for this... But in a way that does not explain the fact that in random encounters, I end up with duplicated items too, some with a tatname it seems, and some without. Surely, because they are identical, but do not stack together..
 
Is it possible to report back to the game the actor (his/her name or tagname) of my team who initiated speech with a NPC? I would like to give a perk to the right person and use that info also for other regular triggers. Maybe having it stored into some new/reserved variable? Moreover, the main char. can be sneaking at the other side of the map.
 
Is it possible to report back to the game the actor (his/her name or tagname) of my team who initiated speech with a NPC? I would like to give a perk to the right person and use that info also for other regular triggers. Maybe having it stored into some new/reserved variable? Moreover, the main char. can be sneaking at the other side of the map.

Not yet. Eventually I'll be trying to add a hook at triggering events (using an in-world object, or starting a conversation), but I don't have that yet.

A short-term option, which still isn't quite ready but is much closer to being done, would be to retrieve the NPC actor by name or tag, then do a distance comparison to everyone in the squad, giving the perk to the closest. It's already possible in FTSE to get an entity location, but not to retrieve an entity by tag or name. But that should be coming in 0.40, or shortly after.
 
Here is a great challenge for you (I never stop do I? ha!)! I am currently trying to setup my mod as a Mac OS application using WineBottler (Mouse cursor and videos are sooo laggy but, whatever) and I realize that for some reasons FOTSE is not launching properly. Some of the color modifications do seem to work, but strangely not all of them.

Also (and that is what I am the most concerned about), the script for keeping the Tagname, also the script "No items in starting inventory" does not work, so probably not a single patch are working?

As you are way more aware than me about this kind of stuff, do you have some clues on what could be happening? The standalone OSX app I created include Wine in itself and directly launch FT Improver.exe. I tried launching BOS.exe instead for the exact same results.

Thanks in advance.

Hugo
 
Last edited:
I wasn't able to see the screenshots - curious why only some color modifications would have worked.

Does the game produce a FTSE.log file when run this way? If so, can I get the log? If it doesn't, then it's possible the initial hook added by FTEInstaller isn't in place or isn't working correctly.
 
Oh sorry for some reasons NMA prevent me from adding screenshots...

I don't think it creates a log. There is a log there, but from two days ago, and it looks like this :

2019/02/02 19:03:37.969 FTSE version 0.30a started.
2019/02/02 19:03:37.969 Detected parameter: exeName
2019/02/02 19:03:37.969 Detected parameter: -w
2019/02/02 19:03:37.969 Applying patch Quartermaster is free
2019/02/02 19:03:37.969 Applying patch Sniper fix
2019/02/02 19:03:37.969 Applying patch Burst bug fix
2019/02/02 19:03:37.969 Applying patch Music blocked fix
2019/02/02 19:03:37.969 Applying patch Tag name fix
2019/02/02 19:03:37.969 Applying patch doNightPerson fix
2019/02/02 19:03:37.969 Applying patch Team Player/Loner fix
2019/02/02 19:03:37.969 Applying patch Color character portraits
2019/02/02 19:03:37.969 Applying patch High res patch
2019/02/02 19:03:37.969 Applying patch Encounter color fix
2019/02/02 19:03:37.969 Applying patch No starting inventory mod
2019/02/02 19:03:37.969 Successfully started LUA engine.
2019/02/02 19:03:37.969 Installing a hook at address 0x57b4ed
2019/02/02 19:03:37.969 Installing a hook at address 0x57cbb0
2019/02/02 19:03:37.969 Installing a hook at address 0x731ba2
2019/02/02 19:03:37.969 Installing a hook at address 0x67ee30
2019/02/02 19:03:37.969 Installing a hook at address 0x6ad6a0
2019/02/02 19:03:37.969 Installing a hook at address 0x6ada90
2019/02/02 19:03:37.969 Installing a hook at address 0x64eec1
2019/02/02 19:03:37.969 Installing a hook at address 0x614c3c
 
Ecran1.png

Ecran2.png

Ecran3.png

Ecran4.png
 
I think my bad screen interferes in the results, for example it is way to bright. But we can see that your full color portraits patch do work, some green texts in character screen show that something is not working properly in the text color patches, and, as I told you, I tested the tagname patch and It does not store the tagname properly, so no overhead text appear over the character with the tagname "LeJoueur", and the game "crash as it should" when I try to move an entity to the not existing "LeJoueur" tagname entity. There seem also to still be a scan line effect, even if I think you implemented a patch to remove it.
 
Here are my codes in case you want to see them :

ftse.lua

Code:
--[[
Leave these definitions alone - they are needed to interface
with the C++ DLL library.
--]]

ACTOR_TABLE_PERM = 0
ACTOR_TABLE_DERIVED = 1
ACTOR_TABLE_TEMPORARY = 2
ACTOR_TABLE_CURRENT = 3

COMBATLOG_SYSTEM = 0
COMBATLOG_FEW = 1
COMBATLOG_DEFAULT = 2
COMBATLOG_ALL = 3

--[[
The following code is used to convert between the internal
game timer (millisecond resolution) to in-game date and time.
--]]

month_end_days = { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}

function MsecToDayHMS(ms,scale)
    if scale > 0 then
      ms = ms * 3
    end
    d = (ms // 86400000)
    h = (ms // 3600000)%24
    m = (ms // 60000)%60
    s = (ms // 1000)%60
    ms = ms % 1000
    gametime = {
      year = 0,
      month = 0,
      day = d,
      hour = h,
      minute = m,
      second = s,
      msec = ms
    }
    return gametime
end

function AddBaseToGameTime(gametime)

    -- add base days, hours and minute
    gametime["minute"] = gametime["minute"] + 29
    gametime["hour"] = gametime["hour"] + 6
    gametime["day"] = gametime["day"] + 2197*365

    -- normalize hours and minutes
    if gametime["minute"] > 59 then
      gametime["minute"] = gametime["minute"] - 60
      gametime["hour"] = gametime["hour"] + 1
    end
    if gametime["hour"] > 23 then
      gametime["hour"] = gametime["hour"] - 24
      gametime["day"] = gametime["day"] + 1
    end
    
    -- calculate year and day within year
    gametime["year"] = gametime["day"]//365
    gametime["day"] = gametime["day"] % 365 + 1

    -- Get month and day within month
    mo = gametime["day"] // 30
    if mo == 0 or gametime["day"] > month_end_days[mo] then
      mo = mo + 1
    end
    if mo > 1 then
      gametime["day"] = gametime["day"] - month_end_days[mo-1]
    end
    gametime["month"] = mo
    return gametime
end

-- Burst bug fix code
function CalculateChance(chance,intended,angle)
  if intended == false then
    chance = math.min(chance,40)
    if angle > 5.0 then
      chance = math.floor(chance * (21.3 - angle) / 16.3)
    end
  end
  return chance
end

function CalculateShare(chance)
  return math.min(chance,70)   
end

function OnBurstAttack(attacker,shots,target_table)
  results = {}
  totalshare = 0
  for _,tgt in ipairs(target_table) do
    share = CalculateShare(CalculateChance(tgt["hit_chance"],tgt["intended"],tgt["angle"]))
    totalshare = totalshare + share
  end
  totalshare = math.max(totalshare,100)
  shotsleft = shots
  for _,tgt in ipairs(target_table) do
    chance = CalculateChance(tgt["hit_chance"],tgt["intended"],tgt["angle"])
    tgtshots = math.min(shotsleft,math.max(1,math.floor(shots * CalculateShare(chance) / totalshare)))
    shotsleft = shotsleft - tgtshots
    myhits = 0
    for i=1,tgtshots do
      roll = math.floor(math.random()*100)
      if roll < chance then
        myhits = myhits + 1
      end
    end
    result = {id=tgt["actor"]["id"], hits=myhits }
    table.insert(results, result)
  end
  return results
end

math.randomseed(os.time())
-- Modifiable functions begin below -----------------


function DefaultStyleChanges(style)
  style:SetColorDefaultText(0.35,0.35,0.35)
  style:SetColorHighlightText(1.0,0.5,0.0)
  style:SetColorOptionsPages(0.20,0.20,0.20)
  style:SetColorPanelTitles(1.0,1.0,1.0) 
  style:SetColorBuffs(1.0,1.0,0.0)
  style:SetColorDebuffs(1.0,0.0,0.0)
  style:SetColorTags(1.0,1.0,0.0)
end

FTSE_config.json

Code:
{
  "_comment1": "Note: When editing this file, do not alter the patch data; only set the 'apply' field appropriately.",
  "_comment2": "Note: When applying additional patches, make sure the address matches the in-memory value where the",
  "_comment3": "patch is supplied, not the location within the EXE file.  To convert, add 0x400000 to the location within the EXE.",

  "patches": [
    {
    "name": "Quartermaster is free",
    "apply": "true",
    "changes": [
    {
    "offset": "5542dc",
    "patch": "ee9090"
    }
    ]
    },
    {
      "name": "Sniper fix",
      "apply": "true",
      "changes": [
        {
          "offset": "8a6c4c",
          "patch": "6c"
        }
      ]
    },
    {
      "name": "Burst bug fix",
      "apply": "true",
      "changes": [
        {
          "offset": "61959b",
          "patch": "01"
        }
      ]
    },
    {
      "name": "Music blocked fix",
      "apply": "true",
      "changes": [
        {
          "offset": "4d0487",
          "patch": "00"
        },
        {
          "offset": "4fb548",
          "patch": "00"
        },
        {
          "offset": "683be8",
          "patch": "00"
        }
      ]
    },
    {
      "name": "Tag name fix",
      "apply": "true",
      "changes": [
        {
          "offset": "4f6857",
          "patch": "56"
        }
      ]
    },
    {
      "name": "doNightPerson fix",
      "apply": "true",
      "changes": [
        {
          "offset": "57c7bf",
          "patch": "909090909090"
        }
      ]
    },
    {
      "name": "Team Player/Loner fix",
      "apply": "true",
      "changes": [
        {
          "offset": "571f9e",
          "patch": "809a89"
        },
        {
          "offset": "57cbb5",
          "patch": "89"
        },
        {
          "offset": "57ce4c",
          "patch": "e9b0020000"
        },
        {
          "offset": "57ced8",
          "patch": "e9540a000090747b9090"
        },
        {
          "offset": "57cf59",
          "patch": "eb7f399ed60e00007477"
        },
        {
          "offset": "57d101",
          "patch": "c64424140166397cc806e941fdffff"
        },
        {
          "offset": "57d931",
          "patch": "8a442414399ed20e0000e99ef5ffff"
        }
      ]
    },
    {
      "name": "Color character portraits",
      "apply": "true",
      "changes": [
        {
          "offset": "4bc8c4",
          "patch": "D905A0DE8B00D9059CDE8B008B863F0100008D4DC451EB45"
        },
        {
          "offset": "4bc93b",
          "patch": "D80598D57F00D9C0D9C08B863F0100008D55C452EB41"
        },
        {
          "offset": "745eb4",
          "patch": "9090"
        },
        {
          "offset": "718ba8",
          "patch": "d9c0d9c08d44e41cd95ce420d95ce424c605b7e08b0001d95ce41c508b8efa000000eb5f"
        }
      ]
    },
    {
      "name": "High res patch",
      "apply": "true",
      "changes": [
        {
          "offset": "4b345e",
          "patch": "7c"
        },
        {
          "offset": "4b3466",
          "patch": "7d"
        },
        {
          "offset": "654638",
          "patch": "7c"
        },
        {
          "offset": "654640",
          "patch": "7c"
        },
        {
          "offset": "65464c",
          "patch": "7c"
        },
        {
          "offset": "654654",
          "patch": "7c"
        }
      ]
    },
    {
      "name": "Encounter color fix",
      "apply": "true",
      "changes": [
        {
          "offset": "6ae3f4",
          "patch": "33c990"
        }
      ]
    },
    {
      "name": "No starting inventory mod",
      "apply": "true",
      "changes": [
        {
          "offset": "898F04",
          "patch": "000000000000000000000000000000000000000000000000000000000000000000"
        },
        {
          "offset": "89D494",
          "patch": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
        }
      ]
    }
  ]
}
 
Oh yes, forgot to mention. The red gun is a modification of the vanilla starting gun, that normally not appear because of the no inventory patch.
 
It does look like the engine isn't starting at all. I have to guess that maybe some of the effects were hex-edited into the EXE directly, because it wouldn't make sense for only part of the color portraits fix to have been applied by the engine.

We can try a couple of things first:

1) Double check that FTSE.DLL is in the same path as BOS.EXE.

2) Does the OSX app reside in the same file system directory as the rest of the files? Wondering if the game is looking for FTSE.DLL in the "current directory", which may be where the app started rather than where BOS.EXE is.

3) To rule out any file permission issue on the log file, try removing FTSE.log and starting the game again. This will confirm whether or not the log file is being produced.

If none of the above works, I can maybe try to give a manual hex edit to see if I can diagnose the DLL loading routine.
 
Thanks for the follow up on this!

So.. It is strange... The .DLL is in place. I also have the memory of having reintroduced the vanilla bos.exe prior to installing your last FOTSE version on my PC, so I am surprised here.

Now I just replaced bos.exe by another vanilla bos.exe I found on a GOG version to eliminate this variable, and the results are the same as those I shown you on the screenshots...

I also removed the log "FTSE.log", and after succesfully launching the game and played for a few seconds, I quit and checked and no log were created. Is the application being "packed" in a .app might be affecting this kind of log creation? Could there be some routine inside wine that prevent this kind of hooks like FOTSE being used?

I could manually hack most of this stuff directly in BOS.exe, but I am afraid about those very cool features I just started playing with, like the perks, that I will lose in the process.

I was recently able to apply (on PC, of course) all my 25 or so quest related perks to my main character using campaign variables, and this is a wonderful sight to witness. If we can bring that to MAC too, that will be just amazing.
 
Couple of things that are essential, but no one asks.

1. How do I use this? I saw all the number codes like 00017ecf81 and whatnot, and I've come to realized that I need to use HxD to make those numbers appear, but which file should I open with HxD? BOS.exe? FTSE.dll?
2. How do I role back to my original game with .bak file?
3. How do I change the portrait to be black and green instead of full color again?
4. I have two BOS.exe files. One with _HR, and the one without it, and I installed this game from Steam. Do I need to select both BOS.exe and BOS_HR.exe file to apply this... FTSE to both files? If I selected BOS.exe file during the installation, then I play the game with BOS_HR.exe file, will my game has all the FTSE related contents?

I know this is a 'modding' forum, but geez... People really are just assuming everyone knows what they're on about. This is not a noob friendly modding place like Nexusmod.
 
1. How do I use this? I saw all the number codes like 00017ecf81 and whatnot, and I've come to realized that I need to use HxD to make those numbers appear, but which file should I open with HxD? BOS.exe? FTSE.dll?

Unless you are specifically trying to add new hex edits (either through reverse engineering or hex fixes from other sources), you should not need to edit any of the hex number codes. Individual fixes can be enabled or disabled in the FTSE_config.json file by updating the value of the "apply" flag to "false".

2. How do I role back to my original game with .bak file?

The safest way is to rename the updated file (BOS.exe or BOS_HR.exe) to some other name (BOS.exe.modified), and rename the .bak file back to the original name.

3. How do I change the portrait to be black and green instead of full color again?

In FTSE_config.json, look for the following section:

Code:
    {
      "name": "Color character portraits",
      "apply": "true",
      "changes": [
        {
          "offset": "4bc8c4",

...

Change "apply": "true" to "apply": "false".

4. I have two BOS.exe files. One with _HR, and the one without it, and I installed this game from Steam. Do I need to select both BOS.exe and BOS_HR.exe file to apply this... FTSE to both files? If I selected BOS.exe file during the installation, then I play the game with BOS_HR.exe file, will my game has all the FTSE related contents?

If I remember correctly, the Steam version runs the _HR version of the game, so that would be the one that needs to be modified. And the changes made by FTSE will only take effect if the modified EXE is used - this allows for running with or without FTSE depending on which EXE is started.

I know this is a 'modding' forum, but geez... People really are just assuming everyone knows what they're on about. This is not a noob friendly modding place like Nexusmod.

Understood - FTSE in its current form is not at all end-user friendly. It's currently targeted for mod creators themselves, to add features to their mods. As I get more standalone bug fixes included, I can add a basic UI to toggle fixes on/off without needing to edit config files. This is probably a good idea anyway, since the same UI tool can validate and add/remove the startup code that the installer puts in place.
 
Back
Top