Modme Forums

Detect damage on a model ( NO TRIGGERS )

Game Modding | Call of Duty: Black Ops 3 | Scripting


ModmeBot:

Thread By: Harry Bo21

function your_function_name()
{
	e_model = getEnt( "YOUR_KVP_VALUE", "script_noteworthy" );
	e_model setCanDamage( 1 );
    
	while ( 1 )
	{
		e_model waittill( "damage", damage, attacker, dir, point, mod, model, tag, part, weapon, flags, inflictor, chargeLevel );
        
		if ( weapon.name == "weapon_name" ) // Optional if you want a certain weapon only to count
			break;
        
	}
	
	// Your code to run when this model is damaged
	playFx( "fx_path\fx_name", e_model.origin ); // If you want a fx to play on the model when it is damaged
	e_model delete(); // If you want the model to delete when shot
}


ModmeBot:

Reply By: mathfag
Don't forget to precache


ModmeBot:

Reply By: Harry Bo21

mathfag
Don't forget to precache

...

everything in level._effect is precached already

precaching again wastes one of the available 800 fx


ModmeBot:

Reply By: mathfag
You wrote "fx_path\fx_name" not level._effect["fx_path\fx_name"] therefore precache. :)


ModmeBot:

Reply By: Abnormal202

mathfag
You wrote "fx_path\fx_name" not level._effect["fx_path\fx_name"] therefore precache. :)

oh c'mon you're just being nitpicky on purpose. people should know how FX works, and if not they should know this script is not the place to learn it, as FX isn't even related to the topic at hand.


ModmeBot:

Reply By: Harry Bo21
Detect damage on a model ( NO TRIGGERS )

Detect damage on a model

not

how to play a fx when a model is shot

i merely advised where to play a fx and how to delete the model - as OPTIONAL extra snippits of info, and the way to do it, not a full tutorial on playing fx

at least my code WORKS so do one


ModmeBot:

Reply By: eDeK
Nice script, by the way, how i can change the "e_model" is a "zombie" and only count the "melee weapons"?
How i can detect the player is knifing a zombie?

function your_function_name()
{
	zombies = level.zombie_team;
    
	while ( 1 )
	{
		zombies waittill( "damage", damage, attacker, dir, point, mod, model, tag, part, weapon, flags, inflictor, chargeLevel );
        
		if ( weapon.name == "MOD_MELEE" ) // Optional if you want a certain weapon only to count
			break;
		}        
	}

	//my code	
	
}


ModmeBot:

Reply By: ihmiskeho

