Damage function for a game For my game I have a function that resolves FireOrders between units. The function is being called a ton of times and it's only being extended from various classes.

I have this: doDamage() for a Particle-Parent, a Matter-Parent and so on (5 in total).

The functions are the same, except for a very little if/else part that splits up a number into two different numbers.

It is very annoying to me to have this "long" function in every weapon class and I would like to somehow outsource the actual damage-determination part, because basicly this is what's different for the weapon classes and the remaining function is entirely the same.

However, I'm unable to come up with a way to outsource this tiny element. I tried to write two functions (getArmourDamage() and getStructDamage()), but it is not working since both values depend on each other, hence a single function return value won't suffice.

function doDamage($fire){
 // this is being called in context Particle::doDamage, Matter::doDamage, Explosive::doDamage etc

    for ($i = 0; $i &lt; $fire-&gt;shots; $i++){
        if ($fire-&gt;rolls[$i] &lt;= $fire-&gt;req){
            $destroyed = false;
            $shielDmg = 0;
            $armourDmg = 0;
            $structDmg = 0;
            $totalDmg = $this-&gt;getDamage($fire) * $this-&gt;getDamageMod(); // INT

            $armour = $fire-&gt;target-&gt;getStructureById($fire-&gt;hitSection);
            $hitSystem = $fire-&gt;target-&gt;getHitSystem($fire);
            $remInt = $hitSystem-&gt;getRemainingIntegrity();
            $negation = $armour-&gt;getRemainingNegation($fire) * $hitSystem-&gt;getArmourMod(); // INT


             // VARIABLE PART
                if ($totalDmg &lt;= $negation/2){
                    $armourDmg = ceil($totalDmg/2);
                }
                else {
                    $armourDmg = ceil(min($totalDmg, $negation));
                    $structDmg = ceil($totalDmg - $armourDmg);
                }
             // ENDS HERE


            if ($remInt - $structDmg &lt; 1){
                $destroyed = true;
                $hitSystem-&gt;destroyed = true;
                Debug::log("overkill for: ".($structDmg - $remInt));
            }

            $dmg = new Damage(
                -1,
                $fire-&gt;id,
                $fire-&gt;gameid,
                $fire-&gt;targetid,
                $armour-&gt;id,
                $hitSystem-&gt;id,
                $fire-&gt;turn,
                $fire-&gt;rolls[$i],
                $fire-&gt;weapon-&gt;type,
                $totalDmg,
                $shielDmg,
                $structDmg,
                $armourDmg,
                0,
                $negation,
                $destroyed,
                "",
                1
            );
            $fire-&gt;damages[] = $dmg;
            $hitSystem-&gt;damages[] = $dmg;
            $armour-&gt;damages[] = $dmg;
            Debug::log("armour rem: ".$armour-&gt;getRemainingIntegrity()." / ".$armour-&gt;integrity.", now adding: ".$armourDmg);
        }
    }
    return true;
}


For reference, these are the various differences per class:

   particle
                if ($totalDmg &lt;= $negation/2){
                    $armourDmg = ceil($totalDmg/2);
                }
                else {
                    $armourDmg = ceil(min($totalDmg, $negation));
                    $structDmg = ceil($totalDmg - $armourDmg);
                }

   matter
                $armourDmg = $negation / 2;
                $structDmg = $totalDmg - $armourDmg;

   ballistic
                $armourDmg = min($totalDmg, $negation *2);
                $structDmg = $totalDmg - $armourDmg;
Please see comment above about thinking about broader review. My guess is that you might have a flawed approach to how you are modelling real-world items in your application. For example, a particle/matter/explosive doesn't really "doDamage" right? It "attacks" or "fires" or whatever you might want to call it.

"Damage" as a concept results from what the properties of the attack and the properties of the thing attacked are right?   So why would you model "damage" as a method on the different attacker entities, when it truly is something that needs to be determined based on the properties of both the attack and the target. Putting the actual calculation in the attacker class would not seem to make sense when you think about it.

You might look through another review I gave where the poster was having a similar problem in modelling application entities to match real world behavior. I hope this may give some insight into how you should be thinking about writing your code.



That being said, if you aren't looking to potentially refactor your application, your problem should actually be easy to solve.  Just break that "variable" area of code out into it's own function:

So base class might look like:

function doDamage($fire) {
    // all your code common to every class in hierarchy


    // call method (overridden with specific logic in each inheriting class
    // possibly this method returns your Damage object
    $dmg = $this-&gt;calculateDamage($someParam, $someOtherParam, ...);

    // other code common to all classes in hierarchy
}


And you only override such code in inheriting classes if logic totally varies from that execution path.



Why does this method always return true? Is it really even meaningful to have a return from a method is the value is always the same?