• Welcome to Freedom Reborn Archive.
 

New FFX Attribute: BODY ARMOR

Started by stumpy, December 16, 2007, 09:41:27 PM

Previous topic - Next topic

stumpy

Okay, while avoiding some other work (heaven save me from priorities!), I took a look at this.

Here is some code for the BODY ARMOR attribute I proposed in another thread. The idea is for a variation on INVULNERABILITY that wears down as it takes repeated damage above its rated value. This reflects comic characters who start out with nice armor or a shield or bulletproof vest or whatever and then, after a battle or two, it's pretty much shredded and not providing much protection.

In this case BODY ARMOR starts out just like INVULNERABILITY. But, its effectiveness is reduced by 10% (rounded up) of the difference in damage and its rating, every time the armor's current rated damage is exceeded. So, if I have 20 points of BODY ARMOR and I am hit by a 15 damage attack, I take no damage and I am ready for the next one. But, if I take a 25 damage attack, then only 5 points of it get past the armor, but my armor has been damaged and next time it will only absorb 19 points of damage (it's rating was exceeded by 5 point and 10% of 5 rounded up is a 1 point reduction in the armor). And so on until it is gone.

This means that 5 points of body armor will be gone pretty quickly. (The 2 and 5 point BODY ARMOR versions are mostly there to allow folks to fine-tune their combo attributes, e.g. combine to make 7, 15, etc. point BODY ARMOR combos.). But, 30 points is likely to last through most of a mission, since it would take many attacks to get rid of it and those attacks would have to do pretty high damage early on.

Obviously, BODY ARMOR should be cheaper than INVULNERABILITY, though at higher ratings it is still a big combat advantage. I priced the cost of the attribute by taking half the cost of the corresponding INVULNERABLE attribute and then subtracting another 100 CP. So, if one were figuring the cost for a combo that gave 50 points of BODY ARMOR, it would be 8000 (the cost of 50 points of INVULNERABILITY) divided by 2, then minus 100, for a total of 3900 CP. The FFEdit CP costs for the built-in versions are given below, along with their FFEdit names.

The code supports FFX removability and is compatible with the INVULNERABLE and PHYSICAL RESISTANCE attributes. For characters with both BODY ARMOR and one of those attributes, the damage comes off of the BODY ARMOR first to reflect it being the "outer shell" of protection, before any inborn toughness is hit. So a character with 10 points of INVULNERABILITY and 10 points of BODY ARMOR will take no damage from a 15 point attack, but his BODY ARMOR rating would drop to 9 points next time, since the 15 points of damage exceeded its rating.

