Skip to content

Feature/missile non lethality#43

Open
drhaluu82-dev wants to merge 6 commits into
maxpetul:masterfrom
drhaluu82-dev:feature/missile-non-lethality
Open

Feature/missile non lethality#43
drhaluu82-dev wants to merge 6 commits into
maxpetul:masterfrom
drhaluu82-dev:feature/missile-non-lethality

Conversation

@drhaluu82-dev
Copy link
Copy Markdown
Contributor

@drhaluu82-dev drhaluu82-dev commented May 25, 2026

In Default (vanilla) Civ 3, if you set a unit as being a 'Cruise Missile', it will ALWAYS have lethal land/sea bombard, regardless of the Lethal Bombard Flags in the editor. So it's impossible to make a Cruise missile non-lethal. In the attached example, this Cruise Missile will always be land/sea Lethal, just based on its Cruise Missile flag, even though Lethal Land/Sea Bombardment isn't set.
cruise1
cruise2

This feature (maybe even bug fix) makes the Lethal Land Bombardment and Lethal Sea Bombardment flags actually matter for Cruise Missiles (just like they matter for all other units).

Config setting is "patch_cruise_missile_ignores_lethal_bombard_abilities" and I believe should be defaulted to FALSE, just in case a modder is unaware of the feature/bug fix. They can turn it on manually by setting this config value to TRUE.

If testing, don't forget to set this config setting to True first!

The code changes are highlighted in comments are "ToC-12" "ToC-13" or "ToC-13A".
ToC-12: Base code to ensure Lethal bombard settings in the editor matter for Cruise Missiles
ToC-13: AI adjustment to ensure AI does not waste missiles on 0 defense units that are out in the open (on a tile by themselves). Seems this is Civ 3 vanilla hardcoded, that missile units cannot kill 0 defense units (ex. workers) that are out the open. So this stops AI from attempting to fire missiles at such targets.
ToC-13A: Adjustment to small bug found when creating ToC-12 that allowed first missile attack to skip a declaration of war. this ensures that the warning pop up still occurs if attempting to bombard a previously allied civ with a missile, so that you must declare war first before engaging in bombard attack (Hidden Nationality ability still allows skipping of war declaration like in vanilla civ 3).

Missile Lethality functionality Tested and regression tested with vanilla civ 3 and the Tides of Crimson mod, works in game.

PR1

changed default setting for patch_cruise_missile_ignores_lethal_bombard_abilities = false.
comment-only update on ToC-12
Updated comment for patch_cruise_missile_ignores_lethal_bombard_abilities in config file, for a better description of feature.
@maxpetul
Copy link
Copy Markdown
Owner

This doesn't quite work. Your edit to patch_Fighter_find_actual_bombard_defender stops non-lethal cruise missiles from killing 1-HP units by preventing those units from being selected as targets for damage. However that only fully prevents lethal damage when cruise missiles have a rate-of-fire of 1. Otherwise, a unit with 2 or more HP could be selected as a target then killed by multiple hits.

Another issue is that much of the code you've inserted won't run because it's part of the regular bombard logic which is not used for cruise missiles. Cruise missiles have their own mostly separate code path. When Unit::bombard_tile is called for a cruise missile, it calls Unit::begin_bombarding_tile like always, then that method checks whether the unit is a cruise missile and, if so, calls Unit::strike_tile_as_cruise_missile and after returns false so the rest of Unit::bombard_tile is skipped. That means Fighter::do_bombard_tile is never called for cruise missiles. Your original approach of clearing the cruise missile flag in begin_bombarding_tile would have avoided this issue, but I wouldn't have liked that approach either as it would cut out the entire cruise missile logic and have made missiles use the standard bombard logic instead. That's a large unnecessary change in my opinion.

To make cruise missiles respect lethal bombard abilities, this should be all you need:

  • Replace the hardcoded true/true for the land_lethal/sea_lethal params passed to find_defender_against_bombardment. That function is called from four places. The two places where the game calls it to get the defender before applying damage are already redirected to patch_Fighter_find_actual_bombard_defender, you've handled those, that's fine. The other two calls are from Unit::ai_eval_bombard_target, which is part of the regular bombard logic and not used for cruise missiles, and from Unit::ai_eval_cruise_missile_target, which is of course the one you want to modify. Modifying that call should work to make the AI aware of this feature instead of your edit to patch_Unit_ai_eval_bombard_target (which won't run anyway because that's only for regular bombardment not cruise missiles). By the way, the way that the params for the lethal flags are hardcoded to true here makes me think it's not a bug that cruise missile strikes are always lethal. That looks like a deliberate choice.

  • Modify can_damage_bombarding, although that function already respects the lethal land & sea flags for cruise missiles since I didn't know they were ignored when I wrote it. Still, it should be modified to be consistent with everything else. That ensures that stack bombard and stealth attack bombard work properly.

  • Somehow modify the loop that applies damage after a cruise missile strike to stop before the target is killed in case the strike is non-lethal. This is the difficult part. The relevant method here is Fighter::do_cruise_missile_strike. I think the easiest approach would be to modify the call to rand_int that rolls to do damage on each round so that damage never happens when the target has 1 HP remaining and the cruise missile strike is not lethal. You'd have to drag that information in from elsewhere, probably easiest to intercept the earlier call to check_combat_anim_visibility since it's passed the cruise missile unit and the defender as parameters.

Do you have the Ghidra project? I forget who I've sent it to. If not, you won't be able to bring up do_cruise_missile_strike or find that other call to find_defender_against_bombardment. I'll help you out with that if you need it, it wouldn't take much time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants