[Solved (work around)] ZScript How to Set Actor DamageFactor dynamically

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Please bear in mind that the people helping you do not automatically know how much you know. You may be asked to upload your project file to look at. Don't be afraid to ask questions about what things mean, but also please be patient with the people trying to help you. (And helpers, please be patient with the person you're trying to help!)
Post Reply
peewee_RotA
Posts: 407
Joined: Fri Feb 07, 2014 6:45 am

[Solved (work around)] ZScript How to Set Actor DamageFactor dynamically

Post by peewee_RotA »

Hi, I'm looking for help on how to set a named damage type's DamageFactor dynamically.

I currently have an item that modifies damage on monsters, but I realized it would be better if I could add a DamageFactor for these damage types since I use that number elsewhere on another item.

So far I cant find any kind of set damagefactor method in zscript.

Basically here is how you define it in properties:

Code: Select all

Actor RaiDoom : DoomImp replaces CellPack
{ 
  Health 200 
  +MISSILEMORE
  +MISSILEEVENMORE
  Speed 16 
  DamageFactor "Pikachu", 0.2  //it's not very effective... 
  DamageFactor "Squirtle", 1.8  //it's super effective! 
}
But I'm looking to modify it in an item apply, like this:

Code: Select all

    override bool Use(bool pickup)
    {
        Owner.SetDamageFactor("fire", 0.25);
        Owner.SetFamageFactor("ice", 2.0);
        return false;
    }
Any way to do this?
Last edited by peewee_RotA on Sun May 19, 2024 4:27 pm, edited 1 time in total.
Jarewill
 
 
Posts: 1853
Joined: Sun Jul 21, 2019 8:54 am

Re: ZScript How to Set Actor DamageFactor dynamically

Post by Jarewill »

While I don't know if it's possible to modify damage types on the fly, you can however make an item with a ModifyDamage override that applies its own damage factors.
For example:

Code: Select all

//This is the base class for the damage modifying item
Class DamageModifier : Inventory{
	Override void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags){
		If(!passive){Return;}
		newdamage = ApplyDamageFactors(self.GetClass(),damageType,damage,damage);
	}
}

//This is how you can utilize it to create a specific damage type modifier: (Also works in DECORATE)
Class DamageModifierRaiDoom : DamageModifier{
	Default{
		DamageFactor "Fire", 0.25;
		DamageFactor "Ice", 2.0;
	}
}

//And you can give it to enemies using an event handler:
Class DamageModifierHandler : EventHandler{
	Override void WorldThingSpawned(WorldEvent e){
		If(e.Thing is "Cacodemon"){
			e.Thing.GiveInventory("DamageModifierRaiDoom",1);
		}
	}
}
peewee_RotA
Posts: 407
Joined: Fri Feb 07, 2014 6:45 am

Re: ZScript How to Set Actor DamageFactor dynamically

Post by peewee_RotA »

Thanks for the example. It looks like the damage factors are on the item, so they only apply when ModifyDamage is run on that item.

The root cause of my problem is that Item #1 makes a calculation based on damage done and Item #2 modifies the damage.

No matter what I do, Item #1's ModifyDamage happens before Item #2's Modify damage. So the changes from the item don't take effect until too late.
User avatar
Player701
 
 
Posts: 1710
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: ZScript How to Set Actor DamageFactor dynamically

Post by Player701 »

peewee_RotA wrote: Fri Mar 08, 2024 5:16 pm The root cause of my problem is that Item #1 makes a calculation based on damage done and Item #2 modifies the damage.

No matter what I do, Item #1's ModifyDamage happens before Item #2's Modify damage. So the changes from the item don't take effect until too late.
I'm not sure if I completely understand your problem, but am I correct in assuming that both Item #1 and Item #2 belong to the same owner?

If they do, then the order of ModifyDamage calls depends on the order the items are situated in the owner's inventory.

So, if you want to ensure that a certain item's ModifyDamage is always called first, your item needs a way to maintain its position in the beginning of the inventory chain. Which can be accomplished with the following code:

Code: Select all

class AlwaysFirstItem : Inventory
{
    override void Tick()
    {
        if (Owner != null && Owner.Inv != self)
        {
            for (let ii = Owner.Inv; ii != null; ii = ii.Inv)
            {
                if (ii.Inv == self)
                {
                    ii.Inv = Inv;
                    Inv = Owner.Inv;
                    Owner.Inv = self;
                    break;
                }
            }
        }
    
        Super.Tick();
    }
}
Note that, for obvious reasons, this would only work if you have only one such item class. If you need to apply effects from multiple items in a consistent order, it might perhaps be feasible to have a "master" item that serves as the entry point e.g. via ModifyDamage, which runs custom code that uses FindInventory and queries the items it finds in the exact order that's necessary to produce the desired result.
peewee_RotA
Posts: 407
Joined: Fri Feb 07, 2014 6:45 am

Re: ZScript How to Set Actor DamageFactor dynamically

Post by peewee_RotA »

That's genius, thanks! That helps me solve a different issue.


For this issue, one item is on the player and one item is on the monster. The player item is using modify damage to count up damage done to increase his XP. The monster item later reduces the damage if it is a certain type, i.e. fire monsters reduce fire damage.

The damage counter increases first with the unmodified damage, then sometime later the monster reduces the damage.

If I could add a damage factor, I know this would be taken into account, and I could use the ApplyDamageFactors function where needed.
User avatar
Player701
 
 
Posts: 1710
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: ZScript How to Set Actor DamageFactor dynamically

Post by Player701 »

peewee_RotA wrote: Sat Mar 23, 2024 4:38 am The player item is using modify damage to count up damage done to increase his XP.
Wouldn't it be better to use the WorldThingDamaged event for that?

AFAIK, this event is fired after the damage has already been done, so you should be able to obtain the final damage value from there.
peewee_RotA
Posts: 407
Joined: Fri Feb 07, 2014 6:45 am

Re: ZScript How to Set Actor DamageFactor dynamically

Post by peewee_RotA »

Thanks, I'll give it a try.

Quick question, does that run in the play scope? I call a lot of player update methods if a level up is reached and I know that can be a challenge from events.
User avatar
Player701
 
 
Posts: 1710
Joined: Wed May 13, 2009 3:15 am
Graphics Processor: nVidia with Vulkan support
Contact:

Re: ZScript How to Set Actor DamageFactor dynamically

Post by Player701 »

peewee_RotA wrote: Sat Mar 23, 2024 7:28 amQuick question, does that run in the play scope? I call a lot of player update methods if a level up is reached and I know that can be a challenge from events.
Yes, it does, so you shouldn't have any trouble updating the player's state from there.
Post Reply

Return to “Scripting”