View Full Version : Logger - Withdrawals
ruff_hi Mar 07, 2008, 10:05 AM BtS has increased the unit withdrawals a lot, increased flanking and siege units that cannot kill units. The logger completely misses this items. I'm currently looking at this to get withdrawals into the logger.
There are two types of withdrawals ...
1) Siege unit has done maximum damage and withdraws
2) Unit with withdrawal chance runs away just before it gets killed
I'm looking for a review of the suggested text ...
1) "While attacking in Babylonian territory at Nippur, Catapult (3.68/5) decimates Babylonian Longbowman (x/6) (Prob Victory: 81.6%)"
2) "While attacking in Babylonian territory at Nippur, Catapult (0.14/5) escapes from Babylonian Longbowman (x/6) (Prob Victory: 81.6%)"
Re colour ... 1) would be darkred indicating victory while 2) would be red indicating defeat.
ruff_hi Mar 09, 2008, 09:49 AM best I can do ...
Logging by BUG Mod 2.11 (BtS 3.13)
------------------------------------------------
Turn 290/500 (1840 AD) [09-Mar-2008 10:47:33]
While attacking in Spanish territory at Seville, Cannon loses to Spanish Musketman (4.95/9) (Prob Victory: 6.7%)
While attacking in Spanish territory at Seville, Cannon loses to Spanish Longbowman (2.88/6) (Prob Victory: 57.6%)
While attacking, Cannon escapes from Spanish Maceman (Prob Victory: 64.5%)
While attacking, Cannon decimates Spanish Musketman (Prob Victory: 95.5%)
Battle Stats:
Units victorious while attacking : 0
Units victorious while defending : 0
Units withdrawing while attacking: 1
Units defeated while attacking : 2
Units defeated while defending : 0
Units escaping while attacking : 1
Dresden Nov 01, 2008, 01:35 AM :bump: So I just had to kick the hornet's nest and see if I could improve the autolog withdrawal logging... :hammer2:
I actually only have a fairly simple question or two but there's a ton of confusing background information that I want to have documented somewhere so here we go.
This is the "simple" version of how BTS determines combat in CvUnit::resolveCombat() and CvUnit::updateCombat().
Make some preliminary calculations and initialize the CombatDetails structures. Fire combatLogCalc event if a human is involved.
Do collateral damage to other units but keep everything secret from Python.
Run the actual combat rounds in a loop. For simplicity, I'm ignoring first strikes.
If defender won the round, check for possible attacker withdrawal:
If attacker should have died but had a successful withdrawal:
Do not actually cause any damage this round.
Do flanking damage to other units (also hidden from Python just like collateral.)
Update attacker experience due to the withdrawal
End the battle early; this is our "escape" withdrawal.
If withdraw unsuccessful or not applicable:
Inflict the damage on the attacker.
Update attacker's CombatDetails.
Fire combatLogHit event if a human is involved.
If attacker won the round, check for combatLimit() restrictions:
If defender's total damage would exceed attacker's combatLimit, force withdrawal:
Update attacker experience due to the withdrawal
Set defender's damage to the attacker's combatLimit
End the battle early; this is our "decimate" withdrawal.
Otherwise, process the attack normally:
Inflict full damage on the defender
Update defender's CombatDetails.
Fire combatLogHit event if a human is involved.
Check to see if somebody died. If they did:
Do flanking damage if the winner was the attacker; again, hidden from Python.
Update experience for the winner.
End the battle.
Check if somebody died.
If so:
Update statistics and war weariness.
Display appropriate combat result message.
Fire combatResult event.
If not:
Display appropriate withdrawal message.
Update attacker's movement points and mission status if he's still alive. I'm not entirely sure of the details here but somehow selectionGroupPushMission gets fired around this time. In the case of a resolved combat, it actually seems to get fired before the combatResult is fired but there's already a good workaround for that.
:crazyeye: Whew.
If you notice where the bolded event firings are, you will see the crux of our problems. We can detect that a withdrawal actually happened by tracking the combatLogCalc and combatLogHit events and reviewing their status when a selectionGroupPushMission event happens. (And boy am I glad ruff figured out how to do that long ago. :D) But in the case of a withdrawal, we don't have a pointer to the defending unit and we didn't get a combatLogHit on the final round so the details are sketchy. This is why the current implementation of relying on the last logged hit doesn't do a particularly good job of determining the type of withdrawal since the last logged hit was actually the next-to-last hit in the battle.
Since we know the criteria for the two withdrawal cases from the SDK battle calculations, we can bluff our way through most of it.
If the defender isn't badly hurt, we know it was an "escape" withdrawal and so the final round of combat was nullified; thus we can use the data from the round before to know both units' status.
If the attacker isn't badly hurt, we know it was a "decimate" withdrawal and so we can assume the defender has had max damage applied; so again the lack of final round data doesn't hurt us.
However, if both units are badly hurt we cannot be sure of what happened because of the lack of final round stats. Furthermore, we don't have a pointer to the defending unit and so we can't tell exactly how much damage it has taken. The best we can do is say it either has the damage it had on the last round or the max damage the attacker can inflict.
So the big question for today is how do we handle that third case? We could implement a generic withdrawal event, but should it be red like escapes, dark red like decimation, or some wacky third color? And what do we do about the defender's strength? Should we ignore it, pick one of the two possibilities, or give a range showing both? And how is it entered into the battle stats?
My gut instinct is to consider it an "escape" withdrawal for stats/coloring and perhaps use a range for the strength but I want to hear other opinions. We need something a little better than the following: ;)
While attacking in the wild, Cannon (3.00/12) withdraws from Barbarian Infantry (5.00/20 or maybe 4.00/20, we just don't effing know) (Prob Victory: 7.4%)
ruff_hi Nov 01, 2008, 06:54 AM hey ... here is an idea ...
Make some preliminary calculations and initialize the CombatDetails structures. Fire combatLogCalc event if a human is involved.
Do collateral damage to other units but keep everything secret from Python. Change the DLL to fire a suitable Python event
Run the actual combat rounds in a loop. For simplicity, I'm ignoring first strikes.
If defender won the round, check for possible attacker withdrawal:
If attacker should have died but had a successful withdrawal:
Do not actually cause any damage this round.
Do flanking damage to other units (also hidden from Python just like collateral.)
Update attacker experience due to the withdrawal
End the battle early; this is our "escape" withdrawal. Change the DLL to fire a suitable Python event
If withdraw unsuccessful or not applicable:
Inflict the damage on the attacker.
Update attacker's CombatDetails.
Fire combatLogHit event if a human is involved.
If attacker won the round, check for combatLimit() restrictions:
If defender's total damage would exceed attacker's combatLimit, force withdrawal:
Update attacker experience due to the withdrawal
Set defender's damage to the attacker's combatLimit
End the battle early; this is our "decimate" withdrawal. Change the DLL to fire a suitable Python event
Otherwise, process the attack normally:
Inflict full damage on the defender
Update defender's CombatDetails.
Fire combatLogHit event if a human is involved.
Check to see if somebody died. If they did:
Do flanking damage if the winner was the attacker; again, hidden from Python. Change the DLL to fire a suitable Python event
Update experience for the winner.
End the battle.
Check if somebody died.
If so:
Update statistics and war weariness.
Display appropriate combat result message.
Fire combatResult event.
If not:
Display appropriate withdrawal message. Change the DLL to fire a suitable Python event
Update attacker's movement points and mission status if he's still alive. I'm not entirely sure of the details here but somehow selectionGroupPushMission gets fired around this time. In the case of a resolved combat, it actually seems to get fired before the combatResult is fired but there's already a good workaround for that.
If you are getting withdrawal messages on a unit that cannot withdrawal (ie axe), then I would suggest we put in unit checking code to suppress the creation of the message. I thought I had something like that in there already.
Elkad Nov 01, 2008, 09:12 AM whatever you do, please don't misuse "Decimate". I'd love to have that withdraw info, but mangling the word to mean "almost all" is best left to talking airheads on CNN. A game with a large historical component should use that word, if at all, in the historical meaning.
Decimation originally refers to a punishment levied against Roman Legions by their own commanders. Generally for gross misconduct like cowardice in the face of the enemy. It has been used by other armies in other eras (including as recently as ww2).
Divide army (including officers and ncos) into groups of 10. Select 1 of each 10 by lot. Other 9 forced to beat him to death. Even the root, Deci, means 1/10th.
ruff_hi Nov 01, 2008, 09:17 AM ahh - I knew it meant 1/10 but I wasn't sure if it was 'reduce by 1/10' or 'reduce to 1/10'. Do you have another suggestion?
The Doc Nov 01, 2008, 01:29 PM ahh - I knew it meant 1/10 but I wasn't sure if it was 'reduce by 1/10' or 'reduce to 1/10'. Do you have another suggestion?
Maybe "wounds" or "damages" instead of "decimates"? :dunno:
Dresden Nov 01, 2008, 04:31 PM Regarding adding events: that is something I thought of myself too but since we don't have a custom DLL (yet ;)) and we also want the code to work as well as possible without a custom DLL, we still need to handle these things as-is. For what it's worth, I was also thinking a custom DLL would fire a unitUpgrade event too.
Regarding "decimate:" Why not simply say exactly what we mean?
While attacking in the wild, Cannon (9.00/12) withdraws after inflicting maximum damage to Barbarian Infantry (4.00/20) (Prob Victory: 7.4%)
EmperorFool Nov 02, 2008, 04:39 AM Why not simply say exactly what we mean?
Why start now? :mischief:
Elkad Nov 02, 2008, 05:08 AM cannon withdraws after crippling barbarian infantry?
cannon reduces barbarian infantry and withdraws?
ruff_hi Nov 02, 2008, 06:56 AM cannon withdraws after crippling barbarian infantryI like this.
Another option is ...
'Your Cannon forces the enemy forces to gather into groups of 10, then watches them as 9 beat the 10th to death."
EmperorFool Feb 19, 2009, 03:25 PM For what it's worth, I was also thinking a custom DLL would fire a unitUpgrade event too.
Done.
PieceOfMind, in his Advanced Combat Odds (http://forums.civfanatics.com/showthread.php?t=310415) DLL mod, uses withdraw to mean doing maximum damage and retreat to mean escaping. I like those and will use them in the event names.
I'd like to add real withdraw/retreat events to BULL and wanted to get some input. Do both need anything other than pAttacker and pDefender? Anything in particular I should look out for? I thought someone already posted the place in the DLL where I'll need to add this, but if someone knows for sure, please chime in.
CombatWithdraw ( pAttacker, pDefender )
CombatRetreat ( pAttacker, pDefender )
I may also add events for flanking and collateral damage. Do you want an event for each unit damaged/killed? Do you want the actual unit that was attacked (pDefender) passed along as well? I'm guessing yes and no:
CombatFlank ( pAttacker, pUnit, iDamage, bKilled )
CombatCollateral ( pAttacker, pUnit, iDamage )
ruff_hi Feb 19, 2009, 03:35 PM I'm assuming that you can get resulting HPs for both attacker and defender from withdrawal. Also, for flanking / collateral - number (and id - for their names) of units damaged.
EmperorFool Feb 19, 2009, 03:41 PM I'm assuming that you can get resulting HPs for both attacker and defender from withdrawal.
You will be passed the CyUnit for both, so yes.
Also, for flanking / collateral - number (and id - for their names) of units damaged.
Maybe you misunderstood my proposal, or are you requesting a separate event detailing how many units were flanked/bombarded before getting the events for each individual unit affected?
ruff_hi Feb 19, 2009, 03:49 PM My understanding of the events following a battle (your new events in blue) ...
unit battle
--> event showing combat odds (does it include withdrawal odds?)
--> event for each round of combat
--> event for kill (either)
--> event for withdrawal / escape
--> event for collateral damage on injured units (one event per unit injured?)
--> event for flanking damage on injured units (including if unit killed) (one event per unit injured?)
Is this what you are proposing? This is slightly different to my above post - maybe our thinking is coming together.
EmperorFool Feb 19, 2009, 03:56 PM Yes, that is my proposal. Flanking/collateral damage events will be fired for each unit affected. Note that if a unit withdraws or retreats, there is no event for unit killed (combatResult).
EmperorFool Feb 20, 2009, 01:29 AM I'm adding these now, but I want to double-check something.
The combatCollateral and combatFlanking events will all be fired before the combatResult/Retreat/Withdrawal event for the attacking unit.
For example, you attack with a Catapult, hitting a stack of 2 Axemen and 2 Spearmen. You will get these events:
combatLogCalc ( Catapult, Axeman1 )
combatLogHit, combatLogHit, . . .
< maximum damage on Axeman1 reached >
combatLogCollateral ( Catapult, Spearman1 )
combatLogCollateral ( Catapult, Spearman2 )
combatLogCollateral ( Catapult, Axeman2 )
combatWithdrawal ( Catapult, Axeman1 )
Also, I went with combatLogFoo for Collateral and Flank since, like Calc and Hit, they are parts of the combat and not the final result of the combat itself. If anyone has a strong opinion the other way, I'm open to new name suggestions.
EmperorFool Feb 20, 2009, 02:41 AM I've added all of these new events, but I leave it to our intrepid Autologgers to fix autologeventmanager. :goodjob:
|
|