@@ -111,25 +111,9 @@ void CASW_Weapon_Laser_Mines::PrimaryAttack( void )
111111 {
112112#ifdef CLIENT_DLL
113113 if ( !prediction->InPrediction () || prediction->IsFirstTimePredicted () )
114- #endif
114+ #endif
115115 {
116- Vector vecSrc = pMarine->GetAbsOrigin ();
117- vecSrc.z += 16 .0f ; // place lower to catch shorter aliens
118- Vector vecAiming = pPlayer->GetAutoaimVectorForMarine (pMarine, GetAutoAimAmount (), GetVerticalAdjustOnlyAutoAimAmount ()); // 45 degrees = 0.707106781187
119- vecAiming.z = 0 ;
120- vecAiming.NormalizeInPlace ();
121-
122- const int nMinesPerShot = MarineSkills ()->GetSkillBasedValueByMarine ( pMarine, ASW_MARINE_SKILL_GRENADES, ASW_MARINE_SUBSKILL_GRENADE_LASER_MINES );
123- const float flSpread = 30 .0f ; // spread of mine throwing in degrees
124-
125- // try to predict whether mine throw is valid, if not then dont do the animation.
126- // small problem: this prediction happens a little earlier than the actual throw, so there will be occassional cases when the animation does play when it shouldnt have or it will not play when it should have. though still better than always playing imo.
127- if ( GetThrownMineCount ( nMinesPerShot, vecSrc, vecAiming, flSpread ) > 0 )
128- {
129- pMarine->DoAnimationEvent ( PLAYERANIMEVENT_THROW_GRENADE );
130-
131- EmitSound ( " ASW_Mine.Throw" );
132- }
116+ pMarine->DoAnimationEvent ( PLAYERANIMEVENT_THROW_GRENADE );
133117 }
134118
135119 // start our delayed attack
@@ -176,14 +160,125 @@ void CASW_Weapon_Laser_Mines::DelayedAttack( void )
176160
177161 for ( int i = 0 ; i < nMinesPerShot; i++ )
178162 {
179- CBaseEntity *pParent = NULL ;
180- trace_t tr ;
163+ // throw each mine out at a different angle
164+ QAngle angRot = vec3_angle ;
181165 Vector vecMineAiming = vecAiming;
182-
183- if ( !ValidateThrow ( i, nMinesPerShot, vecSrc, vecAiming, flSpread, bOnGround, pParent, tr, vecMineAiming ) )
184- continue ;
166+ angRot[ YAW ] = ( (float ) i / (float ) nMinesPerShot ) * flSpread - ( 0 .5f * flSpread );
167+ VectorRotate ( vecAiming, angRot, vecMineAiming );
168+
169+ // trace for a wall in front of the marine
170+ const float flDeployDistance = 180 .0f ;
171+ // if ( i != 1 ) // randomize all but the middle mine's distance slightly
172+ // {
173+ // flDeployDistance += SharedRandomFloat( "LaserMineVariation", -20.0f, 20.0f );
174+ // }
175+ trace_t tr;
176+
177+ if ( !pMarine->IsInhabited () )
178+ {
179+ bOnGround = true ;
180+ #ifndef CLIENT_DLL
181+
182+ Vector vecDest = pMarine->m_vecOffhandItemSpot ;
183+
184+ vecDest.z += 16 ;
185+ if ( i == 0 || i == 2 ) // drop to the side
186+ {
187+ Vector vecPerpendicular;
188+ VectorRotate ( vecAiming, QAngle ( 0 , 90 , 0 ), vecPerpendicular );
189+ Vector vecNewDest = vecDest + vecPerpendicular * ( ( i == 0 ) ? 32 : -32 );
190+ UTIL_TraceLine ( vecDest, vecNewDest, MASK_SOLID, pMarine, COLLISION_GROUP_DEBRIS, &tr ); // trace out to the sides
191+ if ( tr.startsolid )
192+ continue ;
193+
194+ if ( !tr.DidHit () )
195+ {
196+ // trace down again
197+ vecDest = vecNewDest;
198+ UTIL_TraceLine ( vecDest, vecDest - Vector ( 0 , 0 , 128 ), MASK_SOLID, pMarine, COLLISION_GROUP_DEBRIS, &tr );
199+ }
200+ }
201+ else
202+ {
203+ UTIL_TraceLine ( vecDest, vecDest - Vector ( 0 , 0 , 128 ), MASK_SOLID, pMarine, COLLISION_GROUP_DEBRIS, &tr );
204+ }
205+ if ( tr.startsolid )
206+ continue ;
207+
208+ if ( !tr.DidHit () )
209+ continue ;
210+ #endif
211+ }
212+ else
213+ {
214+ UTIL_TraceLine ( vecSrc, vecSrc + vecMineAiming * flDeployDistance, MASK_SOLID, pMarine, COLLISION_GROUP_DEBRIS, &tr );
215+
216+ if ( tr.startsolid ) // if we started in solid, trace again from the marine's center
217+ {
218+ vecSrc.x = pMarine->WorldSpaceCenter ().x ;
219+ vecSrc.y = pMarine->WorldSpaceCenter ().y ;
220+ UTIL_TraceLine ( vecSrc, vecSrc + vecMineAiming * flDeployDistance, MASK_SOLID, pMarine, COLLISION_GROUP_DEBRIS, &tr );
221+ if ( tr.startsolid )
222+ continue ;
223+ }
224+
225+ if ( !tr.DidHit () )
226+ {
227+ // do another trace to try and put it on the ground
228+ #ifndef CLIENT_DLL
229+ Vector vecDest = pPlayer->GetCrosshairTracePos ();
230+ if ( vecDest.DistTo ( vecSrc ) > flDeployDistance )
231+ {
232+ trace_t tr2;
233+ UTIL_TraceLine ( tr.endpos , tr.endpos + Vector ( 0 , 0 , -128 ), MASK_SOLID, pMarine, COLLISION_GROUP_DEBRIS, &tr2 );
234+ tr = tr2;
235+ }
236+ else
237+ {
238+ // just put it under the xhair
239+ vecDest.z += 16 ;
240+ if ( i == 0 || i == 2 ) // drop to the side
241+ {
242+ Vector vecPerpendicular;
243+ VectorRotate ( vecAiming, QAngle ( 0 , 90 , 0 ), vecPerpendicular );
244+ Vector vecNewDest = vecDest + vecPerpendicular * ( ( i == 0 ) ? 32 : -32 );
245+ UTIL_TraceLine ( vecDest, vecNewDest, MASK_SOLID, pMarine, COLLISION_GROUP_DEBRIS, &tr ); // trace out to the sides
246+ if ( tr.startsolid )
247+ continue ;
248+
249+ if ( !tr.DidHit () )
250+ {
251+ // trace down again
252+ vecDest = vecNewDest;
253+ UTIL_TraceLine ( vecDest, vecDest - Vector ( 0 , 0 , 128 ), MASK_SOLID, pMarine, COLLISION_GROUP_DEBRIS, &tr );
254+ }
255+ }
256+ else
257+ {
258+ UTIL_TraceLine ( vecDest, vecDest - Vector ( 0 , 0 , 128 ), MASK_SOLID, pMarine, COLLISION_GROUP_DEBRIS, &tr );
259+ }
260+ }
261+
262+ if ( tr.startsolid )
263+ continue ;
264+
265+ if ( !tr.DidHit () )
266+ continue ;
267+ #endif
268+ bOnGround = true ;
269+ }
270+ }
185271
186272#ifndef CLIENT_DLL
273+ CBaseEntity *pParent = NULL ;
274+ if ( tr.m_pEnt && !tr.m_pEnt ->IsWorld () )
275+ {
276+ pParent = tr.m_pEnt ;
277+ }
278+ // no attaching to alien noses
279+ if ( pParent && ( pParent->IsNPC () || pParent->Classify () == CLASS_ASW_STATUE ) )
280+ continue ;
281+
187282 // calculate the laser aim offset relative to the mine facing
188283 QAngle angFacing, angLaser, angLaserOffset;
189284 VectorAngles ( tr.plane .normal , angFacing );
@@ -198,8 +293,6 @@ void CASW_Weapon_Laser_Mines::DelayedAttack( void )
198293 RotationDelta ( angFacing, angLaser, &angLaserOffset );
199294
200295 CASW_Laser_Mine *pMine = CASW_Laser_Mine::ASW_Laser_Mine_Create ( tr.endpos , angFacing, angLaserOffset, pMarine, pParent, true , this );
201- pMine->m_vecSurfaceNormal = tr.plane .normal ;
202-
203296 IGameEvent * event = gameeventmanager->CreateEvent ( " laser_mine_placed" );
204297 if ( event )
205298 {
@@ -235,154 +328,6 @@ void CASW_Weapon_Laser_Mines::DelayedAttack( void )
235328 m_flNextPrimaryAttack = gpGlobals->curtime ;
236329}
237330
238- bool CASW_Weapon_Laser_Mines::ValidateThrow ( int nMineNumber, int nMinesPerShot, Vector vecSrc, Vector vecAiming, float flSpread, bool &bOnGround, CBaseEntity *pParent, trace_t &tr, Vector &vecMineAiming )
239- {
240- CASW_Player *pPlayer = GetCommander ();
241- if ( !pPlayer )
242- return false ;
243-
244- CASW_Marine *pMarine = GetMarine ();
245- if ( !pMarine || pMarine->GetWaterLevel () == 3 )
246- return false ;
247-
248- // throw each mine out at a different angle
249- QAngle angRot = vec3_angle;
250- angRot[ YAW ] = ( (float ) nMineNumber / (float ) nMinesPerShot ) * flSpread - ( 0 .5f * flSpread );
251- VectorRotate ( vecAiming, angRot, vecMineAiming );
252-
253- // trace for a wall in front of the marine
254- const float flDeployDistance = 180 .0f ;
255- // if ( i != 1 ) // randomize all but the middle mine's distance slightly
256- // {
257- // flDeployDistance += SharedRandomFloat( "LaserMineVariation", -20.0f, 20.0f );
258- // }
259-
260- if ( !pMarine->IsInhabited () )
261- {
262- bOnGround = true ;
263- #ifndef CLIENT_DLL
264-
265- Vector vecDest = pMarine->m_vecOffhandItemSpot ;
266-
267- vecDest.z += 16 ;
268- if ( nMineNumber == 0 || nMineNumber == 2 ) // drop to the side
269- {
270- Vector vecPerpendicular;
271- VectorRotate ( vecAiming, QAngle ( 0 , 90 , 0 ), vecPerpendicular );
272- Vector vecNewDest = vecDest + vecPerpendicular * ( ( nMineNumber == 0 ) ? 32 : -32 );
273- UTIL_TraceLine ( vecDest, vecNewDest, MASK_SOLID, pMarine, COLLISION_GROUP_NONE, &tr ); // trace out to the sides
274- if ( tr.startsolid )
275- return false ;
276-
277- if ( !tr.DidHit () )
278- {
279- // trace down again
280- vecDest = vecNewDest;
281- UTIL_TraceLine ( vecDest, vecDest - Vector ( 0 , 0 , 128 ), MASK_SOLID, pMarine, COLLISION_GROUP_NONE, &tr );
282- }
283- }
284- else
285- {
286- UTIL_TraceLine ( vecDest, vecDest - Vector ( 0 , 0 , 128 ), MASK_SOLID, pMarine, COLLISION_GROUP_NONE, &tr );
287- }
288- if ( tr.startsolid )
289- return false ;
290-
291- if ( !tr.DidHit () )
292- return false ;
293- #endif
294- }
295- else
296- {
297- UTIL_TraceLine ( vecSrc, vecSrc + vecMineAiming * flDeployDistance, MASK_SOLID, pMarine, COLLISION_GROUP_NONE, &tr );
298-
299- if ( tr.startsolid ) // if we started in solid, trace again from the marine's center
300- {
301- vecSrc.x = pMarine->WorldSpaceCenter ().x ;
302- vecSrc.y = pMarine->WorldSpaceCenter ().y ;
303- UTIL_TraceLine ( vecSrc, vecSrc + vecMineAiming * flDeployDistance, MASK_SOLID, pMarine, COLLISION_GROUP_NONE, &tr );
304- if ( tr.startsolid )
305- return false ;
306- }
307-
308- if ( !tr.DidHit () )
309- {
310- // do another trace to try and put it on the ground
311- // #ifndef CLIENT_DLL
312- Vector vecDest = pMarine->GetOffhandThrowDest ();
313- if ( vecDest.DistTo ( vecSrc ) > flDeployDistance )
314- {
315- trace_t tr2;
316- UTIL_TraceLine ( tr.endpos , tr.endpos + Vector ( 0 , 0 , -128 ), MASK_SOLID, pMarine, COLLISION_GROUP_NONE, &tr2 );
317- tr = tr2;
318- }
319- else
320- {
321- // just put it under the xhair
322- vecDest.z += 16 ;
323- if ( nMineNumber == 0 || nMineNumber == 2 ) // drop to the side
324- {
325- Vector vecPerpendicular;
326- VectorRotate ( vecAiming, QAngle ( 0 , 90 , 0 ), vecPerpendicular );
327- Vector vecNewDest = vecDest + vecPerpendicular * ( ( nMineNumber == 0 ) ? 32 : -32 );
328- UTIL_TraceLine ( vecDest, vecNewDest, MASK_SOLID, pMarine, COLLISION_GROUP_NONE, &tr ); // trace out to the sides
329- if ( tr.startsolid )
330- return false ;
331-
332- if ( !tr.DidHit () )
333- {
334- // trace down again
335- vecDest = vecNewDest;
336- UTIL_TraceLine ( vecDest, vecDest - Vector ( 0 , 0 , 128 ), MASK_SOLID, pMarine, COLLISION_GROUP_NONE, &tr );
337- }
338- }
339- else
340- {
341- UTIL_TraceLine ( vecDest, vecDest - Vector ( 0 , 0 , 128 ), MASK_SOLID, pMarine, COLLISION_GROUP_NONE, &tr );
342- }
343- }
344-
345- if ( tr.startsolid )
346- return false ;
347-
348- if ( !tr.DidHit () )
349- return false ;
350- // #endif
351- bOnGround = true ;
352- }
353- }
354-
355- // #ifndef CLIENT_DLL
356- if ( tr.m_pEnt && !tr.m_pEnt ->IsWorld () )
357- {
358- pParent = tr.m_pEnt ;
359- }
360- // no attaching to alien noses
361- if ( pParent && (pParent->IsNPC () || pParent->Classify () == CLASS_ASW_STATUE) )
362- return false ;
363- // #endif
364-
365- return true ;
366- }
367-
368- int CASW_Weapon_Laser_Mines::GetThrownMineCount ( int nMinesPerShot, Vector vecSrc, Vector vecAiming, float flSpread )
369- {
370- int nThrown = 0 ;
371-
372- for ( int i = 0 ; i < nMinesPerShot; i++ )
373- {
374- CBaseEntity *pParent = NULL ;
375- trace_t tr;
376- Vector vecMineAiming = vecAiming;
377- bool bOnGround = false ;
378-
379- if ( ValidateThrow ( i, nMinesPerShot, vecSrc, vecAiming, flSpread, bOnGround, pParent, tr, vecMineAiming ) )
380- nThrown++;
381- }
382-
383- return nThrown;
384- }
385-
386331void CASW_Weapon_Laser_Mines::Precache ()
387332{
388333 BaseClass::Precache ();
0 commit comments