eDeK
Nice script, by the way, how i can change the "e_model" is a "zombie" and only count the "melee weapons"? How i can detect the player is knifing a zombie? function your_function_name() { zombies = level.zombie_team; while ( 1 ) { zombies waittill( "damage", damage, attacker, dir, point, mod, model, tag, part, weapon, flags, inflictor, chargeLevel ); if ( weapon.name == "MOD_MELEE" ) // Optional if you want a certain weapon only to count break; } } //my code }


if ( mod == "MOD_MELEE" )
Also you should check that the damager is actually a player
if ( mod == "MOD_MELEE" && IsPlayer(attacker) )


ModmeBot:

Reply By: eDeK
Im doing a Powerup, this function is "when the player knife the zombie", but not work, i dont know how detect "the player is knifing a zombie".

function knife_me()
{
	self endon( "disconnect" );
    self endon( "death" );
    self endon( "pyrotechnic_done" );

    zombies = level.zombie_team;
               
    zombies waittill( "damage", damage, attacker, dir, point, mod, model, tag, part, weapon, flags, inflictor, chargeLevel );      
    {
	    if ( mod == "MOD_MELEE" && IsPlayer(attacker) )	 
	    {
	        self fire_works_summon( self );	
	    }
	}    

	WAIT_SERVER_FRAME;	
    
}
Thanks for reply/help.


ModmeBot:

Reply By: tom5300

eDeK
Im doing a Powerup, this function is "when the player knife the zombie", but not work, i dont know how detect "the player is knifing a zombie". function knife_me() { self endon( "disconnect" ); self endon( "death" ); self endon( "pyrotechnic_done" ); zombies = level.zombie_team; zombies waittill( "damage", damage, attacker, dir, point, mod, model, tag, part, weapon, flags, inflictor, chargeLevel ); { if ( mod == "MOD_MELEE" && IsPlayer(attacker) ) { self fire_works_summon( self ); } } WAIT_SERVER_FRAME; } Thanks for reply/help.

You cannot waittill on a variable containing the string "axis". You will have to iterate through each zombie, and thread a waittill on each zombie.

I'd try something like:

function knife_me()
{
    zombies = GetAiTeamArray( level.zombie_team );
    foreach(zombie in zombies)
    {
        zombie thread wait_for_knife();
    }
}
function wait_for_knife()
{
    self endon( "disconnect" );
    self endon( "death" );
    self endon( "pyrotechnic_done" );
    while(1)
    {
        self waittill( "damage", damage, attacker, dir, point, mod, model, tag, part, weapon, flags, inflictor, chargeLevel );
        if ( mod == "MOD_MELEE" && IsPlayer(attacker) )	 
        {
            self fire_works_summon( self );	
        }
        WAIT_SERVER_FRAME;
    }
}

Note: I have not tested this code, hope it's error free.


ModmeBot:

Reply By: eDeK
Thanks for reply Tom but dont work it.
I need like <span style="color:#ffffff;">ihmiskeho</span> say "the damager is actually a player".
Is something like that:

if(isdefined(attacker) &amp;&amp; attacker.team != self.team &amp;&amp; !isdefined(attacker.playername))  
{
	if ( mod == "MOD_MELEE" &amp;&amp; IsPlayer(attacker) )	 
    {
        self fire_works_summon( self );	
    }
}
But this no work too. :(


ModmeBot:

Reply By: mathfag

zm_spawner::register_zombie_damage_callback( &amp;knife_dmg ); //in function main

//when a AI is damaged, this will run
//self = AI
function knife_dmg(str_mod, str_hit_location, v_hit_origin, e_player, n_amount, w_weapon, direction_vec, tagName, modelName, partName, dFlags, inflictor, chargeLevel) 
{

if(str_mod == "MOD_MELEE")
	self thread fire_works_summon();

}

function fire_works_summon()
{
//use this new function or you may run into problems


}


ModmeBot:

Reply By: eDeK
Works fine Mathfag, thanks for reply dude, the problem is when i grab the powerup the "Knifing effect (fireworks)" dont stop, still active after the powerup is over.

function __init__()
{
	
	zm_powerups::register_powerup( "pyrotechnic", &amp;grab_pyrotechnic );
	if( ToLower( GetDvarString( "g_gametype" ) ) != "pyrotechnic" )
	{
		zm_powerups::add_zombie_powerup( "pyrotechnic", "pyrotechnic_powerup_model", "", &amp;zm_powerups::func_should_always_drop, POWERUP_ONLY_AFFECTS_GRABBER, !POWERUP_ANY_TEAM, !POWERUP_ZOMBIE_GRABBABLE );						
	} 
}

function grab_pyrotechnic( player )
{
	player PlayLocalSound("vox_pyrotechnic");
	skip = player add_powerup_hud( "pyrotechnic_material_hud", N_POWERUP_DEFAULT_TIME );
    zm_spawner::register_zombie_damage_callback( &amp;knife_dmg );    

	if( skip )
		return; 
	
	if( isdefined(player.pyrotechnic_active) )
		return;		
	
	player thread do_pyrotechnic();
}

function do_pyrotechnic()
{
	self.pyrotechnic_active = true;

    self notify( "pyrotechnic_done" );
    self endon( "disconnect" );
    self endon( "death" );
    self endon( "pyrotechnic_done" );

    self thread knife_dmg();	
}

function knife_dmg(str_mod, str_hit_location, v_hit_origin, e_player, n_amount, w_weapon, direction_vec, tagName, modelName, partName, dFlags, inflictor, chargeLevel) 
{		
    self endon( "disconnect" );
    self endon( "death" );
    self endon( "pyrotechnic_done" );

	if(str_mod == "MOD_MELEE")
	{
		self thread fire_works_summon( e_player, w_weapon );
	}

	WAIT_SERVER_FRAME;
}


ModmeBot:

Reply By: mathfag
Put this in __init__. It should only be activated once.

zm_spawner::register_zombie_damage_callback( &amp;knife_dmg );

Remove
self thread knife_dmg();

Replace
self.pyrotechnic_active = true;
with
level.pyrotechnic_active = true;

Replace function knife_dmg() with
function knife_dmg(str_mod, str_hit_location, v_hit_origin, e_player, n_amount, w_weapon, direction_vec, tagName, modelName, partName, dFlags, inflictor, chargeLevel) 
{		

if(level.pyrotechnic_active == 0)
return 0;

	if(str_mod == "MOD_MELEE")
	{
		self thread fire_works_summon( e_player, w_weapon );
	}

	WAIT_SERVER_FRAME;
}

Make sure
level.pyrotechnic_active
is set to false when the powerup is over


ModmeBot:

Reply By: eDeK
I do all you say.
When i spawn in the game (I shoot the zombies, i cant do points and the "Knife effect is active").
After this, i grab the powerup (I shoot the zombies, i can do points but the "Knife effect is no active" even after powerup is over.").
Very weird all, i gonna still testing but at the moment i have this.

//POWERUP
function __init__()
{	
	zm_powerups::register_powerup( "pyrotechnic", &amp;grab_pyrotechnic );
	if( ToLower( GetDvarString( "g_gametype" ) ) != "pyrotechnic" )
	{
		zm_powerups::add_zombie_powerup( "pyrotechnic", "pyrotechnic_powerup_model", "", &amp;zm_powerups::func_should_always_drop, POWERUP_ONLY_AFFECTS_GRABBER, !POWERUP_ANY_TEAM, !POWERUP_ZOMBIE_GRABBABLE );
		zm_spawner::register_zombie_damage_callback( &amp;knife_dmg );					
	} 
}

function grab_pyrotechnic( player )
{
	player PlayLocalSound("vox_pyrotechnic");
	skip = player add_powerup_hud( "pyrotechnic_material_hud", N_POWERUP_DEFAULT_TIME );    	

	if( skip )
		return; 
	
	if( isdefined(player.pyrotechnic_active) )
		return;		
	
	player thread do_pyrotechnic();
}

function do_pyrotechnic()
{
	level.pyrotechnic_active = true;

    self notify( "pyrotechnic_done" );
    self endon( "disconnect" );
    self endon( "death" );
    self endon( "pyrotechnic_done" );    
}

function knife_dmg(str_mod, str_hit_location, v_hit_origin, e_player, n_amount, w_weapon, direction_vec, tagName, modelName, partName, dFlags, inflictor, chargeLevel) 
{		

	if(level.pyrotechnic_active == 0)
	return 0;

	if(str_mod == "MOD_MELEE")
	{
		self thread fire_works_summon( e_player, w_weapon );
	}

	WAIT_SERVER_FRAME;
}

//HUD
function wait_til_timeout( player, hud )//player = self;
{
	while( hud.time &gt; 0 )
	{
		wait(1);
		hud.time--; 		
	}
	
	player notify( "pyrotechnic_done" );
	player remove_powerup_hud( "pyrotechnic_material_hud" );
	player.pyrotechnic_active = undefined;
	
	
}

function add_powerup_hud( powerup, timer )
{
	if ( !isDefined( self.powerup_hud ) )
		self.powerup_hud = [];
	
	if( isDefined( self.powerup_hud[powerup] ) )
	{
		self.powerup_hud[powerup].time = timer; 
		return true; // tells to skip because powerup is already active
				
	}
	
	self endon( "disconnect" );
	hud = NewClientHudElem( self );
	hud.powerup = powerup;
	hud.foreground = true;
	hud.hidewheninmenu = true;
	hud.alignX = "center";
	hud.alignY = "bottom";
	hud.horzAlign = "center";
	hud.vertAlign = "bottom";
	hud.x = hud.x;
	hud.y = hud.y - 50;
	hud.alpha = 1;
	hud SetShader( powerup , 64, 64 );
	hud scaleOverTime( .5, 32, 32 );
	hud.time = timer;
	hud thread harrybo21_blink_powerup_hud();
	thread wait_til_timeout( self, hud ); 
	
	self.powerup_hud[ powerup ] = hud;
	
	a_keys = GetArrayKeys( self.powerup_hud );
	for ( i = 0; i &lt; a_keys.size; i++ )
	 	self.powerup_hud[ a_keys[i] ] thread move_hud( .5, 0 - ( 24 * ( self.powerup_hud.size ) ) + ( i * 37.5 ) + 25, self.powerup_hud[ a_keys[i] ].y );
	
	//return false;  // powerup is not already active
	level.pyrotechnic_active = false;
		

}

function move_hud( time, x, y )
{
	self moveOverTime( time );
	self.x = x;
	self.y = y;
}

function harrybo21_blink_powerup_hud()
{
	self endon( "delete" );
	self endon( "stop_fade" );
	while( isDefined( self ) )
	{
		if ( self.time &gt;= 20 )
		{
			self.alpha = 1; 
			wait .1;
			continue;
		}
		fade_time = 1;
		if ( self.time &lt; 10 )
			fade_time = .5;
		if ( self.time &lt; 5 )
			fade_time = .25;
			
		self fadeOverTime( fade_time );
		self.alpha = !self.alpha;
		
		wait( fade_time );
	}
}

function remove_powerup_hud( powerup )
{
	self.powerup_hud[ powerup ] destroy();
	self.powerup_hud[ powerup ] notify( "stop_fade" );
	self.powerup_hud[ powerup ] fadeOverTime( .2 );
	self.alpha = 0;
	wait .2;
	self.powerup_hud[ powerup ] delete();
	self.powerup_hud[ powerup ] = undefined;
	self.powerup_hud = array::remove_index( self.powerup_hud, self.powerup_hud[ powerup ], true );
	
	a_keys = GetArrayKeys( self.powerup_hud );
	for ( i = 0; i &lt; a_keys.size; i++ )
	 	self.powerup_hud[ a_keys[i] ] thread move_hud( .5, 0 - ( 24 * ( self.powerup_hud.size ) ) + ( i * 37.5 ) + 25, self.powerup_hud[ a_keys[i] ].y );
}


//FIREWORKS
// Checks to see if fire works is running
// self == zombie
function fire_works_zombie_validation()
{
	if( IS_TRUE( self.barricade_enter ) )
	{
		return false;
	}
	
	if ( IS_TRUE( self.is_traversing ) )
	{
		return false;
	}

	if( !IS_TRUE( self.completed_emerging_into_playable_area ) &amp;&amp; !IsDefined( self.first_node ) )
	{
		return false;
	}

	if ( IS_TRUE( self.is_leaping ) )
	{
		return false;
	}
	
	return true;
}

// Summons the player&#39;s current gun to pop up and fire in a circle for a period of time
// immune_result_direct == target is immune to death gib
// immune_result_indirect == target is immune to death gib on hit from the magic bullet
// self == target zombie
function fire_works_summon( e_player, w_weapon )
{
	w_summoned_weapon = e_player GetCurrentWeapon();
	v_target_zombie_origin = self.origin;
	
	// Checks if self is immune_result_direct == true. If so, do not kill self
	if ( !IS_TRUE( level.aat[ ZM_AAT_FIRE_WORKS_NAME ].immune_result_direct[ self.archetype ] ) )
	{
		self thread zombie_death_gib( e_player, w_weapon, e_player );
	}

	// Spawns base model
	v_firing_pos = v_target_zombie_origin + ZM_AAT_FIRE_WORKS_ZOMBIE_GUN_HEIGHT;
	v_start_yaw = VectorToAngles( v_firing_pos - v_target_zombie_origin );
	v_start_yaw = (0, v_start_yaw[1], 0);
	mdl_weapon = zm_utility::spawn_weapon_model( w_summoned_weapon, undefined, v_target_zombie_origin, v_start_yaw );

	// Stat tracking definitions
	mdl_weapon.owner = e_player;
	mdl_weapon.b_aat_fire_works_weapon = true;
	mdl_weapon.allow_zombie_to_target_ai = true; // lets the zombie damage callbacks pass through damage from this
	
	// Fires FX
	mdl_weapon thread clientfield::set( ZM_AAT_FIRE_WORKS_NAME, 1 );
	
	// Moves weapon upwards to firing position
	mdl_weapon MoveTo( v_firing_pos, ZM_AAT_FIRE_WORKS_SUMMON_TIME );
	mdl_weapon waittill( "movedone" );

	// Starts firing
	for ( i = 0; i &lt; ZM_AAT_FIRE_WORKS_FIRING_NUM_FRAMES; i++ )
	{
		zombie = mdl_weapon zm_aat_fire_works_get_target();
		if ( !IsDefined( zombie ) )
		{
			//if no target available, just pick a random yaw
			v_curr_yaw = (0, RandomIntRange( 0, 360 ), 0);
			v_target_pos = mdl_weapon.origin + VectorScale( AnglesToForward( v_curr_yaw ), 40 );
		}
		else
		{
			v_target_pos = zombie GetCentroid();
		}

		mdl_weapon.angles = VectorToAngles( v_target_pos - mdl_weapon.origin );
		v_flash_pos = mdl_weapon GetTagOrigin( "tag_flash" );
		mdl_weapon DontInterpolate();

		// MagicBullet shots are credited to the model rather than player, as MagicBullet causes recoil on player
		MagicBullet( w_summoned_weapon, v_flash_pos, v_target_pos, mdl_weapon );

		util::wait_network_frame();
	}

	mdl_weapon MoveTo( v_target_zombie_origin, ZM_AAT_FIRE_WORKS_SUMMON_TIME );
	mdl_weapon waittill( "movedone" );
	
	mdl_weapon clientfield::set( ZM_AAT_FIRE_WORKS_NAME, 0 );
	
	util::wait_network_frame(); // Waits for FX to complete
	util::wait_network_frame(); // extra waits for theater playback
	util::wait_network_frame(); // extra waits for theater playback
	
	mdl_weapon Delete();
	wait .25; // Delay for final projectile-based gun shots to finish firing
}

// Death callback for zombies killed by summoned Fire Works weapon
function zm_aat_fire_works_get_target()
{
	a_ai_zombies = array::randomize( GetAiTeamArray( "axis" ) );

	los_checks = 0;
	for ( i = 0; i &lt; a_ai_zombies.size; i++ )
	{
		zombie = a_ai_zombies[i];
		test_origin = zombie getcentroid();
		if ( DistanceSquared( self.origin, test_origin ) &gt; ZM_AAT_FIRE_WORKS_RANGE_SQ )
		{
			continue;
		}

		if ( los_checks &lt; ZM_AAT_FIRE_WORKS_MAX_LOS_CHECKS &amp;&amp; !zombie DamageConeTrace( self.origin ) )
		{
			los_checks++;
			continue;
		}

		return zombie;
	}

	if ( a_ai_zombies.size )
	{
		// just return the first one, so that we at least change direction
		return a_ai_zombies[0];
	}

	return undefined;
}

// self is a zombie
function zm_aat_fire_works_zombie_damage_response( str_mod, str_hit_location, v_hit_origin, e_attacker, n_amount, w_weapon, direction_vec, tagName, modelName, partName, dFlags, inflictor, chargeLevel )
{
	if ( IS_TRUE( level.aat[ ZM_AAT_FIRE_WORKS_NAME ].immune_result_indirect[ self.archetype ] ) )
	{
		return false;
	}

	if ( IS_TRUE( e_attacker.b_aat_fire_works_weapon ) )
	{
		self thread zombie_death_gib( e_attacker, w_weapon, e_attacker.owner );
		return true;
	}

	return false;
}

// Death callback for zombies killed by summoned Fire Works weapon
function zm_aat_fire_works_death_callback( attacker )
{
	if ( isdefined( attacker ) )
	{
		if ( IS_TRUE( attacker.b_aat_fire_works_weapon ) )
		{
			// Checks if player has disconnected
			if ( isdefined( attacker.owner ) )
			{
				e_attacking_player = attacker.owner;
				// TODO set up stat tracking
			}
		}
	}
}

// Gibs and Kills zombie
// self == affected zombie
// e_attacker == the script_model of the gun (needs to do the damage, so the player doesn&#39;t receive kickback)
// w_weapon == the weapon to apply damage using
// e_owner == the owner of the gun (for awarding challenge stat progress)
function zombie_death_gib( e_attacker, w_weapon, e_owner )
{
	gibserverutils::gibhead( self );
	
	if ( math::cointoss() )
	{
		gibserverutils::gibleftarm( self );
	}
	else
	{
		gibserverutils::gibrightarm( self );
	}
	
	gibserverutils::giblegs( self );
	
	self DoDamage( self.health, self.origin, e_attacker, w_weapon, "torso_upper" );

	if ( IsDefined( e_owner ) &amp;&amp; IsPlayer( e_owner ) )
	{
		e_owner zm_stats::increment_challenge_stat( "ZOMBIE_HUNTER_FIRE_WORKS" );
	}
}
Thanks for your time Mathfag.


ModmeBot:

Reply By: mathfag
in grab_pyrotechnic change

if( isdefined(player.pyrotechnic_active) )

to
if( isdefined(player.pyrotechnic_active) &amp;&amp; player.pyrotechnic_active == 1 )

just incase.


The problem is that you set
level.pyrotechnic_active = false;

immediately after setting it to true. Actually you did it before but im guessing since the cpu has to process a bunch of code it gets set after.
anyway
Move
level.pyrotechnic_active = false;

to the end of
function wait_til_timeout


ModmeBot:

Reply By: eDeK

mathfag
in grab_pyrotechnic change if( isdefined(player.pyrotechnic_active) ) to if( isdefined(player.pyrotechnic_active) && player.pyrotechnic_active == 1 ) just incase. The problem is that you set level.pyrotechnic_active = false; immediately after setting it to true. Actually you did it before but im guessing since the cpu has to process a bunch of code it gets set after. anyway Move level.pyrotechnic_active = false; to the end of function wait_til_timeout

I dont have words to describe my gratitude with you, seriously, thanks.


When i spawn in the game the "Knife effect" is active, i grab the powerup for the first time, the "Knife effect" still active, when the powerup is over, the "Knife effect" is over. (Everything goes back to normal)

I grab the powerup for the second time, the powerup is working perfect all the time.
//POWERUP
function __init__()
{	
	zm_powerups::register_powerup( "pyrotechnic", &amp;grab_pyrotechnic );
	if( ToLower( GetDvarString( "g_gametype" ) ) != "pyrotechnic" )
	{
		zm_powerups::add_zombie_powerup( "pyrotechnic", "pyrotechnic_powerup_model", "", &amp;zm_powerups::func_should_always_drop, POWERUP_ONLY_AFFECTS_GRABBER, !POWERUP_ANY_TEAM, !POWERUP_ZOMBIE_GRABBABLE );
		zm_spawner::register_zombie_damage_callback( &amp;knife_dmg );					
	} 
}

function grab_pyrotechnic( player )
{
	player PlayLocalSound("vox_pyrotechnic");
	skip = player add_powerup_hud( "pyrotechnic_material_hud", N_POWERUP_DEFAULT_TIME );    	

	if( skip )
		return; 
	
	if( isdefined(player.pyrotechnic_active) &amp;&amp; player.pyrotechnic_active == 1 )
		return;		
	
	player thread do_pyrotechnic();

}

function do_pyrotechnic()
{
	level.pyrotechnic_active = true;

    self notify( "pyrotechnic_done" );
    self endon( "disconnect" );
    self endon( "death" );
    self endon( "pyrotechnic_done" );

       
}

function knife_dmg(str_mod, str_hit_location, v_hit_origin, e_player, n_amount, w_weapon, direction_vec, tagName, modelName, partName, dFlags, inflictor, chargeLevel) 
{		

	if(level.pyrotechnic_active == 0)
	return 0;

	if(str_mod == "MOD_MELEE")
	{
		self thread fire_works_summon( e_player, w_weapon );
	}

	WAIT_SERVER_FRAME;
}

//HUD
function wait_til_timeout( player, hud )//player = self;
{
	while( hud.time &gt; 0 )
	{
		wait(1);
		hud.time--; 		
	}
	
	player notify( "pyrotechnic_done" );
	player remove_powerup_hud( "pyrotechnic_material_hud" );
	player.pyrotechnic_active = undefined;
	level.pyrotechnic_active = false;
	
	
}

function add_powerup_hud( powerup, timer )
{
	if ( !isDefined( self.powerup_hud ) )
		self.powerup_hud = [];
	
	if( isDefined( self.powerup_hud[powerup] ) )
	{
		self.powerup_hud[powerup].time = timer; 
		return true; // tells to skip because powerup is already active
				
	}
	
	self endon( "disconnect" );
	hud = NewClientHudElem( self );
	hud.powerup = powerup;
	hud.foreground = true;
	hud.hidewheninmenu = true;
	hud.alignX = "center";
	hud.alignY = "bottom";
	hud.horzAlign = "center";
	hud.vertAlign = "bottom";
	hud.x = hud.x;
	hud.y = hud.y - 50;
	hud.alpha = 1;
	hud SetShader( powerup , 64, 64 );
	hud scaleOverTime( .5, 32, 32 );
	hud.time = timer;
	hud thread harrybo21_blink_powerup_hud();
	thread wait_til_timeout( self, hud ); 
	
	self.powerup_hud[ powerup ] = hud;
	
	a_keys = GetArrayKeys( self.powerup_hud );
	for ( i = 0; i &lt; a_keys.size; i++ )
	 	self.powerup_hud[ a_keys[i] ] thread move_hud( .5, 0 - ( 24 * ( self.powerup_hud.size ) ) + ( i * 37.5 ) + 25, self.powerup_hud[ a_keys[i] ].y );
	
	return false;  // powerup is not already active
}




function move_hud( time, x, y )
{
	self moveOverTime( time );
	self.x = x;
	self.y = y;
}

function harrybo21_blink_powerup_hud()
{
	self endon( "delete" );
	self endon( "stop_fade" );
	while( isDefined( self ) )
	{
		if ( self.time &gt;= 20 )
		{
			self.alpha = 1; 
			wait .1;
			continue;
		}
		fade_time = 1;
		if ( self.time &lt; 10 )
			fade_time = .5;
		if ( self.time &lt; 5 )
			fade_time = .25;
			
		self fadeOverTime( fade_time );
		self.alpha = !self.alpha;
		
		wait( fade_time );
	}
}

function remove_powerup_hud( powerup )
{
	self.powerup_hud[ powerup ] destroy();
	self.powerup_hud[ powerup ] notify( "stop_fade" );
	self.powerup_hud[ powerup ] fadeOverTime( .2 );
	self.alpha = 0;
	wait .2;
	self.powerup_hud[ powerup ] delete();
	self.powerup_hud[ powerup ] = undefined;
	self.powerup_hud = array::remove_index( self.powerup_hud, self.powerup_hud[ powerup ], true );
	
	a_keys = GetArrayKeys( self.powerup_hud );
	for ( i = 0; i &lt; a_keys.size; i++ )
	 	self.powerup_hud[ a_keys[i] ] thread move_hud( .5, 0 - ( 24 * ( self.powerup_hud.size ) ) + ( i * 37.5 ) + 25, self.powerup_hud[ a_keys[i] ].y );
}


ModmeBot:

Reply By: mathfag

eDeK
mathfag in grab_pyrotechnic change if( isdefined(player.pyrotechnic_active) ) to if( isdefined(player.pyrotechnic_active) && player.pyrotechnic_active == 1 ) just incase. The problem is that you set level.pyrotechnic_active = false; immediately after setting it to true. Actually you did it before but im guessing since the cpu has to process a bunch of code it gets set after. anyway Move level.pyrotechnic_active = false; to the end of function wait_til_timeout I dont have words to describe my gratitude with you, seriously, thanks. When i spawn in the game the "Knife effect" is active, i grab the powerup for the first time, the "Knife effect" still active, when the powerup is over, the "Knife effect" is over. (Everything goes back to normal) I grab the powerup for the second time, the powerup is working perfect all the time. //POWERUP function __init__() { zm_powerups::register_powerup( "pyrotechnic", &grab_pyrotechnic ); if( ToLower( GetDvarString( "g_gametype" ) ) != "pyrotechnic" ) { zm_powerups::add_zombie_powerup( "pyrotechnic", "pyrotechnic_powerup_model", "", &zm_powerups::func_should_always_drop, POWERUP_ONLY_AFFECTS_GRABBER, !POWERUP_ANY_TEAM, !POWERUP_ZOMBIE_GRABBABLE ); zm_spawner::register_zombie_damage_callback( &knife_dmg ); } } function grab_pyrotechnic( player ) { player PlayLocalSound("vox_pyrotechnic"); skip = player add_powerup_hud( "pyrotechnic_material_hud", N_POWERUP_DEFAULT_TIME ); if( skip ) return; if( isdefined(player.pyrotechnic_active) && player.pyrotechnic_active == 1 ) return; player thread do_pyrotechnic(); } function do_pyrotechnic() { level.pyrotechnic_active = true; self notify( "pyrotechnic_done" ); self endon( "disconnect" ); self endon( "death" ); self endon( "pyrotechnic_done" ); } function knife_dmg(str_mod, str_hit_location, v_hit_origin, e_player, n_amount, w_weapon, direction_vec, tagName, modelName, partName, dFlags, inflictor, chargeLevel) { if(level.pyrotechnic_active == 0) return 0; if(str_mod == "MOD_MELEE") { self thread fire_works_summon( e_player, w_weapon ); } WAIT_SERVER_FRAME; } //HUD function wait_til_timeout( player, hud )//player = self; { while( hud.time > 0 ) { wait(1); hud.time--; } player notify( "pyrotechnic_done" ); player remove_powerup_hud( "pyrotechnic_material_hud" ); player.pyrotechnic_active = undefined; level.pyrotechnic_active = false; } function add_powerup_hud( powerup, timer ) { if ( !isDefined( self.powerup_hud ) ) self.powerup_hud = []; if( isDefined( self.powerup_hud[powerup] ) ) { self.powerup_hud[powerup].time = timer; return true; // tells to skip because powerup is already active } self endon( "disconnect" ); hud = NewClientHudElem( self ); hud.powerup = powerup; hud.foreground = true; hud.hidewheninmenu = true; hud.alignX = "center"; hud.alignY = "bottom"; hud.horzAlign = "center"; hud.vertAlign = "bottom"; hud.x = hud.x; hud.y = hud.y - 50; hud.alpha = 1; hud SetShader( powerup , 64, 64 ); hud scaleOverTime( .5, 32, 32 ); hud.time = timer; hud thread harrybo21_blink_powerup_hud(); thread wait_til_timeout( self, hud ); self.powerup_hud[ powerup ] = hud; a_keys = GetArrayKeys( self.powerup_hud ); for ( i = 0; i < a_keys.size; i++ ) self.powerup_hud[ a_keys] thread move_hud( .5, 0 - ( 24 * ( self.powerup_hud.size ) ) + ( i * 37.5 ) + 25, self.powerup_hud[ a_keys].y ); return false; // powerup is not already active } function move_hud( time, x, y ) { self moveOverTime( time ); self.x = x; self.y = y; } function harrybo21_blink_powerup_hud() { self endon( "delete" ); self endon( "stop_fade" ); while( isDefined( self ) ) { if ( self.time >= 20 ) { self.alpha = 1; wait .1; continue; } fade_time = 1; if ( self.time < 10 ) fade_time = .5; if ( self.time < 5 ) fade_time = .25; self fadeOverTime( fade_time ); self.alpha = !self.alpha; wait( fade_time ); } } function remove_powerup_hud( powerup ) { self.powerup_hud[ powerup ] destroy(); self.powerup_hud[ powerup ] notify( "stop_fade" ); self.powerup_hud[ powerup ] fadeOverTime( .2 ); self.alpha = 0; wait .2; self.powerup_hud[ powerup ] delete(); self.powerup_hud[ powerup ] = undefined; self.powerup_hud = array::remove_index( self.powerup_hud, self.powerup_hud[ powerup ], true ); a_keys = GetArrayKeys( self.powerup_hud ); for ( i = 0; i < a_keys.size; i++ ) self.powerup_hud[ a_keys] thread move_hud( .5, 0 - ( 24 * ( self.powerup_hud.size ) ) + ( i * 37.5 ) + 25, self.powerup_hud[ a_keys].y ); }
in function __init__ add
level.pyrotechnic_active = 0;

because if you do
if(level.pyrotechnic_active == 0)

when it's undefined it screws up

also the line
if( ToLower( GetDvarString( "g_gametype" ) ) != "pyrotechnic" )
is pointless


ModmeBot:

Reply By: eDeK
Yeah, the line is:

if( ToLower( GetDvarString( "g_gametype" ) ) != "zcleansed" )
My fault writing, work perfect now, thanks again, the unique thing i need buff is the score "i cant do points, shooting or knifing, with the powerup active" i dont know why, i need to do a callback to the player/zombie?