Installation is fairly typical for FFX attributes. (Sorry I couldn't do this as a plug-in, but a change to the Damage Management code is required.) The following code goes in ..\ffx3\missions\scripts\ffx.py (open using a plain-text editor like Notepad, make a backup before making any changes). The first part is a replacement for the DamageManagement() function. Search for ### Damage Refund Management, then replace that whole block of code with the following.
############### Damage Refund Management Callback #########
# Currently used by Invulnerable, Temporary Invulnerability and Tough Guy 2
# stumpy 2007-12-16: added BODY ARMOR to the mix.

def DamageManagement(event):
    char=event.object
    lasthealth = FFX_ObjectGetAttr(char,'ivlastdam')

    # BODY ARMOR: invulnerability that wears down through repeated damage
    BAPoints = FFX_ObjectGetAttr(char,'BAPoints',0)
    if BAPoints > 0:
        health = Object_GetAttr(char,'health')
        damage = lasthealth - health
        if Object_IsAlive(char):
            if damage>0:
                payback=BAPoints
                if payback>damage:              # don't refund more damage than we took
                    payback=damage
                if payback+health > lasthealth: # don't bring char above pre-damage health
                    payback = lasthealth - health
                Object_SetAttr(char,'health',health+payback)
                if damage > BAPoints:
                    # took more damage than armor's rating, armor is damaged
                    BAPoints = max( BAPoints - int(0.99+0.10*(damage-BAPoints)), 0 )
                    FFX_ObjectSetAttr(char,'BAPoints',BAPoints)
       
    # toughguy2: fractional damage refund
    if FFX_ObjectGetAttr(char,'tg2Fraction',0) > 0.0:
        health = Object_GetAttr(char,'health')
        damage = lasthealth - health
        if Object_IsAlive(char):
            if damage>0:
                payback = int(damage*FFX_ObjectGetAttr(char,'tg2Fraction')+0.5)
                if payback>damage:              # don't refund more damage than we took
                    payback=damage
                if payback+health > lasthealth: # don't bring char above pre-damage health
                    payback = lasthealth - health
                Object_SetAttr(char,'health',health+payback)

    # invulnerability: flat damage refund
    if FFX_ObjectGetAttr(char,'invPoints',0):
        health = Object_GetAttr(char,'health')
        damage = lasthealth - health
        if Object_IsAlive(char):
            if damage>0:
                payback=FFX_ObjectGetAttr(char,'invPoints')
                if payback>damage:              # don't refund more damage than we took
                    payback=damage
                if payback+health > lasthealth: # don't bring char above pre-damage health
                    payback = lasthealth - health
                Object_SetAttr(char,'health',health+payback)

    FFX_ObjectSetAttr(char,'ivlastdam',Object_GetAttr(char,'health'))               
    RegDamage(char,'DamageManagement')


Then, at the bottom of the file, add the following code
######################################## BODY ARMOR ###########################################
# stumpy 2007-12-16: See http://freedomreborn.net/archive/index.php?topic=45553.0
# stumpy 2007-12-19: Modified so that BA rating is reduced in proportion to excess damage

# The idea is for invulnerability that wears down as more damage is
# taken, reflective of real armor, shielding, etc. that gets
# perforated, cracked, abraded and generally just starts coming apart
# under repeated punishment. The scheme used here is that the
# character starts with N points of BODY ARMOR that acts just like N
# points of INCULNERABILTY. But, whenever the armor takes a shot that
# does more than its rated damage, it's protective value N is
# decreased by damage-N, rounded up. So, 30 points of BODY ARMOR that
# takes a 40 point shot will be reduced by 1 point (10% of 40-30) to
# 29 points of BODY ARMOR. If that same armor had taken a 50 point
# shot, it would be reduced by 2 points to have a new rating of 28.
#
# BODY ARMOR is compatible with both INVULNERABILITY and PHYSICAL
# RESISTANCE. The damage to BODY ARMOR comes off *before* damage to
# the other attributes. In other words, a character's BODY ARMOR is
# not protected by his personal INVULNERABILITY or PHYSICAL
# RESISTANCE.

# FFEdit (attribute names, costs) and strings.txt entries:
# (Note for combo attribs: cost is half the cost of the corresponding INVULNERABLE attribute, minus 100 CP)
# (bodyarmor02, 100 CP)
# ATTRIB_BODYARMOR02_01, BODY ARMOR (02 points)
# ATTRIB_BODYARMOR02_DESC_01, you have gear (armor, shields, etc.) that absorbs punishment for you, but gets worn down by damage exceeding its rating.
# (bodyarmor05, 275 CP)
# ATTRIB_BODYARMOR05_01, BODY ARMOR (05 points)
# ATTRIB_BODYARMOR05_DESC_01, you have gear (armor, shields, etc.) that absorbs punishment for you, but gets worn down by damage exceeding its rating.
# (bodyarmor10, 650 CP)
# ATTRIB_BODYARMOR10_01, BODY ARMOR (10 points)
# ATTRIB_BODYARMOR10_DESC_01, you have gear (armor, shields, etc.) that absorbs punishment for you, but gets worn down by damage exceeding its rating.
# (bodyarmor20, 1150 CP)
# ATTRIB_BODYARMOR20_01, BODY ARMOR (20 points)
# ATTRIB_BODYARMOR20_DESC_01, you have gear (armor, shields, etc.) that absorbs punishment for you, but gets worn down by damage exceeding its rating.
# (bodyarmor30, 1900 CP)
# ATTRIB_BODYARMOR30_01, BODY ARMOR (30 points)
# ATTRIB_BODYARMOR30_DESC_01, you have gear (armor, shields, etc.) that absorbs punishment for you, but gets worn down by damage exceeding its rating.

def initbodyarmor(char, rating, update=0, remove=0):
    if remove:
        BAPoints = max(FFX_ObjectGetAttr(char,'BAPoints',0)-rating,0)
        BaseBAPoints = max(FFX_ObjectGetAttr(char,'BaseBAPoints',0)-rating,0)
        FFX_ObjectSetAttr(char,'BAPoints',BAPoints)
        FFX_ObjectSetAttr(char,'BaseBAPoints',BaseBAPoints)
        return
    if update==0:
        BAPoints = FFX_ObjectGetAttr(char,'BAPoints',0)+rating
        BaseBAPoints = max(FFX_ObjectGetAttr(char,'BaseBAPoints',0)+rating,0)
        if not FFX_ObjectGetAttr(char,'DamageManagement',0):
            FFX_ObjectSetAttr(char,'ivlastdam',Object_GetAttr(char,'health'))
            RegDamage(char,'DamageManagement')
            FFX_ObjectSetAttr(char,'DamageManagement',1)
        FFX_ObjectSetAttr(char,'BAPoints',BAPoints)
        FFX_ObjectSetAttr(char,'BaseBAPoints',BaseBAPoints)

def initbodyarmor02(char, update=0, remove=0):
    initbodyarmor(char, 02, update, remove)

def initbodyarmor05(char, update=0, remove=0):
    initbodyarmor(char, 05, update, remove)

def initbodyarmor10(char, update=0, remove=0):
    initbodyarmor(char, 10, update, remove)

def initbodyarmor20(char, update=0, remove=0):
    initbodyarmor(char, 20, update, remove)

def initbodyarmor30(char, update=0, remove=0):
    initbodyarmor(char, 30, update, remove)


Add the following attributes and costs to the Attributes list in FFEdit.
    bodyarmor02, 100 CP
    bodyarmor05, 275 CP
    bodyarmor10, 650 CP
    bodyarmor20, 1150 CP
    bodyarmor30, 1900 CP

And, finally, add the following strings to ..\ffx3\lang\english\stings.txt.
ATTRIB_BODYARMOR02_01, BODY ARMOR (02 points)
ATTRIB_BODYARMOR02_DESC_01, you have gear (armor, shields, etc.) that absorbs punishment for you, but gets worn down by damage exceeding its rating.
ATTRIB_BODYARMOR05_01, BODY ARMOR (05 points)
ATTRIB_BODYARMOR05_DESC_01, you have gear (armor, shields, etc.) that absorbs punishment for you, but gets worn down by damage exceeding its rating.
ATTRIB_BODYARMOR10_01, BODY ARMOR (10 points)
ATTRIB_BODYARMOR10_DESC_01, you have gear (armor, shields, etc.) that absorbs punishment for you, but gets worn down by damage exceeding its rating.
ATTRIB_BODYARMOR20_01, BODY ARMOR (20 points)
ATTRIB_BODYARMOR20_DESC_01, you have gear (armor, shields, etc.) that absorbs punishment for you, but gets worn down by damage exceeding its rating.
ATTRIB_BODYARMOR30_01, BODY ARMOR (30 points)
ATTRIB_BODYARMOR30_DESC_01, you have gear (armor, shields, etc.) that absorbs punishment for you, but gets worn down by damage exceeding its rating.

And then recompile the language files in FFEdit.

BTW, I toyed with the idea that a hero point use should reset the body armor rating back to it's original rating, i.e. that the hero point should regenerate the armor. It's easy enough to do (though it requires a change to cshelper.py), but it didn't seem quite right to me that a character gets new armor in the middle of a mission...

Anyway, this is a first pass at this, but I think it should generally work. Let me know if it does or if it causes trouble.

Xenolith


yell0w_lantern

Verrrrrry interesting. I may have to use this for Batman.

Epimethee


Xenolith

I think I'm going to swap out all my Invulnerables for Body Armor.  I think it will better reflect guys wearing out or getting beat up during the course of the battle.  Thanks again.

stumpy

I've played around with this in the RR and I find that BODY ARMOR with some level of actual INVULNERABILITY works well for many characters. For those characters, it sort of reflects that their armor's ability to save them from physical damage diminishes as it gets beaten up, but there's always enough left to provide some protection.

And, obviously, there are characters whose resistance to damage is basically innate. In other words, even after 50 blows from Hulk, Superman will still take no damage from gunfire. For that sort of resistance, I would probably stick to INVULNERABILITY.

I have also been toying with the idea of having the armor's effectiveness reduced by a straight one point for every hit that exceeds its rating, rather than by 10% of its current value, just so that the higher initial levels last longer. I'm not sure if that's a better way or not, but I'm open to suggestions.

bearded

Quote from: stumpy on December 19, 2007, 05:11:54 PM
...the armor's effectiveness reduced by a straight one point for every hit that exceeds its rating...
this sounds like the better option.
how hard would it be to tie powers into the rating?  like you have powers which diminish with the armor.

stumpy

How do you mean? The BODY ARMORed character's powers, or the power used to attack him. The former is somewhat doable, in that you could modify the attribute according to what powers the character possesses, but not easily based which power he is using at a given time. The latter is not practically doable, for mostly the same reasons that we don't have INVULNERABILITY only to a choosable damage types. In other words, having armor that defends against a shrapnel (piercing) grenade but not against an energy beam is not really an option.

bearded

the first.  even if it didn't apply to specific powers, what about an armor rating that added to all powers?  or even stats?  as the rating went down, the rating bonus would as well.  when the armor was gone, you'd have your base powers.
or, with the rating totally down, maybe you could 'jinx' your powers away.

Xenolith

I like the % per exceedance.  I think it will keep guys around a little longer...  Maybe the % could run opposite of the body armor.  For example, guys with 5 body armor would lose 20% per, and guys with 20 body amror would loose 5% per.  Seems to me the higher BA guys would wear down more slowly.  My 2 cents anyway.

And I do like having a baseline Invulnerability in there, too.

stumpy

bearded:

This is one of those things that may be doable, but it strikes me as kind of a bookkeeping nightmare with states and customization. What I mean by that is that the code has to keep track of the states of all sorts of things and what they started out as and what they are now and what they might have to go back to and to keep track of them when they can take many forms, like powers, stats, attributes, etc. Like I said, it may be doable, but it's the sort of coding that can result in inconsistent behavior.

The better solution is probably one of the attributes like DEFENSE MECHANISM or ACCIDENTAL CHANGE, which is intended for this sort of thing. It should be easy to write a query function like isBodyArmorGone() to use to trigger the changes.

Xenolith:

I don't know if you intended it this way, but your example works out to one point of BA rating lost each time, just like the flat method. ;)

Initially, I liked the 10% method because it reflects the armor taking more damage earlier on and then slowly being worn down. But I'm not sure that's how it ends up seeming during play. A character with 40 points of BA loses 4 points the first three times the BA's rating is exceeded and then he is down to 28. Then he looses 3 points each time and he is down to 19, then 2 points until he is at 9, then 1 until it's gone. In other words, it sort of does what I wanted, but it doesn't stay at the high rating very long. And it bugs me that the armor looses effectiveness so fast at the higher ratings, even if the attacks are only exceeding that rating by a point or two.

In the real world, the best thing to do would probably be to reduce the armor's rating by 10% or so of the damage taken (not of the armor's rating) each time the rating is exceeded. So, bigger blows do more damage to the armor, just as they would to anything else.

