AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting Help (https://forums.alliedmods.net/forumdisplay.php?f=11)
-   -   [CS] Find entity if it is within the radius and apply damage (https://forums.alliedmods.net/showthread.php?t=224717)

Rirre 08-27-2013 15:39

[CS] Find entity if it is within the radius and apply damage
 
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) }

RateX 08-28-2013 01:32

Re: [CS] Find entity if it is within the radius and apply damage
 
Try using can_see_fm(entityid1, entityid2)
-entityid1 is nade id
-entityid2 is victim id

Rirre 08-28-2013 13:17

Re: [CS] Find entity if it is within the radius and apply damage
 
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?

RateX 08-29-2013 03:02

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

Originally Posted by Rirre (Post 2023445)
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

Rirre 08-29-2013 10:56

Re: [CS] Find entity if it is within the radius and apply damage
 
Thanks, works fine.

ConnorMcLeod 08-29-2013 13:24

Re: [CS] Find entity if it is within the radius and apply damage
 
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);



Rirre 08-29-2013 17:56

Re: [CS] Find entity if it is within the radius and apply damage
 
:arrow:
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


ConnorMcLeod 08-29-2013 20:22

Re: [CS] Find entity if it is within the radius and apply damage
 
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.

ConnorMcLeod 08-30-2013 16:19

Re: [CS] Find entity if it is within the radius and apply damage
 
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.

Rirre 08-30-2013 19:07

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

Originally Posted by ConnorMcLeod (Post 2024989)
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) }


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

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