492 lines
12 KiB
Plaintext

#include maps/mp/_scoreevents;
#include maps/mp/killstreaks/_killstreak_weapons;
#include maps/mp/killstreaks/_killstreaks;
#include common_scripts/utility;
#include maps/mp/_utility;
#using_animtree( "mp_riotshield" );
init()
{
if ( !isDefined( level.riotshield_name ) )
{
level.riotshield_name = "riotshield_mp";
if ( isDefined( level.is_zombie_level ) && level.is_zombie_level )
{
level.riotshield_name = "riotshield_zm";
}
}
level.deployedshieldmodel = "t6_wpn_shield_carry_world";
level.stowedshieldmodel = "t6_wpn_shield_stow_world";
level.carriedshieldmodel = "t6_wpn_shield_carry_world";
level.detectshieldmodel = "t6_wpn_shield_carry_world_detect";
if ( isDefined( level.is_zombie_level ) && level.is_zombie_level )
{
level.deployedshieldmodel = "t6_wpn_zmb_shield_world";
level.stowedshieldmodel = "t6_wpn_zmb_shield_stow";
level.carriedshieldmodel = "t6_wpn_zmb_shield_world";
}
precachemodel( level.stowedshieldmodel );
precachemodel( level.carriedshieldmodel );
precachemodel( level.detectshieldmodel );
level.riotshielddestroyanim = %o_riot_stand_destroyed;
level.riotshielddeployanim = %o_riot_stand_deploy;
level.riotshieldshotanimfront = %o_riot_stand_shot;
level.riotshieldshotanimback = %o_riot_stand_shot_back;
level.riotshieldmeleeanimfront = %o_riot_stand_melee_front;
level.riotshieldmeleeanimback = %o_riot_stand_melee_back;
loadfx( "weapon/riotshield/fx_riotshield_depoly_lights" );
loadfx( "weapon/riotshield/fx_riotshield_depoly_dust" );
level.riotshield_placement_zoffset = 26;
}
register()
{
registerclientfield( "scriptmover", "riotshield_state", 1, 2, "int" );
}
watchpregameclasschange()
{
self endon( "death" );
self endon( "disconnect" );
self endon( "track_riot_shield" );
self waittill( "changed_class" );
if ( level.ingraceperiod && !self.hasdonecombat )
{
self clearstowedweapon();
self refreshshieldattachment();
self thread trackriotshield();
}
}
watchriotshieldpickup()
{
self endon( "death" );
self endon( "disconnect" );
self endon( "track_riot_shield" );
self notify( "watch_riotshield_pickup" );
self endon( "watch_riotshield_pickup" );
self waittill( "pickup_riotshield" );
self endon( "weapon_change" );
/#
println( "Picked up riotshield, expecting weapon_change notify..." );
#/
wait 0,5;
/#
println( "picked up shield but didn't change weapons, attach it!" );
#/
self.hasriotshield = self hasweapon( level.riotshield_name );
self.hasriotshieldequipped = self getcurrentweapon() == level.riotshield_name;
self refreshshieldattachment();
}
trackriotshield()
{
self endon( "death" );
self endon( "disconnect" );
self notify( "track_riot_shield" );
self endon( "track_riot_shield" );
self thread watchpregameclasschange();
self waittill( "weapon_change", newweapon );
self refreshshieldattachment();
self.hasriotshield = self hasweapon( level.riotshield_name );
self.hasriotshieldequipped = self getcurrentweapon() == level.riotshield_name;
self.lastnonshieldweapon = "none";
while ( 1 )
{
self thread watchriotshieldpickup();
currentweapon = self getcurrentweapon();
self.hasriotshield = self hasweapon( level.riotshield_name );
self.hasriotshieldequipped = self getcurrentweapon() == level.riotshield_name;
refresh_attach = 0;
self waittill( "weapon_change", newweapon );
if ( newweapon == level.riotshield_name )
{
refresh_attach = 1;
if ( isDefined( self.riotshieldentity ) )
{
self notify( "destroy_riotshield" );
}
if ( self.hasriotshield )
{
if ( isDefined( self.riotshieldtakeweapon ) )
{
self takeweapon( self.riotshieldtakeweapon );
self.riotshieldtakeweapon = undefined;
}
}
if ( isvalidnonshieldweapon( currentweapon ) )
{
self.lastnonshieldweapon = currentweapon;
}
}
if ( self.hasriotshield || refresh_attach == 1 )
{
self refreshshieldattachment();
}
}
}
isvalidnonshieldweapon( weapon )
{
if ( maps/mp/killstreaks/_killstreaks::iskillstreakweapon( weapon ) )
{
return 0;
}
if ( maps/mp/killstreaks/_killstreak_weapons::isheldkillstreakweapon( weapon ) )
{
return 0;
}
if ( maps/mp/killstreaks/_killstreak_weapons::isgameplayweapon( weapon ) )
{
return 0;
}
if ( weapon == "none" )
{
return 0;
}
if ( isweaponequipment( weapon ) )
{
return 0;
}
return 1;
}
startriotshielddeploy()
{
self notify( "start_riotshield_deploy" );
self thread watchriotshielddeploy();
}
resetreconmodelvisibility( owner )
{
if ( !isDefined( self ) )
{
return;
}
self setinvisibletoall();
self setforcenocull();
if ( !isDefined( owner ) )
{
return;
}
i = 0;
while ( i < level.players.size )
{
if ( level.players[ i ] hasperk( "specialty_showenemyequipment" ) )
{
if ( level.players[ i ].team == "spectator" )
{
i++;
continue;
}
else
{
isenemy = 1;
if ( level.teambased )
{
if ( level.players[ i ].team == owner.team )
{
isenemy = 0;
}
}
else
{
if ( level.players[ i ] == owner )
{
isenemy = 0;
}
}
if ( isenemy )
{
self setvisibletoplayer( level.players[ i ] );
}
}
}
i++;
}
}
resetreconmodelonevent( eventname, owner )
{
self endon( "death" );
for ( ;; )
{
level waittill( eventname, newowner );
if ( isDefined( newowner ) )
{
owner = newowner;
}
self resetreconmodelvisibility( owner );
}
}
attachreconmodel( modelname, owner )
{
if ( !isDefined( self ) )
{
return;
}
reconmodel = spawn( "script_model", self.origin );
reconmodel.angles = self.angles;
reconmodel setmodel( modelname );
reconmodel.model_name = modelname;
reconmodel linkto( self );
reconmodel setcontents( 0 );
reconmodel resetreconmodelvisibility( owner );
reconmodel thread resetreconmodelonevent( "joined_team", owner );
reconmodel thread resetreconmodelonevent( "player_spawned", owner );
self.reconmodel = reconmodel;
}
spawnriotshieldcover( origin, angles )
{
shield_ent = spawn( "script_model", origin, 1 );
shield_ent.targetname = "riotshield_mp";
shield_ent.angles = angles;
shield_ent setmodel( level.deployedshieldmodel );
shield_ent setowner( self );
shield_ent.owner = self;
shield_ent.team = self.team;
shield_ent setteam( self.team );
shield_ent attachreconmodel( level.detectshieldmodel, self );
shield_ent useanimtree( -1 );
shield_ent setscriptmoverflag( 0 );
shield_ent disconnectpaths();
return shield_ent;
}
watchriotshielddeploy()
{
self endon( "death" );
self endon( "disconnect" );
self endon( "start_riotshield_deploy" );
self waittill( "deploy_riotshield", deploy_attempt );
self setheldweaponmodel( 0 );
self setplacementhint( 1 );
placement_hint = 0;
if ( deploy_attempt )
{
placement = self canplaceriotshield( "deploy_riotshield" );
if ( placement[ "result" ] )
{
self.hasdonecombat = 1;
zoffset = level.riotshield_placement_zoffset;
shield_ent = self spawnriotshieldcover( placement[ "origin" ] + ( 0, 0, zoffset ), placement[ "angles" ] );
item_ent = deployriotshield( self, shield_ent );
primaries = self getweaponslistprimaries();
/#
assert( isDefined( item_ent ) );
assert( !isDefined( self.riotshieldretrievetrigger ) );
assert( !isDefined( self.riotshieldentity ) );
if ( level.gametype != "shrp" )
{
assert( primaries.size > 0 );
#/
}
shield_ent setclientfield( "riotshield_state", 1 );
shield_ent.reconmodel setclientfield( "riotshield_state", 1 );
if ( level.gametype != "shrp" )
{
if ( self.lastnonshieldweapon != "none" && self hasweapon( self.lastnonshieldweapon ) )
{
self switchtoweapon( self.lastnonshieldweapon );
}
else
{
self switchtoweapon( primaries[ 0 ] );
}
}
if ( !self hasweapon( "knife_held_mp" ) )
{
self giveweapon( "knife_held_mp" );
self.riotshieldtakeweapon = "knife_held_mp";
}
self.riotshieldretrievetrigger = item_ent;
self.riotshieldentity = shield_ent;
self thread watchdeployedriotshieldents();
self thread deleteshieldontriggerdeath( self.riotshieldretrievetrigger );
self thread deleteshieldonplayerdeathordisconnect( shield_ent );
self.riotshieldentity thread watchdeployedriotshielddamage();
level notify( "riotshield_planted" );
}
else
{
placement_hint = 1;
clip_max_ammo = weaponclipsize( level.riotshield_name );
self setweaponammoclip( level.riotshield_name, clip_max_ammo );
}
}
else
{
placement_hint = 1;
}
if ( placement_hint )
{
self setriotshieldfailhint();
}
}
riotshielddistancetest( origin )
{
/#
assert( isDefined( origin ) );
#/
min_dist_squared = getDvarFloat( "riotshield_deploy_limit_radius" );
min_dist_squared *= min_dist_squared;
i = 0;
while ( i < level.players.size )
{
if ( isDefined( level.players[ i ].riotshieldentity ) )
{
dist_squared = distancesquared( level.players[ i ].riotshieldentity.origin, origin );
if ( min_dist_squared > dist_squared )
{
/#
println( "Shield placement denied! Failed distance check to other riotshields." );
#/
return 0;
}
}
i++;
}
return 1;
}
watchdeployedriotshieldents()
{
/#
assert( isDefined( self.riotshieldretrievetrigger ) );
assert( isDefined( self.riotshieldentity ) );
#/
self waittill( "destroy_riotshield" );
if ( isDefined( self.riotshieldretrievetrigger ) )
{
self.riotshieldretrievetrigger delete();
}
if ( isDefined( self.riotshieldentity ) )
{
if ( isDefined( self.riotshieldentity.reconmodel ) )
{
self.riotshieldentity.reconmodel delete();
}
self.riotshieldentity connectpaths();
self.riotshieldentity delete();
}
}
watchdeployedriotshielddamage()
{
self endon( "death" );
damagemax = getDvarInt( "riotshield_deployed_health" );
self.damagetaken = 0;
while ( 1 )
{
self.maxhealth = 100000;
self.health = self.maxhealth;
self waittill( "damage", damage, attacker, direction, point, type, tagname, modelname, partname, weaponname, idflags );
while ( !isDefined( attacker ) )
{
continue;
}
/#
if ( isDefined( self.owner ) )
{
assert( isDefined( self.owner.team ) );
}
#/
while ( isplayer( attacker ) )
{
while ( level.teambased && attacker.team == self.owner.team && attacker != self.owner )
{
continue;
}
}
if ( type == "MOD_MELEE" )
{
damage *= getDvarFloat( "riotshield_melee_damage_scale" );
}
else if ( type == "MOD_PISTOL_BULLET" || type == "MOD_RIFLE_BULLET" )
{
damage *= getDvarFloat( "riotshield_bullet_damage_scale" );
}
else
{
if ( type != "MOD_GRENADE" && type != "MOD_GRENADE_SPLASH" && type != "MOD_EXPLOSIVE" && type != "MOD_EXPLOSIVE_SPLASH" || type == "MOD_PROJECTILE" && type == "MOD_PROJECTILE_SPLASH" )
{
damage *= getDvarFloat( "riotshield_explosive_damage_scale" );
break;
}
else
{
if ( type == "MOD_IMPACT" )
{
damage *= getDvarFloat( "riotshield_projectile_damage_scale" );
break;
}
else
{
if ( type == "MOD_CRUSH" )
{
damage = damagemax;
}
}
}
}
self.damagetaken += damage;
if ( self.damagetaken >= damagemax )
{
self thread damagethendestroyriotshield( attacker, weaponname );
return;
}
else
{
}
}
}
damagethendestroyriotshield( attacker, weaponname )
{
self notify( "damageThenDestroyRiotshield" );
self endon( "death" );
if ( isDefined( self.owner.riotshieldretrievetrigger ) )
{
self.owner.riotshieldretrievetrigger delete();
}
if ( isDefined( self.reconmodel ) )
{
self.reconmodel delete();
}
self connectpaths();
self.owner.riotshieldentity = undefined;
self notsolid();
self setclientfield( "riotshield_state", 2 );
if ( isDefined( attacker ) && isDefined( weaponname ) && attacker != self.owner && isplayer( attacker ) )
{
maps/mp/_scoreevents::processscoreevent( "destroyed_shield", attacker, self.owner, weaponname );
}
wait getDvarFloat( "riotshield_destroyed_cleanup_time" );
self delete();
}
deleteshieldontriggerdeath( shield_trigger )
{
shield_trigger waittill_any( "trigger", "death" );
self notify( "destroy_riotshield" );
}
deleteshieldonplayerdeathordisconnect( shield_ent )
{
shield_ent endon( "death" );
shield_ent endon( "damageThenDestroyRiotshield" );
self waittill_any( "death", "disconnect", "remove_planted_weapons" );
shield_ent thread damagethendestroyriotshield();
}
watchriotshieldstuckentitydeath( grenade, owner )
{
grenade endon( "death" );
self waittill_any( "damageThenDestroyRiotshield", "death", "disconnect", "weapon_change", "deploy_riotshield" );
grenade detonate( owner );
}