Senior Member
Join Date: Mar 2015
Location: Poland
|
03-16-2016
, 14:54
Re: Is it safe?
|
#4
|
Here is the full code of my plugin. Mainly I have edited what I have descripted in the topic above and added some features.
PHP Code:
#include < amxmodx > #include < fakemeta > #include < hamsandwich >
#pragma semicolon 1
new const DispenserCosts[ 3 ] = { 1500, 500, 700 }; new const DispenserMaxHealing[ 3 ] = { 200, 400, 500 }; new const DispenserMaxHealth[ 3 ] = { 300, 500, 700 }; new const DispenserHealRadius[ 3 ] = { 200, 300, 400 };
#define DISPENSER_EXPLOSION_MAXDMG 90
enum { STATUS_BUILDING, STATUS_ACTIVE }; enum { DISPENSER_LEVEL1, DISPENSER_LEVEL2, DISPENSER_LEVEL3 };
new const gDamageSounds[ ][ ] = { "debris/metal1.wav", "debris/metal2.wav", "debris/metal3.wav" };
new const gDispenserClassname[ ] = "NiceDispenser"; new const szDispenserClassname[ ] = "info_target";
new const gDispenserActive[ ] = "buttons/button9.wav"; new const gDispenserMdl[ ] = "models/mt_dispenser.mdl"; new const gHealingSprite[ ] = "sprites/heal_spr.spr"; new const gExploSprite[ ] = "sprites/zerogxplode.spr";
new gHealingBeam, gExplosionSprite, g_msgMoney, g_HUDSync; new Float:gDispenserOrigin[ 33 ][ 3 ]; new bDispenserID[ 33 ]; new bool:bTrigger[ 33 ];
new const gBeamColor[ 2 ][ 3 ] = { { 255, 50, 50 }, // T { 50, 50, 255 } // CT };
public plugin_init( ) { register_plugin( "Build Dispenser", "2.0", "Podarok/tuty" );
RegisterHam( Ham_TakeDamage, szDispenserClassname, "bacon_TakeDamage", 0 ); RegisterHam( Ham_TraceAttack, szDispenserClassname, "bacon_TraceAttack" ); RegisterHam( Ham_Touch, szDispenserClassname, "bacon_Touch" ); RegisterHam( Ham_Spawn, "player", "EVENT_Spawn", 1 );
register_forward( FM_Think, "DispenserThink" ); register_forward( FM_TraceLine, "FW_Traceline", 1 );
register_clcmd( "say /healmachine", "CommandDispenserBuild" );
g_msgMoney = get_user_msgid( "Money" ); g_HUDSync = CreateHudSyncObj( ); }
public client_disconnect( id ) { if( pev_valid( bDispenserID[ id ] ) ) { bDispenserID[ id ] = 0; set_pev( bDispenserID[ id ], pev_flags, pev( bDispenserID[ id ], pev_flags ) | FL_KILLME ); } }
public plugin_precache( ) { gHealingBeam = precache_model( gHealingSprite ); gExplosionSprite = precache_model( gExploSprite );
precache_model( gDispenserMdl ); precache_sound( gDispenserActive );
new i; for( i = 0; i < sizeof gDamageSounds; i++ ) precache_sound( gDamageSounds[ i ] ); }
public CommandDispenserBuild( id ) { if( !is_user_alive( id ) ) return PLUGIN_CONTINUE;
if( pev_valid( bDispenserID[ id ] ) ) { client_print( id, print_center, "You already have build a Heal Machine!" ); return PLUGIN_HANDLED; }
if( !( pev( id, pev_flags ) & FL_ONGROUND ) ) { client_print( id, print_center, "You must be on ground to build a Heal Machine!" ); return PLUGIN_HANDLED; }
if ( pev( id, pev_bInDuck ) ) { client_print( id, print_center, "You must not duck while building a Heal Machine!" ); return PLUGIN_CONTINUE; }
new iMoney = fm_get_user_money( id );
if( iMoney < DispenserCosts[ DISPENSER_LEVEL1 ] ) { client_print( id, print_center, "Insufficient funds... Need at least %d$", DispenserCosts[ DISPENSER_LEVEL1 ] ); return PLUGIN_HANDLED; }
new Float:flPlayerOrigin[ 3 ]; pev( id, pev_origin, flPlayerOrigin );
new iEntity = engfunc( EngFunc_CreateNamedEntity, engfunc( EngFunc_AllocString, szDispenserClassname ) );
if( !pev_valid( iEntity ) ) return PLUGIN_HANDLED;
new iTeam = fm_get_user_team( id );
set_pev( iEntity, pev_classname, gDispenserClassname ); engfunc( EngFunc_SetModel, iEntity, gDispenserMdl ); set_pev( iEntity, pev_body, ( iTeam == 2 ) ? DISPENSER_LEVEL1 : DISPENSER_LEVEL1 + 3 );
// Drop entity to the ground and fix its size (in order not to go underground) new Float:end[ 3 ]; new tr = create_tr2( );
end[ 0 ] = flPlayerOrigin[ 0 ]; end[ 1 ] = flPlayerOrigin[ 1 ]; end[ 2 ] = -8192.0;
engfunc( EngFunc_TraceLine, flPlayerOrigin, end, IGNORE_MONSTERS, iEntity, tr ); get_tr2( tr, TR_vecEndPos, end ); free_tr2( tr );
new Float:vec_dist = vector_distance( flPlayerOrigin, end ); flPlayerOrigin[ 2 ] -= vec_dist;
new Float:maxs[ 3 ]; maxs[ 0 ] = 12.0; maxs[ 1 ] = 10.0; maxs[ 2 ] = vec_dist + 12.0;
engfunc( EngFunc_SetSize, iEntity, Float:{ -12.0, -10.0, -12.0 }, maxs ); engfunc( EngFunc_SetOrigin, iEntity, flPlayerOrigin );
set_pev( iEntity, pev_team, iTeam ); set_pev( iEntity, pev_solid, SOLID_NOT ); set_pev( iEntity, pev_movetype, MOVETYPE_FLY ); set_pev( iEntity, pev_health, float( DispenserMaxHealth[ DISPENSER_LEVEL1 ] ) ); set_pev( iEntity, pev_takedamage, DAMAGE_YES ); set_pev( iEntity, pev_iuser2, id ); set_pev( iEntity, pev_iuser3, STATUS_BUILDING ); set_pev( iEntity, pev_iuser1, DISPENSER_LEVEL1 ); set_pev( iEntity, pev_nextthink, get_gametime( ) + 0.1 );
gDispenserOrigin[ id ][ 0 ] = flPlayerOrigin[ 0 ]; gDispenserOrigin[ id ][ 1 ] = flPlayerOrigin[ 1 ]; gDispenserOrigin[ id ][ 2 ] = flPlayerOrigin[ 2 ] + vec_dist;
bDispenserID[ id ] = iEntity;
set_task( 5.0, "BuildDispenserSolid", iEntity ); fm_set_user_money( id, iMoney - DispenserCosts[ DISPENSER_LEVEL1 ] );
client_print( id, print_center, "Building a Heal Machine right here!" );
return PLUGIN_HANDLED; }
public BuildDispenserSolid( iEntity ) { if( pev_valid( iEntity ) ) { new iTeam = pev( iEntity, pev_team ) - 1;
fm_set_rendering( iEntity, kRenderFxGlowShell, gBeamColor[ iTeam ][ 0 ], gBeamColor[ iTeam ][ 1 ], gBeamColor[ iTeam ][ 2 ], kRenderNormal, 3 );
set_pev( iEntity, pev_solid, SOLID_BBOX ); set_pev( iEntity, pev_iuser3, STATUS_ACTIVE );
emit_sound( iEntity, CHAN_STATIC, gDispenserActive, VOL_NORM, ATTN_NORM, 0, PITCH_NORM ); } }
public bool:CanUpgradeDispenser( iEntity, id ) { if( pev( iEntity, pev_iuser1 ) == DISPENSER_LEVEL3 ) return false;
if( pev( iEntity, pev_team ) != fm_get_user_team( id ) ) return false;
if( pev( iEntity, pev_iuser2 ) == id ) return false;
if( pev( iEntity, pev_iuser4 ) == id ) return false;
return true; }
public DispenserUpgrade( iEntity, id ) { new iNewLevel = pev( iEntity, pev_iuser1 ) + 1; set_pev( iEntity, pev_body, ( pev( iEntity, pev_team ) == 2 ) ? iNewLevel : iNewLevel + 3 ); set_pev( iEntity, pev_iuser1, iNewLevel ); set_pev( iEntity, pev_health, float( DispenserMaxHealth[ iNewLevel ] ) );
if( iNewLevel == DISPENSER_LEVEL2 ) set_pev( iEntity, pev_iuser4, id );
fm_set_user_money( id, fm_get_user_money( id ) - DispenserCosts[ iNewLevel ] ); emit_sound( iEntity, CHAN_STATIC, gDispenserActive, VOL_NORM, ATTN_NORM, 0, PITCH_NORM );
new iOwner = pev( iEntity, pev_iuser2 );
new szName[ 32 ]; get_user_name( id, szName, 31 );
client_print( iOwner, print_center, "%s has upgraded your Heal Machine to level %d", szName, iNewLevel + 1 ); }
public bacon_TakeDamage( ent, idinflictor, idattacker, Float:damage, damagebits ) { if( !pev_valid( ent ) ) return HAM_IGNORED;
if( !is_user_connected( idattacker ) ) return HAM_IGNORED;
new szClassname[ 32 ]; pev( ent, pev_classname, szClassname, charsmax( szClassname ) );
if( equal( szClassname, gDispenserClassname ) ) { if( pev( ent, pev_team ) == fm_get_user_team( idattacker ) ) return HAM_SUPERCEDE;
if( pev( ent, pev_health ) - damage <= 0.0 ) { new szName[ 32 ]; get_user_name( idattacker, szName, 31 );
new iOwner = pev( ent, pev_iuser2 );
engfunc( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, gDispenserOrigin[ iOwner ], 0 ); write_byte( TE_EXPLOSION ); engfunc( EngFunc_WriteCoord, gDispenserOrigin[ iOwner ][ 0 ] ); engfunc( EngFunc_WriteCoord, gDispenserOrigin[ iOwner ][ 1 ] ); engfunc( EngFunc_WriteCoord, gDispenserOrigin[ iOwner ][ 2 ] ); write_short( gExplosionSprite ); write_byte( 30 ); write_byte( 10 ); write_byte( 0 ); message_end( );
new victim = -1; new Float:fPlayerOrigin[ 3 ], Float:fPlayerVelocity[ 3 ], Float:fDmgToDo, Float:distance; while ( ( victim = engfunc( EngFunc_FindEntityInSphere, victim, gDispenserOrigin[ iOwner ], 250.0 ) ) != 0 ) { if( !is_user_alive( victim ) ) continue;
pev( victim, pev_origin, fPlayerOrigin ); distance = get_distance_f( gDispenserOrigin[ iOwner ], fPlayerOrigin );
fDmgToDo = DISPENSER_EXPLOSION_MAXDMG - ( DISPENSER_EXPLOSION_MAXDMG * ( distance / 250.0 ) ); ExecuteHam( Ham_TakeDamage, victim, ent, iOwner, fDmgToDo, DMG_BLAST );
if ( ( pev( victim, pev_flags ) & FL_ONGROUND ) && fPlayerOrigin[ 2 ] < gDispenserOrigin[ iOwner ][ 2 ] ) fPlayerOrigin[ 2 ] = gDispenserOrigin[ iOwner ][ 2 ] + distance;
pev( victim, pev_velocity, fPlayerVelocity );
for ( new i = 0; i < 3; i++ ) fPlayerVelocity[ i ] = ( ( ( fPlayerOrigin[ i ] - gDispenserOrigin[ iOwner ][ i ] ) * 250.0 / distance + gDispenserOrigin[ iOwner ][ i ] ) - fPlayerOrigin[ i ] ) * 3.0;
set_pev( victim, pev_velocity, fPlayerVelocity ); }
bDispenserID[ iOwner ] = 0; set_pev( ent, pev_flags, pev( ent, pev_flags ) | FL_KILLME );
return HAM_IGNORED; }
emit_sound( ent, CHAN_STATIC, gDamageSounds[ random_num( 0, charsmax( gDamageSounds ) ) ], VOL_NORM, ATTN_NORM, 0, PITCH_NORM ); }
return HAM_IGNORED; }
public bacon_TraceAttack( iVictim, iAttacker, Float:flDamage, Float:flDirection[ 3 ], iTr, iDamageBits ) { if( !pev_valid( iVictim ) ) return HAM_IGNORED;
if( !is_user_connected( iAttacker ) ) return HAM_IGNORED;
new szClassname[ 32 ]; pev( iVictim, pev_classname, szClassname, charsmax( szClassname ) );
if( equal( szClassname, gDispenserClassname ) ) { if( pev( iVictim, pev_team ) == fm_get_user_team( iAttacker ) ) return HAM_SUPERCEDE;
new Float:flEndOrigin[ 3 ]; get_tr2( iTr, TR_vecEndPos, flEndOrigin );
UTIL_Sparks( flEndOrigin ); }
return HAM_IGNORED; }
public bacon_Touch( iEnt, id ) { if( !pev_valid( iEnt ) ) return HAM_IGNORED;
if( !is_user_alive( id ) ) return HAM_IGNORED;
new szClassname[ 32 ]; pev( iEnt, pev_classname, szClassname, charsmax( szClassname ) );
if( equal( szClassname, gDispenserClassname ) ) { if( CanUpgradeDispenser( iEnt, id ) ) { if( fm_get_user_money( id ) >= DispenserCosts[ pev( iEnt, pev_iuser1 ) + 1 ] ) DispenserUpgrade( iEnt, id ); } }
return HAM_IGNORED; }
public EVENT_Spawn( id ) { if( !is_user_alive( id ) ) return HAM_IGNORED;
if( !pev_valid( bDispenserID[ id ] ) ) return HAM_IGNORED;
new iTeam = fm_get_user_team( id ); if( iTeam == pev( bDispenserID[ id ], pev_team ) ) return HAM_IGNORED;
set_pev( bDispenserID[ id ], pev_team, iTeam );
new iLevel = pev( bDispenserID[ id ], pev_iuser1 ); set_pev( bDispenserID[ id ], pev_body, ( iTeam == 2 ) ? iLevel : iLevel + 3 ); fm_set_rendering( bDispenserID[ id ], kRenderFxGlowShell, gBeamColor[ iTeam - 1 ][ 0 ], gBeamColor[ iTeam - 1 ][ 1 ], gBeamColor[ iTeam - 1 ][ 2 ], kRenderNormal, 3 );
return HAM_IGNORED; }
public DispenserThink( iEnt ) { if( !pev_valid( iEnt ) ) return FMRES_IGNORED;
new szClassname[ 32 ]; pev( iEnt, pev_classname, szClassname, 31 );
if( !equal( szClassname, gDispenserClassname ) ) return FMRES_IGNORED;
switch( pev( iEnt, pev_iuser3 ) ) { case STATUS_BUILDING: fm_set_rendering( iEnt, kRenderFxDistort, 255, 255, 255, kRenderTransAdd, 70 ); case STATUS_ACTIVE: { new iOwner = pev( iEnt, pev_iuser2 ); new iTeam = pev( iEnt, pev_team ); new iLevel = pev( iEnt, pev_iuser1 ); new id = -1;
while( ( id = engfunc( EngFunc_FindEntityInSphere, id, gDispenserOrigin[ iOwner ], float( DispenserHealRadius[ iLevel ] ) ) ) != 0 ) { if( !is_user_alive( id ) ) continue;
if( fm_get_user_team( id ) != iTeam ) continue;
if( !UTIL_IsVisible( id, iEnt ) ) continue;
new Float:health; pev( id, pev_health, health );
if( health + 1.0 > float( DispenserMaxHealing[ iLevel ] ) ) continue;
set_pev( id, pev_health, health + 1.0 );
new Float:flOrigin[ 3 ]; pev( id, pev_origin, flOrigin ); UTIL_BeamEnts( flOrigin, gDispenserOrigin[ iOwner ], 50, 200, 50 ); } } }
new Float:flAngles[ 3 ]; pev( iEnt, pev_angles, flAngles ); flAngles[ 1 ] += 1.0;
set_pev( iEnt, pev_angles, flAngles ); set_pev( iEnt, pev_nextthink, get_gametime( ) + 0.1 );
return FMRES_IGNORED; }
public FW_Traceline( Float:start[ 3 ], Float:end[ 3 ], noMonsters, id ) { if( !is_user_alive( id ) ) return FMRES_IGNORED;
new iEnt = get_tr( TR_pHit );
if( !pev_valid( iEnt ) ) { if( bTrigger[ id ] ) { ClearSyncHud( id , g_HUDSync ); bTrigger[ id ] = false; } return FMRES_IGNORED; }
new szClassname[ 32 ]; pev( iEnt, pev_classname, szClassname, 31 );
if( !equal( szClassname, gDispenserClassname ) ) { if( bTrigger[ id ] ) { ClearSyncHud( id , g_HUDSync ); bTrigger[ id ] = false; } return FMRES_IGNORED; }
new iTeam = pev( iEnt, pev_team ) - 1; new iLevel = pev( iEnt, pev_iuser1 ) + 1; new szName[ 32 ], szUpgrade[ 17 ]; get_user_name( pev( iEnt, pev_iuser2 ), szName, 31 );
if( CanUpgradeDispenser( iEnt, id ) ) formatex( szUpgrade, 16, "^n[Upgrade: %d$]", DispenserCosts[ iLevel ] );
set_hudmessage( gBeamColor[ iTeam ][ 0 ] , gBeamColor[ iTeam ][ 1 ] , gBeamColor[ iTeam ][ 2 ] , -1.0 , 0.38 , .holdtime=0.4 , .channel=-1 ); ShowSyncHudMsg( id, g_HUDSync, "[Heal Machine]^n[Owner: %s]^n[HP: %d/%d]^n[Level: %d]%s", szName, pev( iEnt, pev_health ), DispenserMaxHealth[ iLevel - 1 ], iLevel, szUpgrade ); bTrigger[ id ] = true;
return FMRES_IGNORED; }
stock UTIL_BeamEnts( Float:flStart[ 3 ], Float:flEnd[ 3 ], r, g, b ) { engfunc( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flStart ); write_byte( TE_BEAMPOINTS ); engfunc( EngFunc_WriteCoord, flStart[ 0 ] ); engfunc( EngFunc_WriteCoord, flStart[ 1 ] ); engfunc( EngFunc_WriteCoord, flStart[ 2 ] ); engfunc( EngFunc_WriteCoord, flEnd[ 0 ] ); engfunc( EngFunc_WriteCoord, flEnd[ 1 ] ); engfunc( EngFunc_WriteCoord, flEnd[ 2 ] ); write_short( gHealingBeam ); write_byte( 1 ); write_byte( 1 ); write_byte( 1 ); write_byte( 25 ); write_byte( 0 ); write_byte( r ); write_byte( g ); write_byte( b ); write_byte( 255 ); write_byte( 20 ); message_end( ); }
stock UTIL_Sparks( Float:flOrigin[ 3 ] ) { engfunc( EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, flOrigin, 0 ); write_byte( TE_SPARKS ); engfunc( EngFunc_WriteCoord, flOrigin[ 0 ] ); engfunc( EngFunc_WriteCoord, flOrigin[ 1 ] ); engfunc( EngFunc_WriteCoord, flOrigin[ 2 ] ); message_end( ); }
stock bool:UTIL_IsVisible( index, entity ) { new Float:flStart[ 3 ], Float:flDest[ 3 ]; pev( index, pev_origin, flStart ); pev( index, pev_view_ofs, flDest );
for( new i = 0; i < 3; i++ ) flStart[ i ] += flDest[ i ];
pev( entity, pev_origin, flDest ); engfunc( EngFunc_TraceLine, flStart, flDest, IGNORE_MONSTERS, index, 0 );
new Float:flFraction; get_tr2( 0, TR_flFraction, flFraction );
if( flFraction == 1.0 || get_tr2( 0, TR_pHit ) == entity ) return true;
return false; }
stock fm_get_user_money( id ) return get_pdata_int( id, 115, 5 );
stock fm_set_user_money( id, money, flash=1 ) { set_pdata_int( id, 115, money, 5 );
message_begin( MSG_ONE_UNRELIABLE, g_msgMoney, _, id ); write_long( money ); write_byte( flash ? 1 : 0 ); message_end( );
return 1; }
stock fm_get_user_team( id ) return get_pdata_int( id, 114 );
stock fm_set_rendering( entity, fx = kRenderFxNone, r = 255, g = 255, b = 255, render = kRenderNormal, amount = 16 ) { new Float:RenderColor[ 3 ]; RenderColor[ 0 ] = float( r ); RenderColor[ 1 ] = float( g ); RenderColor[ 2 ] = float( b );
set_pev( entity, pev_renderfx, fx ); set_pev( entity, pev_rendercolor, RenderColor ); set_pev( entity, pev_rendermode, render ); set_pev( entity, pev_renderamt, float( amount ) );
return 1; }
These are the forwards I have added/briefly modified :
Code:
RegisterHam( Ham_TakeDamage, szDispenserClassname, "bacon_TakeDamage", 0 );
RegisterHam( Ham_Touch, szDispenserClassname, "bacon_Touch" );
RegisterHam( Ham_Spawn, "player", "EVENT_Spawn", 1 );
register_forward( FM_TraceLine, "FW_Traceline", 1 );
Besides that I have added some entity information in pev_iuser1-4 (entity's levels and additional stuff), but I don't think that this is the reason for such frequent crashes. Could someone please look through and tell me what is wrong, maybe you will find a mistake. There has got to be a stupid small mistake for sure.
I have also moved Ham_TakeDamage from Post to Pre. (Because grenade damage can't be blocked in post event)
Last edited by HamletEagle; 03-17-2016 at 15:57.
Reason: Post fixed
|
|