Honestly, on consideration, that's the way to do things. I should play around with it and work out details like whether the reduction to the armor should be a percent of the total damage of the attack or of the damage that exceeded the rating. In other words, if someone with 20 points of BODY ARMOR is hit by a 15 point shot, nothing happens and the armor's rating stays the same. But, if he is hit by a 50 point attack, should the reduction in the armor's rating be based on the 50 points of the attack or on the 30 points of the attack that exceeded the rating? I am tempted to go with the latter. In other words, if we are using ten percent, that second attack would reduce the armor's rating by 3 points, but an attack that did 30 points would only reduce the rating by 1 point (10% of the 10 points by which the attack exceeded the rating).

Xenolith

I misunderstood what you meant by point for point.  What I thought you meant was that if the Hulk hits a guy for 375 points of damage, then BA would take care of, say, 20 points of damage, but the rest would go through, while stripping all 20 points of BA.  What I was trying to say was that even if the Hulk hits the guy for 375 points of damge, only 5% (1 point) of the 20 BA would be depleted...and the rest of the damage would go through.  Probably not a good example, because the target its going to get KO'd anyway...  I think the slower degredation of the BA was what I was looking at.  Like the punch hit a specific spot, and the chance of hitting there again was slim.

So lets see, a gunshot hits a guy for 21 points of damage.  The target has BA of 20.  One point would go through.  The BA would drop to 18 (10% loss), by one (point for point exceeding the BA), or 19 (5% loss). 

