Raised This Month: $ Target: $400
 0% 

[CS] Find entity if it is within the radius and apply damage


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Rirre
Veteran Member
Join Date: Nov 2006
Old 08-27-2013 , 15:39   [CS] Find entity if it is within the radius and apply damage
Reply With Quote #1

I need to find if "func_wall" entities with FL_MONSTER flag are close enough to deal damage to and then apply damage to them if they are.
The same way as it does for client-/players with adjustable damage depending on the distance from the explosion.
But I am out of ideas how to get it to work.

Also, "m203_nade" is supposed to only hurt FL_MONSTER's if it is visible for the m203_nade (not the player/owner of it) to not hurt them through walls.
Tried Ham_FVisible but it doesn't seem to work :/
Code:
public vexd_pfntouch(pToucher, pTouched) {     new szClassName[32]     if ( pToucher > 0)     {         entity_get_string(pToucher, EV_SZ_classname, szClassName, 31)     }     if(equal(szClassName, "m203_nade"))     {         if(!pTouched && 0)             return         new dmgradius = get_cvar_num("amx_m203rad")         new maxdamage = get_cvar_num("amx_m203dmg")         new Float:fl_vExplodeAt[3]         entity_get_vector(pToucher, EV_VEC_origin, fl_vExplodeAt)         new vExplodeAt[3]         vExplodeAt[0] = floatround(fl_vExplodeAt[0])         vExplodeAt[1] = floatround(fl_vExplodeAt[1])         vExplodeAt[2] = floatround(fl_vExplodeAt[2])         new owner = entity_get_edict(pToucher, EV_ENT_owner)         new origin[3], dist, damage, Float:dRatio, Float:takedamage         // Players         for (new i = 1; i <= 32; i++)         { // Players id             pev(i, pev_takedamage, takedamage)             if(takedamage > DAMAGE_NO)             {                 get_user_origin(i,origin)                 dist = get_distance(origin,vExplodeAt)                 if (dist <= dmgradius)                 {                     dRatio = floatdiv(float(dist),float(dmgradius))                     damage = maxdamage - floatround(floatmul(float(maxdamage),dRatio))                     if(is_user_alive(i))                     {                         ScreenShake(i)                         if(i == owner) // Owner of the nade                         {                             do_damage(i, damage) // Ow! Too close                             set_velocity_from_origin(i, fl_vExplodeAt, get_cvar_float("amx_m203conc")*damage) // knockback                         }                         else if(i != owner && ExecuteHam( Ham_FVisible, i, pToucher ))                         // TEST: Do it hit through the wall?                         // without Ham_FVisible it does. with Ham_FVisible, nothing. Even if the owner and nade is fully visible for the teammate.                             server_print("Teammate!")                     }                 }             }         }         // Monsters         new ent = -1         while((ent = find_ent_by_class(ent, "func_wall")))         {             pev(ent, pev_takedamage, takedamage)             if( takedamage > DAMAGE_NO && pev(ent, pev_flags) & FL_MONSTER )             {                 entity_get_vector(ent, EV_VEC_origin, origin)                 // Need to find if the FL_MONSTER is in the radius to deal damage to                 // dist = get_distance(origin, vExplodeAt) --- do not work                 // dist = entity_range(origin, vExplodeAt) --- do not work either                 if (dist <= dmgradius)                 {                     dRatio = floatdiv(float(dist),float(dmgradius))                     damage = maxdamage - floatround(floatmul(float(maxdamage),dRatio))                     //...do damage                 }             }         }         remove_entity(pToucher)     } } do_damage(victim, damage) {     new Float:takedamage     pev(victim, pev_takedamage, takedamage)     new Float:fl_dmg = float(damage)     fakedamage(victim, "grenade", fl_dmg, DMG_BLAST) }

Last edited by Rirre; 08-28-2013 at 12:19.
Rirre is offline
RateX
Veteran Member
Join Date: Jun 2012
Location: 0o. SEA .o0
Old 08-28-2013 , 01:32   Re: [CS] Find entity if it is within the radius and apply damage
Reply With Quote #2

Try using can_see_fm(entityid1, entityid2)
-entityid1 is nade id
-entityid2 is victim id
RateX is offline
Rirre
Veteran Member
Join Date: Nov 2006
Old 08-28-2013 , 13:17   Re: [CS] Find entity if it is within the radius and apply damage
Reply With Quote #3

Finally I made it to find them in the radius with this:
Code:
        new ent = -1         while((ent = find_ent_by_class(ent, "func_wall")))         {             new Float:fldist, Float:florigin[3]             pev(ent, pev_takedamage, takedamage)             if( takedamage > DAMAGE_NO && pev(ent, pev_flags) & FL_MONSTER )             {                 pev(ent, pev_origin, florigin)                 fldist = get_distance_f(florigin, fl_vExplodeAt)                 if (fldist <= dmgradius && fm_is_ent_visible(pToucher, ent, 0))                 {                     dRatio = floatdiv(fldist,float(dmgradius))                     damage = maxdamage - floatround(floatmul(float(maxdamage),dRatio))                     //...do damage                     server_print("Monster hit")                 }             }         }
EDIT:
Made the damage to work also.

I can't find "can_see_fm" anywhere so I used "fm_is_ent_visible".
Quote:
Originally Posted by Nextra
fm_is_ent_visible will return false negatives relatively often (at least there are many common situations where it will due to the origin comparison).
And yes, it does. Any other suggestions?

Last edited by Rirre; 08-28-2013 at 14:21.
Rirre is offline
RateX
Veteran Member
Join Date: Jun 2012
Location: 0o. SEA .o0
Old 08-29-2013 , 03:02   Re: [CS] Find entity if it is within the radius and apply damage
Reply With Quote #4

Quote:
Originally Posted by Rirre View Post
I can't find "can_see_fm" anywhere so I used "fm_is_ent_visible".
Sorry, I forgot to upload this:
PHP Code:
bool:can_see_fm(entindex1entindex2)
{
    if (!
entindex1 || !entindex2)
        return 
false
//  new ent1, ent2

    
if (pev_valid(entindex1) && pev_valid(entindex1))
    {
        new 
flags pev(entindex1pev_flags)
        if (
flags EF_NODRAW || flags FL_NOTARGET)
        {
            return 
false
        
}

        new 
Float:lookerOrig[3]
        new 
Float:targetBaseOrig[3]
        new 
Float:targetOrig[3]
        new 
Float:temp[3]

        
pev(entindex1pev_originlookerOrig)
        
pev(entindex1pev_view_ofstemp)
        
lookerOrig[0] += temp[0]
        
lookerOrig[1] += temp[1]
        
lookerOrig[2] += temp[2]

        
pev(entindex2pev_origintargetBaseOrig)
        
pev(entindex2pev_view_ofstemp)
        
targetOrig[0] = targetBaseOrig [0] + temp[0]
        
targetOrig[1] = targetBaseOrig [1] + temp[1]
        
targetOrig[2] = targetBaseOrig [2] + temp[2]

        
engfunc(EngFunc_TraceLinelookerOrigtargetOrig0entindex10//  checks the had of seen player
        
if (get_tr2(0TraceResult:TR_InOpen) && get_tr2(0TraceResult:TR_InWater))
        {
            return 
false
        

        else 
        {
            new 
Float:flFraction
            get_tr2
(0TraceResult:TR_flFractionflFraction)
            if (
flFraction == 1.0 || (get_tr2(0TraceResult:TR_pHit) == entindex2))
            {
                return 
true
            
}
            else
            {
                
targetOrig[0] = targetBaseOrig [0]
                
targetOrig[1] = targetBaseOrig [1]
                
targetOrig[2] = targetBaseOrig [2]
                
engfunc(EngFunc_TraceLinelookerOrigtargetOrig0entindex10//  checks the body of seen player
                
get_tr2(0TraceResult:TR_flFractionflFraction)
                if (
flFraction == 1.0 || (get_tr2(0TraceResult:TR_pHit) == entindex2))
                {
                    return 
true
                
}
                else
                {
                    
targetOrig[0] = targetBaseOrig [0]
                    
targetOrig[1] = targetBaseOrig [1]
                    
targetOrig[2] = targetBaseOrig [2] - 17.0
                    engfunc
(EngFunc_TraceLinelookerOrigtargetOrig0entindex10//  checks the legs of seen player
                    
get_tr2(0TraceResult:TR_flFractionflFraction)
                    if (
flFraction == 1.0 || (get_tr2(0TraceResult:TR_pHit) == entindex2))
                    {
                        return 
true
                    
}
                }
            }
        }
    }
    return 
false

Try and see if it helps

Last edited by RateX; 08-29-2013 at 03:03.
RateX is offline
Rirre
Veteran Member
Join Date: Nov 2006
Old 08-29-2013 , 10:56   Re: [CS] Find entity if it is within the radius and apply damage
Reply With Quote #5

Thanks, works fine.
Rirre is offline
ConnorMcLeod
Veteran Member
Join Date: Jul 2006
Location: France (95)
Old 08-29-2013 , 13:24   Re: [CS] Find entity if it is within the radius and apply damage
Reply With Quote #6

vexd_pfntouch, pfn_touch, FM_Touch are bad to use.
You could greatly optimize your code using register_touch.
Also, consider find_ent_sphere so you can retrieve entity list within the wanted sphere :

PHP Code:
new const MONSTER_CLASS[] = "func_wall";

public 
plugin_init()
{
    
register_touch("m203_nade""*""M203_Nade_Touch");
}

public 
M203_Nade_Touch(nadeidOther)
{
    new 
walls[64], monsterFloat:takedamageFloat:distFloat:origin[3], Float:monsterAbsMax[3], Float:monsterAbsMin[3], Float:monsterOrigin[3];
    new 
wallsnum find_sphere_class(nadeMONSTER_CLASSdmgradiuswallssizeof(walls));

    
entity_get_vector(nadeEV_VEC_originorigin);

    for(--
wallsnumwallsnum>=0wallsnum--)
    {
        
monster wallswallsnum ];
        if( 
IsEntMonster(monsterfalse) )
        {
            
entity_get_float(monsterEV_FL_takedamagetakedamage);
            if( 
takedamage != DAMAGE_NO )
            {
                
entity_get_vector(monsterEV_VEC_absminmonsterAbsMin);
                
entity_get_vector(monsterEV_VEC_absmaxmonsterAbsMin);
                
xs_vec_sub(monsterAbsMaxmonsterAbsMinmonsterOrigin);

                
dist get_distance_f(originmonsterOrigin);

                
// if (dist <= dmgradius) // not needed because we use find_sphere_class

                
dRatio dmgradius dist
                damage 
maxdamage floatrounddRatio maxdamage )
                    
                
//...do damage
            
}
        }
    }

    new 
players[32], pnumid;
    
find_sphere_class(nade"player"dmgradiusplayerssizeof(players));

    for(--
pnumpnum >= 0pnum--)
    {
        
id players[pnum];
        if( 
is_user_alive(id) && !get_user_godmode(id) )
        {
            
dist entity_range(nadeid);
            
// do damage, screenshake etc..
        
}
    }

    
remove_entity(nade);
    return 
PLUGIN_HANDLED;
}

bool:IsEntMonster(entbool:bCheckClassName)
{
    if( 
bCheckClassName )
    {
        static class[];
        
entity_get_string(entEV_SZ_classname, class, charsmax(class));
        if( !
equal(class, MONSTER_CLASS) )
        {
            return 
false;
        }
    }

    return !!(
entity_get_int(entEV_INT_flags) & FL_MONSTER);

__________________
- tired and retired -

- my plugins -
ConnorMcLeod is offline
Rirre
Veteran Member
Join Date: Nov 2006
Old 08-29-2013 , 17:56   Re: [CS] Find entity if it is within the radius and apply damage
Reply With Quote #7


Code:
public M203_Nade_Touch(nade, idOther) {     new walls[64], monster, Float:takedamage, Float:dist, Float:origin[3], Float:monsterAbsMax[3], Float:monsterAbsMin[3], Float:monsterOrigin[3], owner = entity_get_edict(nade, EV_ENT_owner), Float:dRatio, Float:damage, frag = 1, monmodel[31], maxdamage = get_cvar_num("amx_m203dmg"), dmgradius = get_cvar_num("amx_m203rad") // warning 213: tag mismatch     new wallsnum = find_sphere_class(nade, MONSTER_CLASS, dmgradius, walls, sizeof(walls))  // warning 213: tag mismatch (2x times)     entity_get_vector(nade, EV_VEC_origin, origin)     entity_get_string(monster, EV_SZ_model, monmodel, 30)     for(--wallsnum; wallsnum>=0; wallsnum--)     {         monster = walls[ wallsnum ]         if( IsEntMonster(monster, false) )         {             entity_get_float(monster, EV_FL_takedamage, takedamage) // error 088: number of arguments does not match definition             if( takedamage != DAMAGE_NO && pev(monster, pev_deadflag) != DEAD_DEAD)             {                 entity_get_vector(monster, EV_VEC_absmin, monsterAbsMin)                 entity_get_vector(monster, EV_VEC_absmax, monsterAbsMin)                 xs_vec_sub(monsterAbsMax, monsterAbsMin, monsterOrigin)                 dist = get_distance_f(origin, monsterOrigin)                 dRatio = dmgradius / dist                 damage = maxdamage - floatround( dRatio * maxdamage ) // this line                 // do damage                 set_pev(monster, pev_dmg_inflictor, owner) // to this line > warning 213: tag mismatch                 new Float:health                 pev(monster, pev_health, health)                 health -= damage                 set_pev(monster, pev_health, health)                 if(health <= 0.0)                 {                     ExecuteHamB(Ham_AddPoints, owner, frag, true)                 }             }         }     }     new players[32], pnum, id     find_sphere_class(nade, "player", dmgradius, players, sizeof(players)) // warning 213: tag mismatch     for(--pnum; pnum >= 0; pnum--)     {         id = players[pnum];         if( is_user_alive(id) && !get_user_godmode(id) )         {             dist = entity_range(nade, id)             // do damage, screenshake etc..             ScreenShake(id) // screen shakes for everyone             if(id == owner)             {                 do_damage(owner, damage) // warning 213: tag mismatch                 set_velocity_from_origin(owner, nade, get_cvar_float("amx_m203conc")*damage) // error 035: argument type mismatch (argument 2)             }         }     }     message_begin(MSG_BROADCAST, SVC_TEMPENTITY)     write_byte(TE_EXPLOSION)     write_coord(origin[0]) // warning 213: tag mismatch     write_coord(origin[1]) // warning 213: tag mismatch     write_coord(origin[2] + 30) // warning 213: tag mismatch     write_short(g_sModelIndexFireball)     write_byte(30)     write_byte(15)     write_byte(TE_EXPLFLAG_NONE)     message_end()     message_begin(MSG_BROADCAST, SVC_TEMPENTITY)     write_byte(TE_WORLDDECAL)     write_coord(origin[0]) // warning 213: tag mismatch     write_coord(origin[1]) // warning 213: tag mismatch     write_coord(origin[2]) // warning 213: tag mismatch     write_byte(g_iDecal)     message_end()     remove_entity(nade)     return PLUGIN_HANDLED } bool:IsEntMonster(ent, bool:bCheckClassName) {     if( bCheckClassName )     {         static class[]         entity_get_string(ent, EV_SZ_classname, class, charsmax(class)) // 4 errors, listed below         if( !equal(class, MONSTER_CLASS) )         {             return false         }     }     return !!(entity_get_int(ent, EV_INT_flags) & FL_MONSTER) }
Code:
error 009: invalid array size (negative or zero)
error 017: undefined symbol "class"
error 072: "sizeof" operator is invalid on "function" symbols
fatal error 107: too many error messages on one line

Last edited by Rirre; 08-30-2013 at 18:56.
Rirre is offline
ConnorMcLeod
Veteran Member
Join Date: Jul 2006
Location: France (95)
Old 08-29-2013 , 20:22   Re: [CS] Find entity if it is within the radius and apply damage
Reply With Quote #8

Haven't tested code at all, mainly you have to declare MONSTER_CLASS not as const, and may be you haven't passed a Float as radius, or you passed a Float but native wants an integer.

For other warnings, if you use amxx1.8.3 you can use write_coord_f and write_angle_f, else you can use engfunc(EngFunc_WriteCoords and engfunc(EngFunc_WriteAngle when Float args are passed.

Anyway, this is scriptin/help forum, you should be able to get rid of such warnings by yourself.
__________________
- tired and retired -

- my plugins -

Last edited by ConnorMcLeod; 08-29-2013 at 20:22.
ConnorMcLeod is offline
Old 08-30-2013, 13:54
Rirre
This message has been deleted by Rirre. Reason: Nvm
ConnorMcLeod
Veteran Member
Join Date: Jul 2006
Location: France (95)
Old 08-30-2013 , 16:19   Re: [CS] Find entity if it is within the radius and apply damage
Reply With Quote #9

About your deleted post, why don't you use ExecuteHam(Ham_TakeDamage to apply damage on entities ?
You could even remove pev_takedamage checks.
Else, make sure you set pev_dmg_inflictor to the nade index, so game and other plugins can know which entity is calling damage.
__________________
- tired and retired -

- my plugins -
ConnorMcLeod is offline
Rirre
Veteran Member
Join Date: Nov 2006
Old 08-30-2013 , 19:07   Re: [CS] Find entity if it is within the radius and apply damage
Reply With Quote #10

Quote:
Originally Posted by ConnorMcLeod View Post
About your deleted post, why don't you use ExecuteHam(Ham_TakeDamage to apply damage on entities ?
You could even remove pev_takedamage checks.
Else, make sure you set pev_dmg_inflictor to the nade index, so game and other plugins can know which entity is calling damage.
I have no clue how to get the attacker/owner if the nade is inflictor. Works fine with this in monster_killed() but not in takedmg().

Ye, you're right. Now that I've thought about it.
takedamage is only set to 0.0/DAMAGE_NO when the CallGibMonster() is called.

ScreenShake & do_damage do nothing when I switched to yours.

Code:
    //HAMSANDWICH     RegisterHam(Ham_Killed, "func_wall", "monster_killed", 1)     RegisterHam(Ham_TakeDamage, "func_wall", "takedmg", 1)     RegisterHam(Ham_Touch, "info_target", "M203_Nade_Touch") public takedmg(victim, inflictor, attacker, Float:damage, damagebits) {     new ClassName[32]     entity_get_string(attacker, EV_SZ_classname, ClassName, charsmax(ClassName))     if(equali(ClassName, "m203_nade"))     {         new owner = entity_get_edict(attacker, EV_ENT_owner)         client_print(owner, print_chat, "M203 hurt monster") // Do not work     } } public monster_killed(victim, killer, shouldgib) {     new ClassName[32]     entity_get_string(killer, EV_SZ_classname, ClassName, charsmax(ClassName))     if(equali(ClassName, "m203_nade"))     {         new owner = entity_get_edict(killer, EV_ENT_owner)         client_print(owner, print_chat, "M203 killed monster") // It works     } } new MONSTER_CLASS[] = "func_wall" public M203_Nade_Touch(nade, idOther) {     new walls[64], monster, Float:dist, Float:origin[3], Float:monsterAbsMax[3], Float:monsterAbsMin[3], Float:monsterOrigin[3], owner = entity_get_edict(nade, EV_ENT_owner)     new wallsnum = find_sphere_class(nade, MONSTER_CLASS, float(dmgradius), walls, sizeof(walls))     entity_get_vector(nade, EV_VEC_origin, origin)     for(--wallsnum; wallsnum>=0; wallsnum--)     {         monster = walls[ wallsnum ]         if( IsEntMonster(monster, false) )         {             entity_get_vector(monster, EV_VEC_absmin, monsterAbsMin)             entity_get_vector(monster, EV_VEC_absmax, monsterAbsMin)             xs_vec_sub(monsterAbsMax, monsterAbsMin, monsterOrigin)             dist = get_distance_f(origin, monsterOrigin)             new Float:damage = (get_pcvar_float(cvar_damage)/get_pcvar_float(cvar_radius))*(get_pcvar_float(cvar_radius)-dist)             ExecuteHam(Ham_TakeDamage, monster, owner, nade, -damage, DMG_BULLET)             client_print(owner, print_chat, "Damage: %f", damage)             g_iDamage[owner][monster] += damage         }     }     new players[32], pnum, id     find_sphere_class(nade, "player", float(dmgradius), players, sizeof(players))     for(--pnum; pnum >= 0; pnum--)     {         id = players[pnum];         if( is_user_alive(id) && !get_user_godmode(id) )         {             dist = entity_range(nade, id)             // do damage, screenshake etc..             ScreenShake(id) // for all players             if(id == owner) // hurt the owner only             {                 do_damage(owner, damage)             }         }     }     message_begin(MSG_BROADCAST, SVC_TEMPENTITY)     write_byte(TE_EXPLOSION)     engfunc(EngFunc_WriteCoord, origin[0])     engfunc(EngFunc_WriteCoord, origin[1])     engfunc(EngFunc_WriteCoord, origin[2] + 30)     write_short(g_sModelIndexFireball)     write_byte(30)     write_byte(15)     write_byte(TE_EXPLFLAG_NONE)     message_end()     message_begin(MSG_BROADCAST, SVC_TEMPENTITY)     write_byte(TE_WORLDDECAL)     engfunc(EngFunc_WriteCoord, origin[0])     engfunc(EngFunc_WriteCoord, origin[1])     engfunc(EngFunc_WriteCoord, origin[2])     write_byte(g_iDecal)     message_end()     remove_entity(nade)     return PLUGIN_HANDLED } bool:IsEntMonster(ent, bool:bCheckClassName) {     if( bCheckClassName )     {         static class[32]         entity_get_string(ent, EV_SZ_classname, class, charsmax(class))         if( !equal(class, MONSTER_CLASS) )         {             return false         }     }     return !!(entity_get_int(ent, EV_INT_flags) & FL_MONSTER) }

Last edited by Rirre; 08-31-2013 at 05:34.
Rirre is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 18:57.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode