Issue with custom damage system (pistolwhipping)
#1

So I made a custom damage system based off of this guide https://sampforum.blast.hk/showthread.php?tid=558839, but there is an issue.

If I pistol whip someone (punch someone with a gun) it bases it off torso damage. Basically, I can punch someone and hit 40 now. How do I solve this issue?

Example:



See code below.

PHP код:
#define BODY_PART_TORSO 3 
#define BODY_PART_GROIN 4 
#define BODY_PART_LEFT_ARM 5 
#define BODY_PART_RIGHT_ARM 6 
#define BODY_PART_LEFT_LEG 7 
#define BODY_PART_RIGHT_LEG 8 
#define BODY_PART_HEAD 9 
my_SetPlayerArmour(playeridFloat:amount)
{
    if(
amount 0.0)
    {
        
amount 0.0;
    }
    return 
SetPlayerArmour(playeridamount);
}
#if defined _ALS_SetPlayerArmour
    #undef SetPlayerArmour
#else
    #define _ALS_SetPlayerArmour
#endif
#define SetPlayerArmour my_SetPlayerArmour
public OnPlayerConnect(playerid

    
SetPlayerTeam(playerid0); 
    return 
1

public 
OnPlayerTakeDamage(playeridissueridFloat:amountweaponidbodypart

    new 
Floathealth,Floatarmour
    
GetPlayerHealth(playeridhealth); 
    
GetPlayerArmour(playeridarmour); 
    switch(
weaponid// Starts the switch, and switches through the variable "weaponid". (declared in callback) 
    

        case 
24// Desert Eagle weapon ID
        
{
            switch(
armour)
            {
                case 
0:
                {
                    switch(
bodypart)
                    {
                        case 
3SetPlayerHealth(playeridhealth 40); // Torso.
                        
case 4SetPlayerHealth(playeridhealth 18); // Groin.
                        
case 5SetPlayerHealth(playeridhealth 8);  // Left Arm.
                        
case 6SetPlayerHealth(playeridhealth 8); // Right Arm.
                        
case 7SetPlayerHealth(playeridhealth 8);  // Left Leg.
                        
case 8SetPlayerHealth(playeridhealth 8); // Right Leg.
                        
case 9SetPlayerHealth(playeridhealth 50); // Head.
                    
}
                }
                default:
                {
                    switch(
bodypart)
                    {
                        case 
3SetPlayerArmour(playeridarmour 30); // Torso.
                        
case 4SetPlayerArmour(playeridarmour 14); // Groin.
                        
case 5SetPlayerArmour(playeridarmour 6);  // Left Arm.
                        
case 6SetPlayerArmour(playeridarmour 6); // Right Arm.
                        
case 7SetPlayerArmour(playeridarmour 6);  // Left Leg.
                        
case 8SetPlayerArmour(playeridarmour 6); // Right Leg.
                        
case 9SetPlayerArmour(playeridarmour 40); // Head.
                    
}
                }
            }
        }
        } 
    } 
    return 
1

Reply
#2

There are a few issues with your health/armor code in general.
If a player has 1.0 armor, a shot would only do one damage.
You need to calculate the overhead if a player has less armor than the damage done, and subtract the rest from their health.

Furthermore you use switch on a Float value. It works in this very case (since you check for 0, which is the equivalent to the Float 0.0).
switch does work on Float but it is the opposite of efficient since it generates a really large jump table.
That complete switch is unneccessary, just use if (since you only have 2 cases anyway).

Furthermore why OnPlayerTakeDamage? Do you want to have lagshooting on your server?
Use OnPlayerWeaponShot to avoid lagshooting and pistol whipping (pistol whipping is not a projectile, so it won't get called).
In case you do want to have lagshooting, simply check the damage value passed to the callback (pistol whipping does less damage than a bullet).

Also for the bodypart damage you could rather work with a multiplier value instead of hardcoding every case for every weapon.
Same for an armor hit, just do (eg) 10% less damage to armor.
Reply
#3

Quote:
Originally Posted by NaS
Посмотреть сообщение
There are a few issues with your health/armor code in general.
If a player has 1.0 armor, a shot would only do one damage.
You need to calculate the overhead if a player has less armor than the damage done, and subtract the rest from their health.

Furthermore you use switch on a Float value. It works in this very case (since you check for 0, which is the equivalent to the Float 0.0).
switch does work on Float but it is the opposite of efficient since it generates a really large jump table.
That complete switch is unneccessary, just use if (since you only have 2 cases anyway).

Furthermore why OnPlayerTakeDamage? Do you want to have lagshooting on your server?
Use OnPlayerWeaponShot to avoid lagshooting and pistol whipping (pistol whipping is not a projectile, so it won't get called).
In case you do want to have lagshooting, simply check the damage value passed to the callback (pistol whipping does less damage than a bullet).

Also for the bodypart damage you could rather work with a multiplier value instead of hardcoding every case for every weapon.
Same for an armor hit, just do (eg) 10% less damage to armor.
Hi there, thanks a lot for your advice.

I've tried to work with what you've described, but honestly, I am quite clueless on a few things and have some questions.

How would I go over calculating the overhead to deduct health after armour? I have noticed that there is an issue in general with the index being out of bounds at the moment.
PHP код:
[debugRun time error 4"Array index out of bounds"
[debug]  Attempted to read/write array element at index 65535 in array of size 47
[debugAMX backtrace:
[
debug#0 0005f9d8 in public OnPlayerTakeDamage (1, 65535, 1079194420, 54, 3) 
About OnPlayerTakeDamage, I didn't know that OnPlayerWeaponShot avoids lagshooting. Thanks a lot for the intel. Does OnPlayerWeaponShot look at what team you're in? I just changed it and now I do 0 damage shooting at my test account. I'd like everyone to be in the same team on my server so vehicles can't take damage from shots. (except for the tires.)

Lastly, I realized a knife's special attack doesn't work properly when you're in the same team. Do you know if there is a workaround to this issue?

Here is the full code that I currently have, I hope you can guide me further and help me turn this into an efficient, working system.

https://pastebin.com/icxScHs1
Reply
#4

Why are you even trying to make a system like this? There is a lot of considerations you need to take into account clearly you are not qualified for as you are unable to even solve the most simplistic considerations involved in this type of system. Just use weap-config and build your system around it doing this will save you countless hours of frustration and forum posts trying to figure out what is going on.
Reply
#5

Код:
// Check for pistol whip
	switch (weaponid) {
		case WEAPON_COLT45 .. WEAPON_SNIPER,
		     WEAPON_MINIGUN, WEAPON_SPRAYCAN, WEAPON_FIREEXTINGUISHER: {
			// A pistol whip inflicts 2.64 damage
			if (_:amount == _:2.6400001049041748046875) {
				// Save the weapon in the bodypart argument (it's always BODY_PART_TORSO)
				bodypart = weaponid;
				weaponid = WEAPON_PISTOLWHIP;
			}
		}
	}
Credits for Slice (weapon-config). Just add pistolwhip = true and check above bodypart code.


And about that:
Код:
[debug] Run time error 4: "Array index out of bounds" 
[debug]  Attempted to read/write array element at index 65535 in array of size 47 
[debug] AMX backtrace: 
[debug] #0 0005f9d8 in public OnPlayerTakeDamage (1, 65535, 1079194420, 54, 3)
You have to check - if(issuerid != INVALID_PLAYER_ID) before using issuerid in array.
Reply
#6

Quote:
Originally Posted by Pottus
Посмотреть сообщение
Why are you even trying to make a system like this? There is a lot of considerations you need to take into account clearly you are not qualified for as you are unable to even solve the most simplistic considerations involved in this type of system. Just use weap-config and build your system around it doing this will save you countless hours of frustration and forum posts trying to figure out what is going on.
Hey Pottus,

I appreciate your concern and I am well aware that what I am doing is very time consuming and comes with a lot of issues I cannot solve on my own. I am very aware of the fact that I lack the experience required to make complex yet effective systems. I know I would probably be better off doing what you've stated. But this doesn't stop me from trying myself anyway. I've found that this is how I learn the best, and I actually enjoy it too. The satisfaction I feel when I solve an issue, regardless of if it's as effective as it can or should be is amazing. I much prefer this rather than just downloading a file and not understanding how it works at all. Regardless, the way you've worded what you wrote was quite demotivating, but I thank you for your input anyway.

Quote:
Originally Posted by raydx
Посмотреть сообщение
Код:
// Check for pistol whip
	switch (weaponid) {
		case WEAPON_COLT45 .. WEAPON_SNIPER,
		     WEAPON_MINIGUN, WEAPON_SPRAYCAN, WEAPON_FIREEXTINGUISHER: {
			// A pistol whip inflicts 2.64 damage
			if (_:amount == _:2.6400001049041748046875) {
				// Save the weapon in the bodypart argument (it's always BODY_PART_TORSO)
				bodypart = weaponid;
				weaponid = WEAPON_PISTOLWHIP;
			}
		}
	}
Credits for Slice (weapon-config). Just add pistolwhip = true and check above bodypart code.


And about that:
Код:
[debug] Run time error 4: "Array index out of bounds" 
[debug]  Attempted to read/write array element at index 65535 in array of size 47 
[debug] AMX backtrace: 
[debug] #0 0005f9d8 in public OnPlayerTakeDamage (1, 65535, 1079194420, 54, 3)
You have to check - if(issuerid != INVALID_PLAYER_ID) before using issuerid in array.
Thanks a lot, this solved my issues. It's much appreciated. I'm only left with the knife's special ability not working now, because players are in the same team. I guess I'll sacrifice the knife until I am more familiar with scripting and know how to get around it.
Reply
#7

In case the health/armor "overhead" is still an issue, you first subtract the damage from the armor variable, even if it's 0.0.
If the result is negative (< 0.0), there was more damage done than the player had armor. In that case subtract the absolute value of the armor from the health.

This way you don't have to add a special case if the player has armor, since an armor of 0.0 will still do 100% damage to health.

For example:

Код:
new Float:damage = 50.0, Float:health = 75.0, Float:armor = 25.0; // Example starting values

armor = armor - damage; // Subtract damage from armor

if(armor < 0.0) // Armor is negative, so the negative amount is the damage that has to be done to health
{
	health += armor; // Since armor is negative, this is actually a subtraction

	armor = 0.0; // Revert it to 0.0

	if(health < 0.0) // health dropped below 0.0, set it to 0.0 to avoid negative health
	{
		health = 0.0;
	}
}
else
{
	// Health damage
}

// Update player health and armor, etc
Reply
#8

Quote:
Originally Posted by Stefhan
Посмотреть сообщение
Hey Pottus,

I appreciate your concern and I am well aware that what I am doing is very time consuming and comes with a lot of issues I cannot solve on my own. I am very aware of the fact that I lack the experience required to make complex yet effective systems. I know I would probably be better off doing what you've stated. But this doesn't stop me from trying myself anyway. I've found that this is how I learn the best, and I actually enjoy it too. The satisfaction I feel when I solve an issue, regardless of if it's as effective as it can or should be is amazing. I much prefer this rather than just downloading a file and not understanding how it works at all. Regardless, the way you've worded what you wrote was quite demotivating, but I thank you for your input anyway.



Thanks a lot, this solved my issues. It's much appreciated. I'm only left with the knife's special ability not working now, because players are in the same team. I guess I'll sacrifice the knife until I am more familiar with scripting and know how to get around it.
You are not even close to solving all the issues I saw your code not even close.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)