If that same target was hit by the 21 point bullet, and only had a BA of 5, then 16 points would go through.  The BA would drop to 4.5 or 5? (10% loss), by 16 points (stripping it point for point, exceeding the BA), or 4 (20% loss).

Now whether its 10% before damage, after damage, or whatever, I think you'll have to just go with what you like.  I'm not very good at scripting, so I'll never change it anyway.   :rolleyes:


stumpy

Okay, I changed the code above to reflect the armor being reduced by 10% (rounded up) of the damage it takes in excess of its current rating, as proposed in my last post. Thus, someone with 20 points of BODY ARMOR who takes an attack doing 20 or less points of damage will be undamaged and the armor stays the same. If the damage exceeds the armors rating by between 1 and 10 points, the armor loses 1 point from is rating for next time. If the damage exceeds the rating by between 11 and 20 points, the armor loses 2 points from its rating. And so on, so that the armor will last forever if no attacks exceed its rating and it will last for a while if the attacks do damage just above its rating. But, if many attacks are doing 40 or 50 points of damage over its rating, it will be gone pretty quickly. A 5 point kevlar vest is going to be toast after one shot from Mjolnir. ;)

Also, I added some query functions (isBodyArmorHalf(), isBodyArmorQuarter(), and isBodyArmorGone()) to be used as triggers for characters who have BODY ARMOR. They test whether the armor's rating has been reduced to half of its original rating, a quarter of its original rating or if it's totally destroyed.

These functions should probably go in the section of ffx.py with the other query functions. Search for def isParasite and put these below that function (after the return 0).
# stumpy 2007-12-19: Added for use with BODY ARMOR
# Body armor is gone
def isBodyArmorGone(char):
    return FFX_ObjectGetAttr(char,'BAPoints',0) < 1

# Body armor is down to half or less of its initial rating
def isBodyArmorHalf(char):
    return FFX_ObjectGetAttr(char,'BAPoints',0) <= FX_ObjectGetAttr(char,'BaseBAPoints',1)/2

# Body armor is down to one-quarter or less of its initial rating
def isBodyArmorQuarter(char):
    return FFX_ObjectGetAttr(char,'BAPoints',0) <= FX_ObjectGetAttr(char,'BaseBAPoints',1)/4

Xenolith

Playing around with this...

It really fills in the gap between Invulnerability and PD/AD.  I'm very happy with this attribute.

wickerman

This is outstanding stumpy.  I really am digging this for Gorgon in the Metal storm mod.  He has a baseline toughness, but often 'armors up' by using his petrifying gaze on himself to turn his skin to pure rock.  Now he can have that outer shell smashed away and still maintain his 5 or so points of invulnerability...

thanks a million.