#How to develop brand new damage system and attribute system?

1 messages · Page 1 of 1 (latest)

grizzled ivy
#

I want to develop my own attribute system and damage system. For instance, the three basic attribute is: fire,frost,thunder. Every fire gives the player 1 attack, every frost gives the player 100 max health. every thunder gives the player 1/100 attack speed ( if you have 100 thunder, then you attack once more per second). When dealing with damage, there is no armor or magic resist like things. So I think there are some todos:

  1. hide all the original game attribute system and damage system
  2. develop my own AttributeManager class and DamageManager class
  3. take over the attack event of the game, and apply my damage
  4. etc.....(don't know)

Are there any repository that i can reference? If not, how could i develop?

median silo
#

You could remake the entire system, or you could override the current attributes
For example, rename strength/agility/intelligence to fire/frost/thunder
Change the stats gained by them (eg make every hero a strength hero and remove the HP gain)
Then you just need to tweak the hud icons and labels instead if having to completely remake it
For damage, you could remove all sources of armour and mr, or make all damage pure

grizzled ivy
#

thanks for your help ~ I am making my own attribute system, and I want every one strength give 20 max health. modifier code like below. However, when i press T to change the strength (implement in another file), the health leaves unchange ( the GetModifierHealthBonus function only called once). Is there a way to calculate the health bonus dynamically?

@registerModifier()
export class modifier_custom_attack_damage extends BaseModifier {

    IsHidden(): boolean {
        return false;
    }

    // Not a debuff
    IsDebuff(): boolean {
        return false;
    }

    // Cannot be purged
    IsPurgable(): boolean {
        return false;
    }

    // Declare functions to listen to
    DeclareFunctions(): ModifierFunction[] {
        return [
            ModifierFunction.ON_ATTACK_LANDED,
            ModifierFunction.HEALTH_BONUS
        ];
    }

    // Calculate health bonus based on custom strength
    GetModifierHealthBonus(): number {
        if (!IsServer()) return 0;

        const parent = this.GetParent();
        if (!parent.IsHero()) return 0;

        const playerID = parent.GetPlayerOwnerID();
        const customStrength = safeAttributeManager.getStrength(playerID);
        
        // Each point of strength increases health by 20 (adjustable as needed)
        const healthPerStrength = 20;
        const bonusHealth = customStrength * healthPerStrength;
        
        print(`[CustomAttributes] Strength: ${customStrength}, Health bonus: ${bonusHealth}`);
        return bonusHealth;
    }
    
    OnAttackLanded(event: ModifierAttackEvent): void {
        ......
    }
    
    OnCreated(): void {
        if (IsServer()) {
            // Check for attribute changes every half second
            this.StartIntervalThink(0.5);
        }
    }
    
    OnIntervalThink(): void {
        if (IsServer()) {
            const parent = this.GetParent();
            parent.CalculateGenericBonuses();
        }
    }
}```
limber owl
#

There is two functions for stats recalc:
CalculateGenericBonuses (for every unit except heroes)
CalculateStatBonus(true) (for heroes only)
You called first one for hero and thats why hp unchanged

#

There is also similar bad design for creep heroes/heroes/creeps: there is health_bonus and extra_health_bonus and you need pick one of them based on unit type:
hero: extra_health_bonus?
unit: health_bonus?
creep hero: health_bonus?
(check yourself what works now)

#

Your code also have two issues:

  1. You start interval think server side only and in OnIntervalThink check for side for no reason (it will be always server)
  2. You return 0 for bonus health at client side that will resilt in wrong hp displayed because panorama can't get actual health bonus value
grizzled ivy
#

thanks~ i have changed to CalculateStatBonus and it works. the second issue you mentioned, how do i fix it? Besides, the hp displayed works at client side now.

#

when I press T to add strength the hp changed as i want. so Why there is the second issue?

limber owl
#

Probably because hp is special thing

#

Anyway you have two ways to fix that issue in future:

  1. Use stacks to transmit server side value because they available at both sides
  2. Use transmitters if you need more than one server side only value (your case i think)
#

Be aware also while playing with bonus hp that due to valve code heroes hp can go into negative area (with enough -bonus hp debuff) that will result in broken hero (creep heroes have min health = 0)

#

This issue will also happen if you wanted to display actual modifier bonus in tooltip via property. It will show 0 with your current code

grizzled ivy
#

the implement of the attributemanager is just a class with Strength Alility and Intellect and some get 、set function. So can i write the code like this?

 GetModifierHealthBonus(): number {
        //if (!IsServer()) return 0;   just comment this line of code

        const parent = this.GetParent();
        if (!parent.IsHero()) return 0;

        const playerID = parent.GetPlayerOwnerID();
        const customStrength = safeAttributeManager.getStrength(playerID);
        
        
        const healthPerStrength = 20;
        const bonusHealth = customStrength * healthPerStrength;
        
        print(`[CustomAttributes] 力量: ${customStrength}, 血量加成: ${bonusHealth}`);
        return bonusHealth;
    }
#

full code below

#

it has a global instance, in which there are a table records all the attribute of the players.

limber owl
#

Im like 99% sure that this line

export const safeAttributeManager = new SafeAttributeManager(); 

compiled into something like _G["safeAttributeManager"] = SafeAttributeManager() that will just create table at server side (with all your variables and functions) and this what will happen next

  1. Server side lua calls GetModifierHealthBonus() and get required value (because all things present server side)
  2. Panorama calls GetModifierHealthBonus() via client lua and throws because safeAttributeManager = nil
#

Even if safeAttributeManager present at both sides somehow you will get different values (with current code) at client and at server because they don't share same memory

grizzled ivy
#

thanks I fully understand~

#

besides I have used ths CustomNetTable. in the vconsole I can only see logs from Server. So maybe the GetModifierHealthBonus only called from server?

limber owl
#

Maybe, attack speed 100% called from both sides

median silo
#

I wouldnt imagine health is only serverside
Does the client get called if you take damage?

grizzled ivy
#

no only server called. And it is called because i call CalculateStatBonus in OnIntervalThink

median silo
#

If you start the thinker serverside you dont need to filter out the client btw

earnest trail