From f00a8f46d8fe9d19729cd36438b0fa5a4d308234 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 22 Jul 2023 04:21:00 +0300 Subject: [PATCH 01/10] client: studio: fix types in AArch64 NEON code --- cl_dll/studio_util.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cl_dll/studio_util.cpp b/cl_dll/studio_util.cpp index 2d4bad80..c2fb3bed 100644 --- a/cl_dll/studio_util.cpp +++ b/cl_dll/studio_util.cpp @@ -24,9 +24,9 @@ AngleMatrix ==================== */ #if XASH_SIMD_NEON -const uint32x4_t AngleMatrix_sign0 = vreinterpretq_f32_u32(vsetq_lane_u32(0x80000000, vdupq_n_u32(0), 0)); -const uint32x4_t AngleMatrix_sign1 = vreinterpretq_f32_u32(vsetq_lane_u32(0x80000000, vdupq_n_u32(0), 1)); -const uint32x4_t AngleMatrix_sign2 = vreinterpretq_f32_u32(vsetq_lane_u32(0x80000000, vdupq_n_u32(0), 2)); +static const uint32x4_t AngleMatrix_sign0 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0), 0); +static const uint32x4_t AngleMatrix_sign1 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0), 1); +static const uint32x4_t AngleMatrix_sign2 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0), 2); #endif void AngleMatrix( const float *angles, float (*matrix)[4] ) { @@ -254,7 +254,11 @@ AngleQuaternion ==================== */ #if XASH_SIMD_NEON -const float32x4_t AngleQuaternion_sign2 = vzipq_f32(vdupq_n_u32(0x80000000), vdupq_n_u32(0x00000000)).val[0]; // { 0x80000000, 0x00000000, 0x80000000, 0x00000000 }; +static const float32x4_t AngleQuaternion_sign2 = + vzipq_f32( + vreinterpret_f32_u32(vdupq_n_u32(0x80000000)), + vreinterpret_f32_u32(vdupq_n_u32(0x00000000)) + ).val[0]; // { 0x80000000, 0x00000000, 0x80000000, 0x00000000 }; #endif void AngleQuaternion( float *angles, vec4_t quaternion ) { @@ -272,7 +276,7 @@ void AngleQuaternion( float *angles, vec4_t quaternion ) float32x4_t sy_cr_cy_sr = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 1); float32x4_t cr_cy_sr_sy = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 2); float32x4_t cy_sr_sy_cr = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 3); - float32x4_t sp_sp_sp_sp_signed = veorq_u32(sp_sp_sp_sp, AngleQuaternion_sign2); + float32x4_t sp_sp_sp_sp_signed = veorq_u32(vreinterpret_u32_f32(sp_sp_sp_sp), AngleQuaternion_sign2); float32x4_t left = vmulq_f32(vmulq_f32(sr_sy_cr_cy, cp_cp_cp_cp), cy_sr_sy_cr); From b4bd06603e871c54a40e798c6c8a9a6d344e98c8 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 22 Jul 2023 04:28:51 +0300 Subject: [PATCH 02/10] client: studio: fix NEON vreinterpret types, fix memcpy --- cl_dll/studio_util.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cl_dll/studio_util.cpp b/cl_dll/studio_util.cpp index c2fb3bed..00419a39 100644 --- a/cl_dll/studio_util.cpp +++ b/cl_dll/studio_util.cpp @@ -216,7 +216,7 @@ void ConcatTransforms( float in1[3][4], float in2[3][4], float out[3][4] ) out_reg.val[2] = vfmaq_laneq_f32(out_reg.val[2], in2_reg.val[1], in1_reg.val[2], 1); out_reg.val[2] = vfmaq_laneq_f32(out_reg.val[2], in2_reg.val[2], in1_reg.val[2], 2); - memcpy(&out, &out_reg, sizeof(out)); + memcpy(out, &out_reg, sizeof(float) * 3 * 4); #else out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0]; @@ -256,8 +256,8 @@ AngleQuaternion #if XASH_SIMD_NEON static const float32x4_t AngleQuaternion_sign2 = vzipq_f32( - vreinterpret_f32_u32(vdupq_n_u32(0x80000000)), - vreinterpret_f32_u32(vdupq_n_u32(0x00000000)) + vreinterpretq_f32_u32(vdupq_n_u32(0x80000000)), + vreinterpretq_f32_u32(vdupq_n_u32(0x00000000)) ).val[0]; // { 0x80000000, 0x00000000, 0x80000000, 0x00000000 }; #endif void AngleQuaternion( float *angles, vec4_t quaternion ) @@ -276,7 +276,7 @@ void AngleQuaternion( float *angles, vec4_t quaternion ) float32x4_t sy_cr_cy_sr = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 1); float32x4_t cr_cy_sr_sy = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 2); float32x4_t cy_sr_sy_cr = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 3); - float32x4_t sp_sp_sp_sp_signed = veorq_u32(vreinterpret_u32_f32(sp_sp_sp_sp), AngleQuaternion_sign2); + float32x4_t sp_sp_sp_sp_signed = veorq_u32(vreinterpretq_u32_f32(sp_sp_sp_sp), AngleQuaternion_sign2); float32x4_t left = vmulq_f32(vmulq_f32(sr_sy_cr_cy, cp_cp_cp_cp), cy_sr_sy_cr); From d4995df92ceb921fbfbd46f3f6f41fbd2bcac8bc Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 22 Jul 2023 04:36:03 +0300 Subject: [PATCH 03/10] client: studio: another NEON type fix for AngleQuaternion, static-ize global NEON vectors --- cl_dll/studio_util.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/cl_dll/studio_util.cpp b/cl_dll/studio_util.cpp index 00419a39..fc241b88 100644 --- a/cl_dll/studio_util.cpp +++ b/cl_dll/studio_util.cpp @@ -254,11 +254,7 @@ AngleQuaternion ==================== */ #if XASH_SIMD_NEON -static const float32x4_t AngleQuaternion_sign2 = - vzipq_f32( - vreinterpretq_f32_u32(vdupq_n_u32(0x80000000)), - vreinterpretq_f32_u32(vdupq_n_u32(0x00000000)) - ).val[0]; // { 0x80000000, 0x00000000, 0x80000000, 0x00000000 }; +static const uint32x4_t AngleQuaternion_sign2 = vzipq_u32(vdupq_n_u32(0x80000000), vdupq_n_u32(0x00000000)).val[0]; // { 0x80000000, 0x00000000, 0x80000000, 0x00000000 }; #endif void AngleQuaternion( float *angles, vec4_t quaternion ) { @@ -411,12 +407,12 @@ QuaternionMatrix ==================== */ #if XASH_SIMD_NEON -const uint32x4_t QuaternionMatrix_sign1 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0x00000000), 0); // { 0x80000000, 0x00000000, 0x00000000, 0x00000000 }; -const uint32x4_t QuaternionMatrix_sign2 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0x00000000), 1); // { 0x00000000, 0x80000000, 0x00000000, 0x00000000 }; -const uint32x4_t QuaternionMatrix_sign3 = vsetq_lane_u32(0x00000000, vdupq_n_u32(0x80000000), 2); // { 0x80000000, 0x80000000, 0x00000000, 0x80000000 }; -const float32x4_t matrix3x4_identity_0 = vsetq_lane_f32(1, vdupq_n_f32(0), 0); // { 1, 0, 0, 0 } -const float32x4_t matrix3x4_identity_1 = vsetq_lane_f32(1, vdupq_n_f32(0), 1); // { 0, 1, 0, 0 } -const float32x4_t matrix3x4_identity_2 = vsetq_lane_f32(1, vdupq_n_f32(0), 2); // { 0, 0, 1, 0 } +static const uint32x4_t QuaternionMatrix_sign1 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0x00000000), 0); // { 0x80000000, 0x00000000, 0x00000000, 0x00000000 }; +static const uint32x4_t QuaternionMatrix_sign2 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0x00000000), 1); // { 0x00000000, 0x80000000, 0x00000000, 0x00000000 }; +static const uint32x4_t QuaternionMatrix_sign3 = vsetq_lane_u32(0x00000000, vdupq_n_u32(0x80000000), 2); // { 0x80000000, 0x80000000, 0x00000000, 0x80000000 }; +static const float32x4_t matrix3x4_identity_0 = vsetq_lane_f32(1, vdupq_n_f32(0), 0); // { 1, 0, 0, 0 } +static const float32x4_t matrix3x4_identity_1 = vsetq_lane_f32(1, vdupq_n_f32(0), 1); // { 0, 1, 0, 0 } +static const float32x4_t matrix3x4_identity_2 = vsetq_lane_f32(1, vdupq_n_f32(0), 2); // { 0, 0, 1, 0 } #endif void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] ) From 43710ea984094aef985c49a4ec30146cec3aeb5e Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 22 Jul 2023 04:45:59 +0300 Subject: [PATCH 04/10] client: studio: NEON vector types all over place here --- cl_dll/studio_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cl_dll/studio_util.cpp b/cl_dll/studio_util.cpp index fc241b88..d1dbeb7f 100644 --- a/cl_dll/studio_util.cpp +++ b/cl_dll/studio_util.cpp @@ -272,7 +272,7 @@ void AngleQuaternion( float *angles, vec4_t quaternion ) float32x4_t sy_cr_cy_sr = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 1); float32x4_t cr_cy_sr_sy = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 2); float32x4_t cy_sr_sy_cr = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 3); - float32x4_t sp_sp_sp_sp_signed = veorq_u32(vreinterpretq_u32_f32(sp_sp_sp_sp), AngleQuaternion_sign2); + float32x4_t sp_sp_sp_sp_signed = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(sp_sp_sp_sp), AngleQuaternion_sign2)); float32x4_t left = vmulq_f32(vmulq_f32(sr_sy_cr_cy, cp_cp_cp_cp), cy_sr_sy_cr); From 6ee8c66c29b2850400a35c3ddca93002442a8842 Mon Sep 17 00:00:00 2001 From: Roman Chistokhodov Date: Mon, 21 Aug 2023 10:11:22 +0300 Subject: [PATCH 05/10] Fix op4mortar option handling and behavior. Fix op4 mortar shell think and touch functions (#384) --- dlls/gearbox/op4mortar.cpp | 685 ++++++++++++++++++++++++------------- 1 file changed, 442 insertions(+), 243 deletions(-) diff --git a/dlls/gearbox/op4mortar.cpp b/dlls/gearbox/op4mortar.cpp index e323d0f6..39ec413e 100644 --- a/dlls/gearbox/op4mortar.cpp +++ b/dlls/gearbox/op4mortar.cpp @@ -7,18 +7,19 @@ #include "monsters.h" #include "player.h" #include "soundent.h" +#include "decals.h" class CMortarShell : public CGrenade { public: void Precache(); - void BurnThink(); - void MortarExplodeTouch(CBaseEntity *pOther); + void EXPORT BurnThink(); + void EXPORT MortarExplodeTouch(CBaseEntity *pOther); void Spawn(); - void FlyThink(); + void EXPORT FlyThink(); int Save(CSave &save); int Restore(CRestore &restore); - static CMortarShell *CreateMortarShell(Vector p_VecOrigin, Vector p_VecAngles, CBaseEntity *pOwner, int velocity); + static CMortarShell *CreateMortarShell(Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, int velocity); static TYPEDESCRIPTION m_SaveData[]; int m_iTrail; @@ -48,114 +49,123 @@ void CMortarShell::Precache() void CMortarShell::Spawn() { Precache(); - SET_MODEL(ENT(pev), "models/mortarshell.mdl"); - UTIL_SetSize(pev, g_vecZero, g_vecZero); - pev->solid = SOLID_BBOX; pev->movetype = MOVETYPE_BOUNCE; + pev->solid = SOLID_BBOX; + + SET_MODEL(edict(), "models/mortarshell.mdl"); + + UTIL_SetSize(pev, g_vecZero, g_vecZero); + UTIL_SetOrigin(pev, pev->origin); pev->classname = MAKE_STRING("mortar_shell"); + SetThink(&CMortarShell::BurnThink); SetTouch(&CMortarShell::MortarExplodeTouch); - pev->dmg = gSkillData.plrDmgRPG*2; - pev->nextthink = gpGlobals->time + 0.1; + UTIL_MakeVectors(pev->angles); + + pev->velocity = -(gpGlobals->v_forward * m_velocity); + pev->gravity = 1; + + pev->dmg = gSkillData.plrDmgRPG * 2; + + pev->nextthink = gpGlobals->time + 0.01; m_flIgniteTime = gpGlobals->time; m_iSoundedOff = FALSE; } void CMortarShell::MortarExplodeTouch(CBaseEntity *pOther) { + pev->enemy = pOther->edict(); + + const Vector direction = pev->velocity.Normalize(); + + const Vector vecSpot = pev->origin - direction * 32; + TraceResult tr; - Vector vecSpot; + UTIL_TraceLine(vecSpot, vecSpot + direction * 64, ignore_monsters, edict(), &tr); - pev->model = iStringNull;//invisible - pev->solid = SOLID_NOT;// intangible + pev->model = 0; + pev->solid = SOLID_NOT; pev->takedamage = DAMAGE_NO; - vecSpot = pev->origin + Vector( 0, 0, 8 ); - UTIL_TraceLine( vecSpot, vecSpot + Vector( 0, 0, -40 ), ignore_monsters, dont_ignore_glass, ENT(pev), &tr ); - - // Pull out of the wall a bit - if( tr.flFraction != 1.0 ) + if (tr.flFraction != 1.0f) { - pev->origin = tr.vecEndPos + ( tr.vecPlaneNormal * ( pev->dmg - 24 ) * 0.6 ); + pev->origin = 0.6f * ((pev->dmg - 24.0f) * tr.vecPlaneNormal) + tr.vecEndPos; } - int iContents = UTIL_PointContents( pev->origin ); + const int contents = UTIL_PointContents(pev->origin); - MESSAGE_BEGIN( MSG_PAS, SVC_TEMPENTITY, pev->origin ); - WRITE_BYTE( TE_EXPLOSION ); // This makes a dynamic light and the explosion sprites/sound - WRITE_COORD( pev->origin.x ); // Send to PAS because of the sound - WRITE_COORD( pev->origin.y ); - WRITE_COORD( pev->origin.z ); - if( iContents != CONTENTS_WATER ) - { - WRITE_SHORT( g_sModelIndexFireball ); - } + MESSAGE_BEGIN(MSG_PAS, SVC_TEMPENTITY, pev->origin); + WRITE_BYTE(TE_EXPLOSION); + WRITE_COORD(pev->origin.x); + WRITE_COORD(pev->origin.y); + WRITE_COORD(pev->origin.z); + + if (contents == CONTENTS_WATER) + WRITE_SHORT(g_sModelIndexWExplosion); else - { - WRITE_SHORT( g_sModelIndexWExplosion ); - } - WRITE_BYTE( (pev->dmg - 50) * 5); // scale * 10 - WRITE_BYTE( 10 ); // framerate - WRITE_BYTE( TE_EXPLFLAG_NONE ); + WRITE_SHORT(g_sModelIndexFireball); + + WRITE_BYTE(static_cast((pev->dmg - 50.0) * 5.0)); + WRITE_BYTE(10); + WRITE_BYTE(TE_EXPLFLAG_NONE); MESSAGE_END(); - CSoundEnt::InsertSound( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 ); - entvars_t *pevOwner; - if( pev->owner ) - pevOwner = VARS( pev->owner ); - else - pevOwner = NULL; + CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, 1024, 3.0); - pev->owner = NULL; // can't traceline attack owner if this is set + entvars_t* pOwner = VARS(pev->owner); + pev->owner = NULL; - RadiusDamage( pev, pevOwner, pev->dmg, CLASS_NONE, DMG_BLAST ); + RadiusDamage(pev, pOwner, pev->dmg, CLASS_NONE, 64); - if( RANDOM_FLOAT( 0, 1 ) < 0.5 ) - { - UTIL_DecalTrace( &tr, 11 ); - } + if (RANDOM_FLOAT(0, 1) >= 0.5) + UTIL_DecalTrace(&tr, DECAL_SCORCH2); else - { - UTIL_DecalTrace( &tr, 12 ); - } + UTIL_DecalTrace(&tr, DECAL_SCORCH1); - switch( RANDOM_LONG( 0, 2 ) ) + switch (RANDOM_LONG(0, 2)) { case 0: - EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris1.wav", 0.55, ATTN_NORM ); + EMIT_SOUND(edict(), CHAN_VOICE, "weapons/debris1.wav", 0.55, ATTN_NORM); break; case 1: - EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris2.wav", 0.55, ATTN_NORM ); + EMIT_SOUND(edict(), CHAN_VOICE, "weapons/debris2.wav", 0.55, ATTN_NORM); break; case 2: - EMIT_SOUND( ENT( pev ), CHAN_VOICE, "weapons/debris3.wav", 0.55, ATTN_NORM ); + EMIT_SOUND(edict(), CHAN_VOICE, "weapons/debris3.wav", 0.55, ATTN_NORM); break; } pev->effects |= EF_NODRAW; - SetThink( &CGrenade::Smoke ); + + SetThink(&CMortarShell::Smoke); + pev->velocity = g_vecZero; + pev->nextthink = gpGlobals->time + 0.3; - if( iContents != CONTENTS_WATER ) + if (contents != CONTENTS_WATER) { - int sparkCount = RANDOM_LONG( 0, 3 ); - for( int i = 0; i < sparkCount; i++ ) - Create( "spark_shower", pev->origin, tr.vecPlaneNormal, NULL ); + const int sparkCount = RANDOM_LONG(0, 3); + + for (int i = 0; i < sparkCount; ++i) + { + CBaseEntity::Create("spark_shower", pev->origin, tr.vecPlaneNormal); + } } } void CMortarShell::BurnThink() { - UTIL_VecToAngles(pev->velocity); - pev->angles = pev->velocity; + pev->angles = UTIL_VecToAngles(pev->velocity); + + pev->angles.x -= 90; MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, pev->origin); - WRITE_BYTE(110); + WRITE_BYTE(TE_SPRITE_SPRAY); WRITE_COORD(pev->origin.x); WRITE_COORD(pev->origin.y); WRITE_COORD(pev->origin.z); @@ -168,8 +178,10 @@ void CMortarShell::BurnThink() WRITE_BYTE(120); MESSAGE_END(); - if(!((m_flIgniteTime + 0.2) >= gpGlobals->time)) + if (gpGlobals->time > m_flIgniteTime + 0.2) + { SetThink(&CMortarShell::FlyThink); + } pev->nextthink = gpGlobals->time + 0.01; } @@ -177,36 +189,35 @@ void CMortarShell::BurnThink() void CMortarShell::FlyThink() { pev->angles = UTIL_VecToAngles(pev->velocity); - pev->angles.x -= 90; + pev->angles.x -= 90.0f; - if(pev->velocity.z < 20 && !m_iSoundedOff) + if(pev->velocity.z < 20.0f && !m_iSoundedOff) { m_iSoundedOff = TRUE; - EMIT_SOUND_DYN(ENT(pev), 2, "weapons/ofmortar.wav", 1, 0, 0, 100); + EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/ofmortar.wav", RANDOM_FLOAT(0.8, 0.9), ATTN_NONE); } pev->nextthink = gpGlobals->time + 0.1; } -CMortarShell *CMortarShell::CreateMortarShell(Vector p_VecOrigin, Vector p_VecAngles, CBaseEntity *pOwner, int velocity) +CMortarShell *CMortarShell::CreateMortarShell(Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, int velocity) { - CMortarShell *rocket = GetClassPtr( (CMortarShell *)NULL ); - rocket->Spawn(); - - rocket->pev->gravity = 1; - UTIL_SetOrigin( rocket->pev, p_VecOrigin ); - rocket->pev->angles = UTIL_VecToAngles(p_VecAngles); - UTIL_MakeVectors(p_VecAngles); - rocket->pev->velocity = rocket->pev->velocity - gpGlobals->v_forward * velocity; - if (pOwner) - rocket->pev->owner = ENT(pOwner->pev); - - return rocket; + CMortarShell *pShell = GetClassPtr( (CMortarShell *)NULL ); + UTIL_SetOrigin(pShell->pev, vecOrigin); + + pShell->pev->angles = vecAngles; + pShell->m_velocity = velocity; + + pShell->Spawn(); + + pShell->pev->owner = pOwner->edict(); + + return pShell; } #define SF_MORTAR_ACTIVE (1 << 0) #define SF_MORTAR_LINE_OF_SIGHT (1 << 4) -#define SF_MORTAR_CAN_CONTROL (1 << 5) +#define SF_MORTAR_CONTROLLABLE (1 << 5) class COp4Mortar : public CBaseMonster { @@ -224,44 +235,56 @@ public: void EXPORT MortarThink(); static TYPEDESCRIPTION m_SaveData[]; int ObjectCaps() { return 0; } + void PlaySound(); - float m_FireDelay; - BOOL m_tracking; - float m_minRange; - float m_maxRange; - float m_lastupdate; - float m_zeroYaw; - float m_lastFire; - float m_trackDelay; - float m_flExplodeTime; - int m_hmax; - int m_hmin; int d_x; int d_y; + float m_lastupdate; + int m_direction; + Vector m_start; + Vector m_end; int m_velocity; + int m_hmin; + int m_hmax; + float m_fireLast; + float m_maxRange; + float m_minRange; int m_iEnemyType; - int m_iUpdateTime; + float m_fireDelay; + float m_trackDelay; + BOOL m_tracking; + float m_zeroYaw; Vector m_vGunAngle; Vector m_vIdealGunVector; Vector m_vIdealGunAngle; + + float m_lastTimePlayedSound; }; LINK_ENTITY_TO_CLASS(op4mortar, COp4Mortar) TYPEDESCRIPTION COp4Mortar::m_SaveData[] = { - DEFINE_FIELD( COp4Mortar, m_tracking, FIELD_BOOLEAN ), - DEFINE_FIELD( COp4Mortar, m_FireDelay, FIELD_FLOAT ), - DEFINE_FIELD( COp4Mortar, m_minRange, FIELD_FLOAT), - DEFINE_FIELD( COp4Mortar, m_maxRange, FIELD_FLOAT ), - DEFINE_FIELD( COp4Mortar, m_lastFire, FIELD_FLOAT), - DEFINE_FIELD( COp4Mortar, m_trackDelay, FIELD_FLOAT ), - DEFINE_FIELD( COp4Mortar, m_hmax, FIELD_INTEGER ), - DEFINE_FIELD( COp4Mortar, m_hmin, FIELD_INTEGER ), - DEFINE_FIELD( COp4Mortar, m_velocity, FIELD_INTEGER ), - DEFINE_FIELD( COp4Mortar, m_iEnemyType, FIELD_INTEGER ), - DEFINE_FIELD( COp4Mortar, m_vGunAngle, FIELD_VECTOR ), + DEFINE_FIELD(COp4Mortar, d_x, FIELD_INTEGER), + DEFINE_FIELD(COp4Mortar, d_y, FIELD_INTEGER), DEFINE_FIELD(COp4Mortar, m_lastupdate, FIELD_FLOAT), + DEFINE_FIELD(COp4Mortar, m_direction, FIELD_INTEGER), + DEFINE_FIELD(COp4Mortar, m_start, FIELD_VECTOR), + DEFINE_FIELD(COp4Mortar, m_end, FIELD_VECTOR), + DEFINE_FIELD(COp4Mortar, m_velocity, FIELD_INTEGER), + DEFINE_FIELD(COp4Mortar, m_hmin, FIELD_INTEGER), + DEFINE_FIELD(COp4Mortar, m_hmax, FIELD_INTEGER), + DEFINE_FIELD(COp4Mortar, m_fireLast, FIELD_FLOAT), + DEFINE_FIELD(COp4Mortar, m_maxRange, FIELD_FLOAT), + DEFINE_FIELD(COp4Mortar, m_minRange, FIELD_FLOAT), + DEFINE_FIELD(COp4Mortar, m_iEnemyType, FIELD_INTEGER), + DEFINE_FIELD(COp4Mortar, m_fireDelay, FIELD_FLOAT), + DEFINE_FIELD(COp4Mortar, m_trackDelay, FIELD_FLOAT), + DEFINE_FIELD(COp4Mortar, m_tracking, FIELD_BOOLEAN), + DEFINE_FIELD(COp4Mortar, m_zeroYaw, FIELD_FLOAT), + DEFINE_FIELD(COp4Mortar, m_vGunAngle, FIELD_VECTOR), + DEFINE_FIELD(COp4Mortar, m_vIdealGunVector, FIELD_VECTOR), + DEFINE_FIELD(COp4Mortar, m_vIdealGunAngle, FIELD_VECTOR), }; IMPLEMENT_SAVERESTORE( COp4Mortar, CBaseMonster ) @@ -277,85 +300,120 @@ void COp4Mortar::Precache() void COp4Mortar::Spawn() { - float angle; - Precache(); + UTIL_SetOrigin(pev, pev->origin); - SET_MODEL(ENT(pev), "models/mortar.mdl"); + SET_MODEL(edict(), "models/mortar.mdl"); + + pev->health = 1; pev->sequence = LookupSequence("idle"); + ResetSequenceInfo(); + pev->frame = 0; pev->framerate = 1; + m_tracking = FALSE; - m_lastupdate = gpGlobals->time + 0.5; - m_vGunAngle = Vector(0,0,0); - m_iUpdateTime = 0; - if(m_FireDelay < 0.5) - m_FireDelay = 5; + if (m_fireDelay < 0.5) + m_fireDelay = 5; - if(m_minRange == 0) + if (m_minRange == 0) m_minRange = 128; - if(m_maxRange == 0) - m_maxRange = 3072; + if (m_maxRange == 0) + m_maxRange = 2048; InitBoneControllers(); - angle = pev->angles.y + 180; - m_zeroYaw = UTIL_AngleMod(angle); - m_hEnemy = NULL; + m_vGunAngle = g_vecZero; - if (pev->spawnflags & SF_MORTAR_ACTIVE) - SetThink(&COp4Mortar::MortarThink); - else - SetThink(NULL); + m_lastupdate = gpGlobals->time; - m_flExplodeTime = gpGlobals->time + 5; + m_zeroYaw = UTIL_AngleMod(pev->angles.y + 180.0); - pev->nextthink = gpGlobals->time + 0.1; + m_fireLast = gpGlobals->time; + m_trackDelay = gpGlobals->time; + + m_hEnemy = NULL; + + pev->nextthink = gpGlobals->time + 0.01; + SetThink(&COp4Mortar::MortarThink); +} + +void COp4Mortar::PlaySound() +{ + if (gpGlobals->time > m_lastTimePlayedSound + 0.12f) + { + EMIT_SOUND(ENT(pev), CHAN_VOICE, "player/pl_grate1.wav", 1.0f, ATTN_NORM); + m_lastTimePlayedSound = gpGlobals->time + 0.12f; + } } void COp4Mortar::UpdatePosition(float direction, int controller) { - if(m_vGunAngle.y > 90) - m_vGunAngle.y = 90; + if (gpGlobals->time - m_lastupdate >= 0.06) + { + switch (controller) + { + case 0: + d_x = 3 * direction; + break; - if(m_vGunAngle.y < -90) - m_vGunAngle.y = -90; + case 1: + d_y = 3 * direction; + break; + } - if(m_vGunAngle.x > 90) - m_vGunAngle.x = 90; + m_vGunAngle.x = d_x + m_vGunAngle.x; + m_vGunAngle.y = d_y + m_vGunAngle.y; - if(m_vGunAngle.x < 0) - m_vGunAngle.x = 0; + if (m_hmin > m_vGunAngle.y) + { + m_vGunAngle.y = m_hmin; + d_y = 0; + } - if(controller == 1) - m_vGunAngle.y += direction/2; - else - m_vGunAngle.x += direction/2; + if (m_vGunAngle.y > m_hmax) + { + m_vGunAngle.y = m_hmax; + d_y = 0; + } - if(m_iUpdateTime >= 15) - { - EMIT_SOUND_DYN(ENT(pev), 2, "player/pl_grate1.wav", 1, 0.8, 0, 100); - m_iUpdateTime = 0; - } + if (m_vGunAngle.x < 10) + { + m_vGunAngle.x = 10; + d_x = 0; + } + else if (m_vGunAngle.x > 90) + { + m_vGunAngle.x = 90; + d_x = 0; + } - SetBoneController(1, m_vGunAngle.y); - SetBoneController(0, m_vGunAngle.x); + if (0 != d_x || 0 != d_y) + { + PlaySound(); + } + + SetBoneController(0, m_vGunAngle.x); + SetBoneController(1, m_vGunAngle.y); - m_lastupdate = gpGlobals->time + 0.1; - m_iUpdateTime++; + d_x = 0; + d_y = 0; + + m_lastupdate = gpGlobals->time; + } } void COp4Mortar::MortarThink() { - Vector pos, angle, vecTarget; + const float flInterval = StudioFrameAdvance(); - if(m_fSequenceFinished) + if (m_fSequenceFinished) { - if(pev->sequence != LookupSequence("idle")) + if (pev->sequence != LookupSequence("idle")) { pev->frame = 0; pev->sequence = LookupSequence("idle"); @@ -363,55 +421,75 @@ void COp4Mortar::MortarThink() } } - DispatchAnimEvents(); - StudioFrameAdvance(); + DispatchAnimEvents(flInterval); + + //GlowShellUpdate(); pev->nextthink = gpGlobals->time + 0.1; - if(pev->spawnflags & SF_MORTAR_ACTIVE) + if ((pev->spawnflags & SF_MORTAR_ACTIVE) != 0) { - if(m_hEnemy == 0 || !m_hEnemy->IsAlive()) + if (!m_hEnemy) { m_hEnemy = FindTarget(); } - } - if(m_hEnemy != 0) - { - vecTarget = Vector( m_hEnemy->pev->origin.x, m_hEnemy->pev->origin.y, m_hEnemy->pev->absmax.z); + CBaseEntity* pEnemy = m_hEnemy; - if((pev->origin - m_hEnemy->pev->origin).Length() <= m_maxRange) + if (pEnemy) { - GetAttachment(0, pos, angle); + const float distance = (pEnemy->pev->origin - pev->origin).Length(); - m_vIdealGunVector = VecCheckThrow(pev, pos, vecTarget, 700, 1); - m_vIdealGunVector.x =- m_vIdealGunVector.x; - m_vIdealGunVector.y =- m_vIdealGunVector.y; + if (pEnemy->IsAlive() && m_minRange <= distance && distance <= m_maxRange) + { + if (gpGlobals->time - m_trackDelay > 0.5) + { + Vector vecPos, vecAngle; + GetAttachment(0, vecPos, vecAngle); - m_vIdealGunAngle = UTIL_VecToAngles(m_vIdealGunVector); + m_vIdealGunVector = VecCheckThrow(pev, vecPos, pEnemy->pev->origin, m_velocity / 2); - m_trackDelay = gpGlobals->time; - } - AIUpdatePosition(); - } + m_vIdealGunAngle = UTIL_VecToAngles(m_vIdealGunVector); - if(m_hEnemy != 0 && gpGlobals->time - m_lastFire > 5 && (m_hEnemy->pev->origin - pev->origin).Length() > 710) - { - EMIT_SOUND_DYN(ENT(pev), 2, "weapons/mortarhit.wav", 1, 0.8, 0, 100); - UTIL_ScreenShake(pev->origin, 12, 100, 2, 1000); + m_trackDelay = gpGlobals->time; + } - float speed = m_vIdealGunVector.Length(); + AIUpdatePosition(); - angle = m_vIdealGunAngle; + const float idealDistance = m_vIdealGunVector.Length(); - if(speed > 0) - { - if(CMortarShell::CreateMortarShell(pev->origin, angle, this, floor(speed))) + if (idealDistance > 1.0) + { + if (gpGlobals->time - m_fireLast > m_fireDelay) + { + EMIT_SOUND(edict(), CHAN_VOICE, "weapons/mortarhit.wav", VOL_NORM, ATTN_NORM); + UTIL_ScreenShake(pev->origin, 12.0, 100.0, 2.0, 1000.0); + + Vector vecPos, vecAngle; + GetAttachment(0, vecPos, vecAngle); + + vecAngle = m_vGunAngle; + + vecAngle.y = UTIL_AngleMod(pev->angles.y + m_vGunAngle.y); + + if (CMortarShell::CreateMortarShell(vecPos, vecAngle, this, idealDistance)) + { + pev->sequence = LookupSequence("fire"); + pev->frame = 0; + ResetSequenceInfo(); + } + + m_fireLast = gpGlobals->time; + } + } + else + { + m_fireLast = gpGlobals->time; + } + } + else { - pev->frame = 0; - pev->sequence = LookupSequence("fire"); - ResetSequenceInfo(); - m_lastFire = gpGlobals->time; + m_hEnemy = NULL; } } } @@ -419,32 +497,102 @@ void COp4Mortar::MortarThink() CBaseEntity *COp4Mortar::FindTarget() { - CBaseEntity *pPlayer; - Vector BarretEnd; - Vector BarretAngle; - Vector targetPosition; - TraceResult tr; - CBaseEntity *pIdealTarget = NULL; + CBaseEntity* pPlayerTarget = UTIL_FindEntityByClassname(NULL, "player"); + + if (!pPlayerTarget) + return pPlayerTarget; + + m_pLink = NULL; + + CBaseEntity* pIdealTarget = NULL; + float flIdealDist = m_maxRange; + + Vector barrelEnd, barrelAngle; + GetAttachment(0, barrelEnd, barrelAngle); + + if (pPlayerTarget->IsAlive()) + { + const float distance = (pPlayerTarget->pev->origin - pev->origin).Length(); + + if (distance >= m_minRange && m_maxRange >= distance) + { + TraceResult tr; + UTIL_TraceLine(barrelEnd, pPlayerTarget->pev->origin + pPlayerTarget->pev->view_ofs, dont_ignore_monsters, edict(), &tr); + + if ((pev->spawnflags & SF_MORTAR_LINE_OF_SIGHT) == 0 || tr.pHit == pPlayerTarget->pev->pContainingEntity) + { + if (0 == m_iEnemyType) + return pPlayerTarget; + + flIdealDist = distance; + pIdealTarget = pPlayerTarget; + } + } + } + + const Vector maxRange(m_maxRange, m_maxRange, m_maxRange); + + CBaseEntity* pList[100]; + const int count = UTIL_EntitiesInBox(pList, ARRAYSIZE(pList), pev->origin - maxRange, pev->origin + maxRange, FL_MONSTER | FL_CLIENT); + + for (int i = 0; i < count; ++i) + { + CBaseEntity* pEntity = pList[i]; + + if (this == pEntity) + continue; + + if ((pEntity->pev->spawnflags & SF_MONSTER_PRISONER) != 0) + continue; + + if (pEntity->pev->health <= 0) + continue; - if((pPlayer = UTIL_FindEntityByClassname(0, "player")) == NULL ) - return NULL; + CBaseMonster* pMonster = pEntity->MyMonsterPointer(); - m_pLink = 0; + if (!pMonster) + continue; - GetAttachment(0, BarretEnd, BarretAngle); + if (pMonster->IRelationship(pPlayerTarget) != R_AL) + continue; - float dist = (pPlayer->pev->origin - pev->origin).Length(); + if ((pEntity->pev->flags & FL_NOTARGET) != 0) + continue; - if(pPlayer->IsAlive()) + if (!FVisible(pEntity)) + continue; + + if (pEntity->IsPlayer() && (pev->spawnflags & SF_MORTAR_ACTIVE) != 0) + { + if (pMonster->FInViewCone(this)) + { + pev->spawnflags &= ~SF_MORTAR_ACTIVE; + } + } + } + + for (CBaseEntity* pEntity = m_pLink; pEntity; pEntity = pEntity->m_pLink) { - if(m_maxRange >= dist) + const float distance = (pEntity->pev->origin - pev->origin).Length(); + + if (distance >= m_minRange && m_maxRange >= distance && (!pIdealTarget || flIdealDist > distance)) { - targetPosition = pPlayer->pev->origin + pev->view_ofs; - UTIL_TraceLine(BarretEnd, targetPosition, ignore_monsters, dont_ignore_glass, ENT(pev), &tr); + TraceResult tr; + UTIL_TraceLine(barrelEnd, pEntity->pev->origin + pEntity->pev->view_ofs, dont_ignore_monsters, edict(), &tr); - if((!(pev->spawnflags & SF_MORTAR_LINE_OF_SIGHT) || tr.pHit == ENT(pPlayer->pev)) && !m_iEnemyType) + if ((pev->spawnflags & SF_MORTAR_LINE_OF_SIGHT) != 0) + { + if (tr.pHit == pEntity->edict()) + { + flIdealDist = distance; + } + if (tr.pHit == pEntity->edict()) + pIdealTarget = pEntity; + } + else { - pIdealTarget = pPlayer; + flIdealDist = distance; + pIdealTarget = pEntity; } } } @@ -459,40 +607,40 @@ int COp4Mortar::TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, floa void COp4Mortar::KeyValue(KeyValueData *pvkd) { - if(strcmp(pvkd->szKeyName, "m_hmax")) + if(FStrEq(pvkd->szKeyName, "h_max")) { m_hmax = atoi(pvkd->szValue); - pvkd->fHandled = 1; + pvkd->fHandled = TRUE; } - else if(strcmp(pvkd->szKeyName, "m_hmin")) + else if(FStrEq(pvkd->szKeyName, "h_min")) { m_hmin = atoi(pvkd->szValue); - pvkd->fHandled = 1; + pvkd->fHandled = TRUE; } - else if(strcmp(pvkd->szKeyName, "mortar_velocity")) + else if(FStrEq(pvkd->szKeyName, "mortar_velocity")) { m_velocity = atoi(pvkd->szValue); - pvkd->fHandled = 1; + pvkd->fHandled = TRUE; } - else if(strcmp(pvkd->szKeyName, "mindist")) + else if(FStrEq(pvkd->szKeyName, "mindist")) { m_minRange = atoi(pvkd->szValue); - pvkd->fHandled = 1; + pvkd->fHandled = TRUE; } - else if(strcmp(pvkd->szKeyName, "maxdist")) + else if(FStrEq(pvkd->szKeyName, "maxdist")) { m_maxRange = atoi(pvkd->szValue); - pvkd->fHandled = 1; + pvkd->fHandled = TRUE; } - else if(strcmp(pvkd->szKeyName, "enemytype")) + else if(FStrEq(pvkd->szKeyName, "enemytype")) { m_iEnemyType = atoi(pvkd->szValue); - pvkd->fHandled = 1; + pvkd->fHandled = TRUE; } - else if(strcmp(pvkd->szKeyName, "firedelay")) + else if(FStrEq(pvkd->szKeyName, "firedelay")) { - m_FireDelay = atoi(pvkd->szValue); - pvkd->fHandled = 1; + m_fireDelay = atoi(pvkd->szValue); + pvkd->fHandled = TRUE; } else { @@ -502,58 +650,109 @@ void COp4Mortar::KeyValue(KeyValueData *pvkd) void COp4Mortar::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) { - SetThink(NULL); - - if((pev->spawnflags & SF_MORTAR_CAN_CONTROL) && (pActivator->pev->origin - pev->origin).Length() < 170) + if (useType == USE_TOGGLE && (!pActivator || pActivator->IsPlayer())) { - EMIT_SOUND_DYN(ENT(pev), 2, "weapons/mortarhit.wav", 1, 0, 0, 100); - UTIL_ScreenShake(pev->origin, 12, 100, 2, 1000); + if ((pev->spawnflags & SF_MORTAR_ACTIVE) == 0 && (pev->spawnflags & SF_MORTAR_CONTROLLABLE) != 0) + { + //Player fired a mortar + EMIT_SOUND(edict(), CHAN_VOICE, "weapons/mortarhit.wav", VOL_NORM, ATTN_NONE); + UTIL_ScreenShake(pev->origin, 12.0, 100.0, 2.0, 1000.0); - Vector pos, angle; - GetAttachment(0, pos, angle); - angle = m_vGunAngle; - float anglemod = pev->angles.y + m_vGunAngle.y; + Vector pos, angle; + GetAttachment(0, pos, angle); - angle.y = UTIL_AngleMod(anglemod); + angle = m_vGunAngle; - if((CMortarShell::CreateMortarShell(pos, angle, this, 2000 - (m_vGunAngle.x * 12.25))) != NULL) - { - pev->frame = 0; - pev->sequence = LookupSequence("fire"); - ResetSequenceInfo(); + angle.y = UTIL_AngleMod(pev->angles.y + m_vGunAngle.y); + + if (CMortarShell::CreateMortarShell(pos, angle, pActivator ? pActivator : this, m_velocity)) + { + pev->sequence = LookupSequence("fire"); + pev->frame = 0; + ResetSequenceInfo(); + } + return; } } + //Toggle AI active state + if (ShouldToggle(useType, (pev->spawnflags & SF_MORTAR_ACTIVE) != 0)) + { + pev->spawnflags ^= SF_MORTAR_ACTIVE; + + m_fireLast = 0; + m_hEnemy = NULL; + } } void COp4Mortar::AIUpdatePosition() { - if(m_hEnemy != 0 && (m_hEnemy->pev->origin - pev->origin).Length() < 710) - return; + if (fabs(m_vGunAngle.x - m_vIdealGunAngle.x) >= 3.0) + { + const float angle = UTIL_AngleDiff(m_vGunAngle.x, m_vIdealGunAngle.x); + + if (angle != 0) + { + const float absolute = fabs(angle); + if (absolute <= 3.0) + d_x = static_cast(-absolute); + else + d_x = angle > 0 ? -3 : 3; + } + } - if(m_vIdealGunAngle.x == 270 && m_vIdealGunAngle.y == 0) + const float yawAngle = UTIL_AngleMod(m_zeroYaw + m_vGunAngle.y); + + if (fabs(yawAngle - m_vIdealGunAngle.y) >= 3.0) { - m_vIdealGunAngle.x = 0; - m_vIdealGunAngle.y = 0; + const float angle = UTIL_AngleDiff(yawAngle, m_vIdealGunAngle.y); + + if (angle != 0) + { + const float absolute = fabs(angle); + if (absolute <= 3.0) + d_y = static_cast(-absolute); + else + d_y = angle > 0 ? -3 : 3; + } } - if(m_vIdealGunAngle.x <= 0) - m_vIdealGunAngle.x = 0; + m_vGunAngle.x += d_x; + m_vGunAngle.y += d_y; - if(m_vIdealGunAngle.x > 90) - m_vIdealGunAngle.x = 90; + if (m_hmin > m_vGunAngle.y) + { + m_vGunAngle.y = m_hmin; + d_y = 0; + } - if(m_vIdealGunAngle.y > 165 && m_vIdealGunAngle.y < 270) - m_vIdealGunAngle.y = -90; + if (m_vGunAngle.y > m_hmax) + { + m_vGunAngle.y = m_hmax; + d_y = 0; + } - else if(m_vIdealGunAngle.y > 90 && m_vIdealGunAngle.y < 165) - m_vIdealGunAngle.y = 90; + if (m_vGunAngle.x < 10.0) + { + m_vGunAngle.x = 10.0; + d_x = 0; + } + else if (m_vGunAngle.x > 90.0) + { + m_vGunAngle.x = 90.0; + d_x = 0; + } + if (0 != d_x || 0 != d_y) + { + PlaySound(); + } - SetBoneController(0, m_vIdealGunAngle.x); - SetBoneController(1, m_vIdealGunAngle.y); + SetBoneController(0, m_vGunAngle.x); + SetBoneController(1, m_vGunAngle.y); - m_vGunAngle = m_vIdealGunAngle; + d_y = 0; + d_x = 0; } //======================================================== @@ -571,9 +770,9 @@ public: int ObjectCaps() { return FCAP_CONTINUOUS_USE; } static TYPEDESCRIPTION m_SaveData[]; - float m_direction; - float m_lastpush; + int m_direction; int m_controller; + float m_lastpush; }; LINK_ENTITY_TO_CLASS(func_op4mortarcontroller, COp4MortarController) @@ -620,7 +819,7 @@ void COp4MortarController::KeyValue(KeyValueData *pvkd) if(FStrEq(pvkd->szKeyName, "mortar_axis")) { m_controller = atoi(pvkd->szValue); - pvkd->fHandled = 1; + pvkd->fHandled = TRUE; } else CBaseToggle::KeyValue(pvkd); From 2b031dd5857ca3e14b7ccbd7167b626c057cd79e Mon Sep 17 00:00:00 2001 From: Roman Chistokhodov Date: Tue, 29 Aug 2023 19:00:23 +0300 Subject: [PATCH 06/10] Revert fixing bigmomma wait on info_bigmomma (It affects gameplay) (#385) --- dlls/bigmomma.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/bigmomma.cpp b/dlls/bigmomma.cpp index 62188740..d668f5bd 100644 --- a/dlls/bigmomma.cpp +++ b/dlls/bigmomma.cpp @@ -931,7 +931,7 @@ void CBigMomma::StartTask( Task_t *pTask ) TaskComplete(); break; case TASK_WAIT_NODE: - m_flWaitFinished = gpGlobals->time + GetNodeDelay(); + m_flWait = gpGlobals->time + GetNodeDelay(); if( m_hTargetEnt->pev->spawnflags & SF_INFOBM_WAIT ) ALERT( at_aiconsole, "BM: Wait at node %s forever\n", STRING( pev->netname ) ); else From 26d4fac2aa63f3b4a61599e1d4cd1a875eebb329 Mon Sep 17 00:00:00 2001 From: Roman Chistokhodov Date: Sun, 3 Sep 2023 15:54:48 +0300 Subject: [PATCH 07/10] Respect hud_saytext cvar. Remove redundant print to console (#387) --- cl_dll/saytext.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cl_dll/saytext.cpp b/cl_dll/saytext.cpp index 35d08bec..8a4bd1aa 100644 --- a/cl_dll/saytext.cpp +++ b/cl_dll/saytext.cpp @@ -100,10 +100,11 @@ int CHudSayText::Draw( float flTime ) int y = Y_START; #if USE_VGUI - if( ( gViewPort && gViewPort->AllowedToPrintText() == FALSE ) || !m_HUD_saytext->value ) + if( ( gViewPort && gViewPort->AllowedToPrintText() == FALSE ) ) return 1; #endif - + if ( !m_HUD_saytext->value ) + return 1; // make sure the scrolltime is within reasonable bounds, to guard against the clock being reset flScrollTime = Q_min( flScrollTime, flTime + m_HUD_saytext_time->value ); @@ -173,8 +174,6 @@ void CHudSayText::SayTextPrint( const char *pszBuf, int iBufSize, int clientInde ConsolePrint( pszBuf ); return; } -#else - ConsolePrint( pszBuf ); #endif int i; From a7755b3196345271dc76f9c9e78509637d1957e1 Mon Sep 17 00:00:00 2001 From: Roman Chistokhodov Date: Thu, 7 Sep 2023 17:55:21 +0300 Subject: [PATCH 08/10] Fix the upper rope segment sometimes incorrectly aligned. Tidy up the rope code a bit (#388) --- dlls/gearbox/ropes.cpp | 234 +++++++++++++++++++++-------------------- dlls/player.cpp | 2 + dlls/player.h | 2 +- 3 files changed, 122 insertions(+), 116 deletions(-) diff --git a/dlls/gearbox/ropes.cpp b/dlls/gearbox/ropes.cpp index 7e45431e..2132db36 100644 --- a/dlls/gearbox/ropes.cpp +++ b/dlls/gearbox/ropes.cpp @@ -31,16 +31,6 @@ #define SPRING_DAMPING 0.1f #define ROPE_IGNORE_SAMPLES 4 // integrator may be hanging if less than -//#define SetAbsOrigin(x) pev->origin = x; -#define SetAbsAngles(x) pev->angles = x; -#define SetAbsVelociy(x) pev->velocity = x; -#define SetNextThink(x) pev->nextthink = x; -#define SetEffects(x) pev->effects = x; -#define SetSolidType(x) pev->solid = x; -#define AddFlags(x) pev->flags |= x; -#define SetMoveType(x) pev->movetype = x; -#define AddEffectsFlags(x) pev->effects |= x; - /** * Data for a single rope joint. */ @@ -74,17 +64,22 @@ public: static CRopeSample* CreateSample(); - RopeSampleData* GetData() { + RopeSampleData& GetData() + { + return data; + } + + RopeSampleData& GetSourceData() { if (swapped) - return &data2; + return data2; else - return &data; + return data; } - RopeSampleData* GetData2() { + RopeSampleData& GetTargetData() { if (swapped) - return &data; + return data; else - return &data2; + return data2; } void Swap() @@ -92,6 +87,11 @@ public: swapped = !swapped; } + void ResetSwap() + { + swapped = FALSE; + } + private: RopeSampleData data; RopeSampleData data2; @@ -257,7 +257,7 @@ void CRope::Activate() void CRope::InitRope() { - AddFlags( FL_ALWAYSTHINK ); + pev->flags |= FL_ALWAYSTHINK; for( int uiSample = 0; uiSample < m_NumSamples; ++uiSample ) { @@ -334,7 +334,7 @@ void CRope::InitRope() InitializeRopeSim(); SetThink(&CRope::RopeThink); - SetNextThink( gpGlobals->time + 0.01 ); + pev->nextthink = gpGlobals->time + 0.01; } void CRope::RopeThink() @@ -364,7 +364,7 @@ void CRope::RopeThink() Creak(); } - SetNextThink( gpGlobals->time + 0.001 ); + pev->nextthink = gpGlobals->time + 0.001; } void CRope::InitializeRopeSim() @@ -376,26 +376,26 @@ void CRope::InitializeRopeSim() CRopeSegment* pSegment = seg[ uiSeg ]; CRopeSample* pSample = pSegment->GetSample(); - RopeSampleData *data = pSample->GetData(); + RopeSampleData& data = pSample->GetData(); - data->mPosition = pSegment->pev->origin; + data.mPosition = pSegment->pev->origin; - data->mVelocity = g_vecZero; - data->mForce = g_vecZero; - data->mMassReciprocal = 1; - data->mApplyExternalForce = false; - data->mExternalForce = g_vecZero; + data.mVelocity = g_vecZero; + data.mForce = g_vecZero; + data.mMassReciprocal = 1; + data.mApplyExternalForce = false; + data.mExternalForce = g_vecZero; Vector vecOrigin, vecAngles; pSegment->GetAttachment( 0, vecOrigin, vecAngles ); - data->restLength = ( pSegment->pev->origin - vecOrigin ).Length(); + data.restLength = ( pSegment->pev->origin - vecOrigin ).Length(); } { //Zero out the anchored segment's mass so it stays in place. CRopeSample *pSample = m_Samples[ 0 ]; - pSample->GetData()->mMassReciprocal = 0; + pSample->GetData().mMassReciprocal = 0; } CRopeSegment* pSegment = seg[ m_iSegments - 1 ]; @@ -414,19 +414,19 @@ void CRope::InitializeRopeSim() CRopeSample* pSample = m_Samples[ m_NumSamples - 1 ]; - RopeSampleData *data = pSample->GetData(); + RopeSampleData& data = pSample->GetData(); - data->mPosition = vecOrigin; + data.mPosition = vecOrigin; m_LastEndPos = vecOrigin; - data->mVelocity = g_vecZero; + data.mVelocity = g_vecZero; - data->mForce = g_vecZero; + data.mForce = g_vecZero; - data->mMassReciprocal = 0.2; + data.mMassReciprocal = 0.2; - data->mApplyExternalForce = false; + data.mApplyExternalForce = false; int uiNumSegs = ROPE_IGNORE_SAMPLES; @@ -453,6 +453,7 @@ void CRope::RunSimOnSamples() int uiIndex = 0; + bool swapped = false; while( true ) { ++uiIndex; @@ -472,13 +473,15 @@ void CRope::RunSimOnSamples() { m_Samples[i]->Swap(); } + swapped = !swapped; + } - //CRopeSample **swap = ppSampleSource; - //ppSampleSource = ppSampleTarget; - //ppSampleTarget = swap; - - //std::swap( ppSampleSource, ppSampleTarget ); - + if (swapped) + { + for (int i=0; iResetSwap(); + } } mLastTime = gpGlobals->time; @@ -503,12 +506,12 @@ void CRope::ComputeForces( CRopeSample** ppSystem ) int uiIndex; for( uiIndex = 0; uiIndex < m_NumSamples; ++uiIndex ) { - ComputeSampleForce( *ppSystem[ uiIndex ]->GetData() ); + ComputeSampleForce( ppSystem[ uiIndex ]->GetSourceData() ); } for( uiIndex = 0; uiIndex < m_iSegments; ++uiIndex ) { - ComputeSpringForce( *ppSystem[ uiIndex ]->GetData(), *ppSystem[ uiIndex+1 ]->GetData() ); + ComputeSpringForce( ppSystem[ uiIndex ]->GetSourceData(), ppSystem[ uiIndex+1 ]->GetSourceData() ); } } @@ -576,16 +579,16 @@ void CRope::RK4Integrate( const float flDeltaTime ) for( int uiIndex = 0; uiIndex < m_NumSamples; ++uiIndex, ++pTemp1, ++pTemp2 ) { - RopeSampleData *data = m_Samples[ uiIndex ]->GetData(); + RopeSampleData& data = m_Samples[ uiIndex ]->GetSourceData(); - pTemp2->mForce = data->mMassReciprocal * data->mForce * flDeltas[ 0 ]; - pTemp2->mVelocity = data->mVelocity * flDeltas[ 0 ]; - pTemp2->restLength = data->restLength; + pTemp2->mForce = data.mMassReciprocal * data.mForce * flDeltas[ 0 ]; + pTemp2->mVelocity = data.mVelocity * flDeltas[ 0 ]; + pTemp2->restLength = data.restLength; - pTemp1->mMassReciprocal = data->mMassReciprocal; - pTemp1->mVelocity = data->mVelocity + pTemp2->mForce; - pTemp1->mPosition = data->mPosition + pTemp2->mVelocity; - pTemp1->restLength = data->restLength; + pTemp1->mMassReciprocal = data.mMassReciprocal; + pTemp1->mVelocity = data.mVelocity + pTemp2->mForce; + pTemp1->mPosition = data.mPosition + pTemp2->mVelocity; + pTemp1->restLength = data.restLength; } ComputeForces( g_pTempList[ 0 ] ); @@ -598,16 +601,16 @@ void CRope::RK4Integrate( const float flDeltaTime ) for( int uiIndex = 0; uiIndex < m_NumSamples; ++uiIndex, ++pTemp1, ++pTemp2 ) { - RopeSampleData *data = m_Samples[ uiIndex ]->GetData(); + RopeSampleData& data = m_Samples[ uiIndex ]->GetSourceData(); - pTemp2->mForce = data->mMassReciprocal * pTemp1->mForce * flDeltas[ uiStep - 1 ]; + pTemp2->mForce = data.mMassReciprocal * pTemp1->mForce * flDeltas[ uiStep - 1 ]; pTemp2->mVelocity = pTemp1->mVelocity * flDeltas[ uiStep - 1 ]; - pTemp2->restLength = data->restLength; + pTemp2->restLength = data.restLength; - pTemp1->mMassReciprocal = data->mMassReciprocal; - pTemp1->mVelocity = data->mVelocity + pTemp2->mForce; - pTemp1->mPosition = data->mPosition + pTemp2->mVelocity; - pTemp1->restLength = data->restLength; + pTemp1->mMassReciprocal = data.mMassReciprocal; + pTemp1->mVelocity = data.mVelocity + pTemp2->mForce; + pTemp1->mPosition = data.mPosition + pTemp2->mVelocity; + pTemp1->restLength = data.restLength; } ComputeForces( g_pTempList[ 0 ] ); @@ -619,9 +622,9 @@ void CRope::RK4Integrate( const float flDeltaTime ) for( int uiIndex = 0; uiIndex < m_NumSamples; ++uiIndex, ++pTemp1, ++pTemp2 ) { - RopeSampleData *data = m_Samples[ uiIndex ]->GetData(); + RopeSampleData& data = m_Samples[ uiIndex ]->GetSourceData(); - pTemp2->mForce = data->mMassReciprocal * pTemp1->mForce * flDeltas[ 3 ]; + pTemp2->mForce = data.mMassReciprocal * pTemp1->mForce * flDeltas[ 3 ]; pTemp2->mVelocity = pTemp1->mVelocity * flDeltas[ 3 ]; } @@ -634,16 +637,16 @@ void CRope::RK4Integrate( const float flDeltaTime ) for( int uiIndex = 0; uiIndex < m_NumSamples; ++uiIndex, ++pTemp1, ++pTemp2, ++pTemp3, ++pTemp4 ) { - RopeSampleData *pSource = m_Samples[ uiIndex ]->GetData(); - RopeSampleData *pTarget = m_Samples[ uiIndex ]->GetData2(); + RopeSampleData& pSource = m_Samples[ uiIndex ]->GetSourceData(); + RopeSampleData& pTarget = m_Samples[ uiIndex ]->GetTargetData(); const Vector vecPosChange = 1.0f / 6.0f * ( pTemp1->mVelocity + ( pTemp2->mVelocity + pTemp3->mVelocity ) * 2 + pTemp4->mVelocity ); const Vector vecVelChange = 1.0f / 6.0f * ( pTemp1->mForce + ( pTemp2->mForce + pTemp3->mForce ) * 2 + pTemp4->mForce ); - pTarget->mPosition = pSource->mPosition + ( vecPosChange );//* flDeltaTime ); + pTarget.mPosition = pSource.mPosition + ( vecPosChange );//* flDeltaTime ); - pTarget->mVelocity = pSource->mVelocity + ( vecVelChange );//* flDeltaTime ); + pTarget.mVelocity = pSource.mVelocity + ( vecVelChange );//* flDeltaTime ); } } @@ -686,30 +689,31 @@ void CRope::TraceModels( CRopeSegment** ppPrimarySegs, CRopeSegment** ppHiddenSe Vector vecAngles; GetAlignmentAngles( - m_Samples[ 0 ]->GetData()->mPosition, - m_Samples[ 1 ]->GetData()->mPosition, + m_Samples[ 0 ]->GetData().mPosition, + m_Samples[ 1 ]->GetData().mPosition, vecAngles ); - ( *ppPrimarySegs )->SetAbsAngles( vecAngles ); + ( *ppPrimarySegs )->pev->angles = vecAngles; } TraceResult tr; if( mObjectAttached ) { - for( int uiSeg = 1; uiSeg < m_iSegments; ++uiSeg ) + for( unsigned int uiSeg = 1; uiSeg < m_iSegments; ++uiSeg ) { CRopeSample* pSample = m_Samples[ uiSeg ]; - Vector vecDist = pSample->GetData()->mPosition - ppHiddenSegs[ uiSeg ]->pev->origin; + Vector vecDist = pSample->GetData().mPosition - ppHiddenSegs[ uiSeg ]->pev->origin; vecDist = vecDist.Normalize(); + // HACK: this code relies on integer underflow. uiSeg must be unsigned! const float flTraceDist = ( uiSeg - mAttachedObjectsSegment + 2 ) < 5 ? 50 : 10; const Vector vecTraceDist = vecDist * flTraceDist; - const Vector vecEnd = pSample->GetData()->mPosition + vecTraceDist; + const Vector vecEnd = pSample->GetData().mPosition + vecTraceDist; UTIL_TraceLine( ppHiddenSegs[ uiSeg ]->pev->origin, vecEnd, ignore_monsters, edict(), &tr ); @@ -728,17 +732,17 @@ void CRope::TraceModels( CRopeSegment** ppPrimarySegs, CRopeSegment** ppHiddenSe Vector vecNormal = tr.vecPlaneNormal.Normalize() * 20000.0; - RopeSampleData *data = ppPrimarySegs[ uiSeg ]->GetSample()->GetData(); + RopeSampleData& data = ppPrimarySegs[ uiSeg ]->GetSample()->GetData(); - data->mApplyExternalForce = true; + data.mApplyExternalForce = true; - data->mExternalForce = vecNormal; + data.mExternalForce = vecNormal; - data->mVelocity = g_vecZero; + data.mVelocity = g_vecZero; } else { - Vector vecOrigin = pSample->GetData()->mPosition; + Vector vecOrigin = pSample->GetData().mPosition; TruncateEpsilon( vecOrigin ); @@ -748,16 +752,16 @@ void CRope::TraceModels( CRopeSegment** ppPrimarySegs, CRopeSegment** ppHiddenSe } else { - for( int uiSeg = 1; uiSeg < m_iSegments; ++uiSeg ) + for( unsigned int uiSeg = 1; uiSeg < m_iSegments; ++uiSeg ) { UTIL_TraceLine( ppHiddenSegs[ uiSeg ]->pev->origin, - m_Samples[ uiSeg ]->GetData()->mPosition, + m_Samples[ uiSeg ]->GetData().mPosition, ignore_monsters, edict(), &tr ); if( tr.flFraction == 1.0 ) { - Vector vecOrigin = m_Samples[ uiSeg ]->GetData()->mPosition; + Vector vecOrigin = m_Samples[ uiSeg ]->GetData().mPosition; TruncateEpsilon( vecOrigin ); @@ -774,9 +778,9 @@ void CRope::TraceModels( CRopeSegment** ppPrimarySegs, CRopeSegment** ppHiddenSe ppPrimarySegs[ uiSeg ]->SetAbsOrigin( vecOrigin ); - ppPrimarySegs[ uiSeg ]->GetSample()->GetData()->mApplyExternalForce = true; + ppPrimarySegs[ uiSeg ]->GetSample()->GetData().mApplyExternalForce = true; - ppPrimarySegs[ uiSeg ]->GetSample()->GetData()->mExternalForce = vecNormal * 40000.0; + ppPrimarySegs[ uiSeg ]->GetSample()->GetData().mExternalForce = vecNormal * 40000.0; } } } @@ -790,26 +794,26 @@ void CRope::TraceModels( CRopeSegment** ppPrimarySegs, CRopeSegment** ppHiddenSe GetAlignmentAngles( pSegment->pev->origin, pSegment2->pev->origin, vecAngles ); - pSegment->SetAbsAngles( vecAngles ); + pSegment->pev->angles = vecAngles; } if( m_iSegments > 1 ) { CRopeSample *pSample = m_Samples[ m_NumSamples - 1 ]; - UTIL_TraceLine( m_LastEndPos, pSample->GetData()->mPosition, ignore_monsters, edict(), &tr ); + UTIL_TraceLine( m_LastEndPos, pSample->GetData().mPosition, ignore_monsters, edict(), &tr ); if( tr.flFraction == 1.0 ) { - m_LastEndPos = pSample->GetData()->mPosition; + m_LastEndPos = pSample->GetData().mPosition; } else { m_LastEndPos = tr.vecEndPos; - pSample->GetData()->mApplyExternalForce = true; + pSample->GetData().mApplyExternalForce = true; - pSample->GetData()->mExternalForce = tr.vecPlaneNormal.Normalize() * 40000.0; + pSample->GetData().mExternalForce = tr.vecPlaneNormal.Normalize() * 40000.0; } CRopeSegment *pSegment = ppPrimarySegs[ m_NumSamples - 2 ]; @@ -818,7 +822,7 @@ void CRope::TraceModels( CRopeSegment** ppPrimarySegs, CRopeSegment** ppHiddenSe GetAlignmentAngles( pSegment->pev->origin, m_LastEndPos, vecAngles ); - pSegment->SetAbsAngles( vecAngles ); + pSegment->pev->angles = vecAngles; } } @@ -829,22 +833,22 @@ void CRope::SetRopeSegments( const int uiNumSegments, { TraceModels( ppPrimarySegs, ppHiddenSegs ); - ppPrimarySegs[ 0 ]->SetSolidType( SOLID_TRIGGER ); - ppPrimarySegs[ 0 ]->SetEffects( 0 ); + ppPrimarySegs[ 0 ]->pev->solid = SOLID_TRIGGER; + ppPrimarySegs[ 0 ]->pev->effects = 0; - ppHiddenSegs[ 0 ]->SetSolidType( SOLID_NOT ); - ppHiddenSegs[ 0 ]->SetEffects( EF_NODRAW ); + ppHiddenSegs[ 0 ]->pev->solid = SOLID_NOT; + ppHiddenSegs[ 0 ]->pev->effects = EF_NODRAW; for( int uiIndex = 1; uiIndex < uiNumSegments; ++uiIndex ) { CRopeSegment* pPrim = ppPrimarySegs[ uiIndex ]; CRopeSegment* pHidden = ppHiddenSegs[ uiIndex ]; - pPrim->SetSolidType( SOLID_TRIGGER ); - pPrim->SetEffects( 0 ); + pPrim->pev->solid = SOLID_TRIGGER; + pPrim->pev->effects = 0; - pHidden->SetSolidType( SOLID_NOT ); - pHidden->SetEffects( EF_NODRAW ); + pHidden->pev->solid = SOLID_NOT; + pHidden->pev->effects = EF_NODRAW; Vector vecOrigin = pPrim->pev->origin; @@ -974,7 +978,7 @@ Vector CRope::GetAttachedObjectsVelocity() const if( !mObjectAttached ) return g_vecZero; - return seg[ mAttachedObjectsSegment ]->GetSample()->GetData()->mVelocity; + return seg[ mAttachedObjectsSegment ]->GetSample()->GetData().mVelocity; } void CRope::ApplyForceFromPlayer( const Vector& vecForce ) @@ -1002,11 +1006,11 @@ void CRope::ApplyForceToSegment( const Vector& vecForce, const int uiSegment ) { //Apply force to the last sample. - RopeSampleData *data = m_Samples[ uiSegment - 1 ]->GetData(); + RopeSampleData& data = m_Samples[ uiSegment - 1 ]->GetData(); - data->mExternalForce = data->mExternalForce + vecForce; + data.mExternalForce = data.mExternalForce + vecForce; - data->mApplyExternalForce = true; + data.mApplyExternalForce = true; } } @@ -1043,7 +1047,7 @@ bool CRope::ShouldCreak() const { CRopeSample* pSample = seg[ mAttachedObjectsSegment ]->GetSample(); - if( pSample->GetData()->mVelocity.Length() > 20.0 ) + if( pSample->GetData().mVelocity.Length() > 20.0 ) return RANDOM_LONG( 1, 5 ) == 1; } @@ -1093,7 +1097,7 @@ float CRope::GetRopeLength() const Vector CRope::GetRopeOrigin() const { - return m_Samples[ 0 ]->GetData()->mPosition; + return m_Samples[ 0 ]->GetData().mPosition; } bool CRope::IsValidSegmentIndex( const int uiSegment ) const @@ -1106,7 +1110,7 @@ Vector CRope::GetSegmentOrigin( const int uiSegment ) const if( !IsValidSegmentIndex( uiSegment ) ) return g_vecZero; - return m_Samples[ uiSegment ]->GetData()->mPosition; + return m_Samples[ uiSegment ]->GetData().mPosition; } Vector CRope::GetSegmentAttachmentPoint( const int uiSegment ) const @@ -1142,8 +1146,8 @@ Vector CRope::GetSegmentDirFromOrigin( const int uiSegmentIndex ) const //There is one more sample than there are segments, so this is fine. const Vector vecResult = - m_Samples[ uiSegmentIndex + 1 ]->GetData()->mPosition - - m_Samples[ uiSegmentIndex ]->GetData()->mPosition; + m_Samples[ uiSegmentIndex + 1 ]->GetData().mPosition - + m_Samples[ uiSegmentIndex ]->GetData().mPosition; return vecResult.Normalize(); } @@ -1156,7 +1160,7 @@ Vector CRope::GetAttachedObjectsPosition() const Vector vecResult; if( mAttachedObjectsSegment < m_iSegments ) - vecResult = m_Samples[ mAttachedObjectsSegment ]->GetData()->mPosition; + vecResult = m_Samples[ mAttachedObjectsSegment ]->GetData().mPosition; vecResult = vecResult + ( mAttachedObjectsOffset * GetSegmentDirFromOrigin( mAttachedObjectsSegment ) ); @@ -1194,7 +1198,7 @@ void CRopeSample::Spawn() { pev->classname = MAKE_STRING( "rope_sample" ); - AddEffectsFlags( EF_NODRAW ); + pev->effects |= EF_NODRAW; } CRopeSample* CRopeSample::CreateSample() @@ -1238,14 +1242,14 @@ void CRopeSegment::Spawn() SET_MODEL( edict(), STRING( mModelName ) ); - SetMoveType( MOVETYPE_NOCLIP ); - SetSolidType( SOLID_TRIGGER ); - SetEffects( EF_NODRAW ); + pev->movetype = MOVETYPE_NOCLIP; + pev->solid = SOLID_TRIGGER; + pev->effects = EF_NODRAW; SetAbsOrigin( pev->origin ); UTIL_SetSize( pev, Vector( -30, -30, -30 ), Vector( 30, 30, 30 ) ); - SetNextThink( gpGlobals->time + 0.5 ); + pev->nextthink = gpGlobals->time + 0.5; } void CRopeSegment::Touch( CBaseEntity* pOther ) @@ -1267,9 +1271,9 @@ void CRopeSegment::Touch( CBaseEntity* pOther ) { if( mCanBeGrabbed ) { - RopeSampleData *data = m_Sample->GetData(); + RopeSampleData& data = m_Sample->GetData(); - pOther->pev->origin = data->mPosition; + pOther->pev->origin = data.mPosition; pPlayer->SetOnRopeState( true ); pPlayer->SetRope( GetMasterRope() ); @@ -1280,9 +1284,9 @@ void CRopeSegment::Touch( CBaseEntity* pOther ) if( vecVelocity.Length() > 0.5 ) { //Apply some external force to move the rope. - Solokiller - data->mApplyExternalForce = true; + data.mApplyExternalForce = true; - data->mExternalForce = data->mExternalForce + vecVelocity * 750; + data.mExternalForce = data.mExternalForce + vecVelocity * 750; } if( GetMasterRope()->IsSoundAllowed() ) @@ -1326,7 +1330,7 @@ CRopeSegment* CRopeSegment::CreateSegment( CRopeSample* pSample, string_t iszMod pSegment->mCauseDamage = false; pSegment->mCanBeGrabbed = true; - pSegment->mDefaultMass = pSample->GetData()->mMassReciprocal; + pSegment->mDefaultMass = pSample->GetData().mMassReciprocal; pSegment->SetMasterRope(rope); return pSegment; @@ -1334,9 +1338,9 @@ CRopeSegment* CRopeSegment::CreateSegment( CRopeSample* pSample, string_t iszMod void CRopeSegment::ApplyExternalForce( const Vector& vecForce ) { - m_Sample->GetData()->mApplyExternalForce = true; + m_Sample->GetData().mApplyExternalForce = true; - m_Sample->GetData()->mExternalForce = m_Sample->GetData()->mExternalForce + vecForce; + m_Sample->GetData().mExternalForce = m_Sample->GetData().mExternalForce + vecForce; } void CRopeSegment::SetCauseDamageOnTouch( const bool bCauseDamage ) diff --git a/dlls/player.cpp b/dlls/player.cpp index 9c4d9eb0..6d615c85 100644 --- a/dlls/player.cpp +++ b/dlls/player.cpp @@ -37,6 +37,8 @@ #include "pm_shared.h" #include "hltv.h" +#include "ropes.h" + // #define DUCKFIX extern DLL_GLOBAL ULONG g_ulModelIndexPlayer; diff --git a/dlls/player.h b/dlls/player.h index c5ead599..746b5d9c 100644 --- a/dlls/player.h +++ b/dlls/player.h @@ -17,7 +17,7 @@ #define PLAYER_H #include "pm_materials.h" -#include "ropes.h" +class CRope; #define PLAYER_FATAL_FALL_SPEED 1024// approx 60 feet #define PLAYER_MAX_SAFE_FALL_SPEED 580// approx 20 feet From 6938f7e10ee4ad47180cf8aabf4b3dfb5a92cb4b Mon Sep 17 00:00:00 2001 From: Roman Chistokhodov Date: Sat, 16 Sep 2023 13:23:11 +0300 Subject: [PATCH 09/10] Fix sporelauncher not playing a pet sound. Set idle anim chances same as in opfor (#391) --- dlls/gearbox/sporelauncher.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dlls/gearbox/sporelauncher.cpp b/dlls/gearbox/sporelauncher.cpp index 9a2d59bd..103f2952 100644 --- a/dlls/gearbox/sporelauncher.cpp +++ b/dlls/gearbox/sporelauncher.cpp @@ -280,7 +280,7 @@ void CSporelauncher::Reload(void) m_fInSpecialReload = 2; // Play reload sound. - EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/splauncher_reload.wav", 1, ATTN_NORM, 0, 100); + EMIT_SOUND(m_pPlayer->edict(), CHAN_ITEM, "weapons/splauncher_reload.wav", 0.7f, ATTN_NORM); SendWeaponAnim(SPLAUNCHER_RELOAD_LOAD); @@ -328,12 +328,12 @@ void CSporelauncher::WeaponIdle(void) { int iAnim; float flRand = UTIL_SharedRandomFloat(m_pPlayer->random_seed, 0, 1); - if (flRand <= 0.4) + if (flRand <= 0.75f) { iAnim = SPLAUNCHER_IDLE; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0f; } - else if (flRand <= 0.8) + else if (flRand <= 0.95f) { iAnim = SPLAUNCHER_IDLE2; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 4.0f; @@ -342,6 +342,7 @@ void CSporelauncher::WeaponIdle(void) { iAnim = SPLAUNCHER_FIDGET; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 4.0f; + EMIT_SOUND(m_pPlayer->edict(), CHAN_ITEM, "weapons/splauncher_pet.wav", 0.7f, ATTN_NORM); } SendWeaponAnim(iAnim); From 04e56448f25a5061f16c063f462d6cc61da1538e Mon Sep 17 00:00:00 2001 From: Andrey Akhmichin <15944199+nekonomicon@users.noreply.github.com> Date: Tue, 19 Sep 2023 23:13:36 +0500 Subject: [PATCH 10/10] Revert "ARMv8 neon support" This reverts commit 8da76a8c3fb5246fb08526673f79f9a8d5498336. --- cl_dll/neon_mathfun.h | 356 ----------------------------------------- cl_dll/studio_util.cpp | 235 --------------------------- 2 files changed, 591 deletions(-) delete mode 100644 cl_dll/neon_mathfun.h diff --git a/cl_dll/neon_mathfun.h b/cl_dll/neon_mathfun.h deleted file mode 100644 index e45b92c1..00000000 --- a/cl_dll/neon_mathfun.h +++ /dev/null @@ -1,356 +0,0 @@ -/* NEON implementation of sin, cos, exp and log - - Inspired by Intel Approximate Math library, and based on the - corresponding algorithms of the cephes math library -*/ - -/* Copyright (C) 2011 Julien Pommier - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - (this is the zlib license) -*/ - -#include - -typedef float32x4_t v4sf; // vector of 4 float -typedef uint32x4_t v4su; // vector of 4 uint32 -typedef int32x4_t v4si; // vector of 4 uint32 - -#define s4f_x(s4f) vgetq_lane_f32(s4f, 0) -#define s4f_y(s4f) vgetq_lane_f32(s4f, 1) -#define s4f_z(s4f) vgetq_lane_f32(s4f, 2) -#define s4f_w(s4f) vgetq_lane_f32(s4f, 3) - -#define c_inv_mant_mask ~0x7f800000u -#define c_cephes_SQRTHF 0.707106781186547524 -#define c_cephes_log_p0 7.0376836292E-2 -#define c_cephes_log_p1 - 1.1514610310E-1 -#define c_cephes_log_p2 1.1676998740E-1 -#define c_cephes_log_p3 - 1.2420140846E-1 -#define c_cephes_log_p4 + 1.4249322787E-1 -#define c_cephes_log_p5 - 1.6668057665E-1 -#define c_cephes_log_p6 + 2.0000714765E-1 -#define c_cephes_log_p7 - 2.4999993993E-1 -#define c_cephes_log_p8 + 3.3333331174E-1 -#define c_cephes_log_q1 -2.12194440e-4 -#define c_cephes_log_q2 0.693359375 - -/* natural logarithm computed for 4 simultaneous float - return NaN for x <= 0 -*/ -inline v4sf log_ps(v4sf x) { - v4sf one = vdupq_n_f32(1); - - x = vmaxq_f32(x, vdupq_n_f32(0)); /* force flush to zero on denormal values */ - v4su invalid_mask = vcleq_f32(x, vdupq_n_f32(0)); - - v4si ux = vreinterpretq_s32_f32(x); - - v4si emm0 = vshrq_n_s32(ux, 23); - - /* keep only the fractional part */ - ux = vandq_s32(ux, vdupq_n_s32(c_inv_mant_mask)); - ux = vorrq_s32(ux, vreinterpretq_s32_f32(vdupq_n_f32(0.5f))); - x = vreinterpretq_f32_s32(ux); - - emm0 = vsubq_s32(emm0, vdupq_n_s32(0x7f)); - v4sf e = vcvtq_f32_s32(emm0); - - e = vaddq_f32(e, one); - - /* part2: - if( x < SQRTHF ) { - e -= 1; - x = x + x - 1.0; - } else { x = x - 1.0; } - */ - v4su mask = vcltq_f32(x, vdupq_n_f32(c_cephes_SQRTHF)); - v4sf tmp = vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(x), mask)); - x = vsubq_f32(x, one); - e = vsubq_f32(e, vreinterpretq_f32_u32(vandq_u32(vreinterpretq_u32_f32(one), mask))); - x = vaddq_f32(x, tmp); - - v4sf z = vmulq_f32(x,x); - - v4sf y = vdupq_n_f32(c_cephes_log_p0); - y = vmulq_f32(y, x); - y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p1)); - y = vmulq_f32(y, x); - y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p2)); - y = vmulq_f32(y, x); - y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p3)); - y = vmulq_f32(y, x); - y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p4)); - y = vmulq_f32(y, x); - y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p5)); - y = vmulq_f32(y, x); - y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p6)); - y = vmulq_f32(y, x); - y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p7)); - y = vmulq_f32(y, x); - y = vaddq_f32(y, vdupq_n_f32(c_cephes_log_p8)); - y = vmulq_f32(y, x); - - y = vmulq_f32(y, z); - - - tmp = vmulq_f32(e, vdupq_n_f32(c_cephes_log_q1)); - y = vaddq_f32(y, tmp); - - - tmp = vmulq_f32(z, vdupq_n_f32(0.5f)); - y = vsubq_f32(y, tmp); - - tmp = vmulq_f32(e, vdupq_n_f32(c_cephes_log_q2)); - x = vaddq_f32(x, y); - x = vaddq_f32(x, tmp); - x = vreinterpretq_f32_u32(vorrq_u32(vreinterpretq_u32_f32(x), invalid_mask)); // negative arg will be NAN - return x; -} - -#define c_exp_hi 88.3762626647949f -#define c_exp_lo -88.3762626647949f - -#define c_cephes_LOG2EF 1.44269504088896341 -#define c_cephes_exp_C1 0.693359375 -#define c_cephes_exp_C2 -2.12194440e-4 - -#define c_cephes_exp_p0 1.9875691500E-4 -#define c_cephes_exp_p1 1.3981999507E-3 -#define c_cephes_exp_p2 8.3334519073E-3 -#define c_cephes_exp_p3 4.1665795894E-2 -#define c_cephes_exp_p4 1.6666665459E-1 -#define c_cephes_exp_p5 5.0000001201E-1 - -/* exp() computed for 4 float at once */ -inline v4sf exp_ps(v4sf x) { - v4sf tmp, fx; - - v4sf one = vdupq_n_f32(1); - x = vminq_f32(x, vdupq_n_f32(c_exp_hi)); - x = vmaxq_f32(x, vdupq_n_f32(c_exp_lo)); - - /* express exp(x) as exp(g + n*log(2)) */ - fx = vmlaq_f32(vdupq_n_f32(0.5f), x, vdupq_n_f32(c_cephes_LOG2EF)); - - /* perform a floorf */ - tmp = vcvtq_f32_s32(vcvtq_s32_f32(fx)); - - /* if greater, substract 1 */ - v4su mask = vcgtq_f32(tmp, fx); - mask = vandq_u32(mask, vreinterpretq_u32_f32(one)); - - - fx = vsubq_f32(tmp, vreinterpretq_f32_u32(mask)); - - tmp = vmulq_f32(fx, vdupq_n_f32(c_cephes_exp_C1)); - v4sf z = vmulq_f32(fx, vdupq_n_f32(c_cephes_exp_C2)); - x = vsubq_f32(x, tmp); - x = vsubq_f32(x, z); - - static const float cephes_exp_p[6] = { c_cephes_exp_p0, c_cephes_exp_p1, c_cephes_exp_p2, c_cephes_exp_p3, c_cephes_exp_p4, c_cephes_exp_p5 }; - v4sf y = vld1q_dup_f32(cephes_exp_p+0); - v4sf c1 = vld1q_dup_f32(cephes_exp_p+1); - v4sf c2 = vld1q_dup_f32(cephes_exp_p+2); - v4sf c3 = vld1q_dup_f32(cephes_exp_p+3); - v4sf c4 = vld1q_dup_f32(cephes_exp_p+4); - v4sf c5 = vld1q_dup_f32(cephes_exp_p+5); - - y = vmulq_f32(y, x); - z = vmulq_f32(x,x); - y = vaddq_f32(y, c1); - y = vmulq_f32(y, x); - y = vaddq_f32(y, c2); - y = vmulq_f32(y, x); - y = vaddq_f32(y, c3); - y = vmulq_f32(y, x); - y = vaddq_f32(y, c4); - y = vmulq_f32(y, x); - y = vaddq_f32(y, c5); - - y = vmulq_f32(y, z); - y = vaddq_f32(y, x); - y = vaddq_f32(y, one); - - /* build 2^n */ - int32x4_t mm; - mm = vcvtq_s32_f32(fx); - mm = vaddq_s32(mm, vdupq_n_s32(0x7f)); - mm = vshlq_n_s32(mm, 23); - v4sf pow2n = vreinterpretq_f32_s32(mm); - - y = vmulq_f32(y, pow2n); - return y; -} - -#define c_minus_cephes_DP1 -0.78515625 -#define c_minus_cephes_DP2 -2.4187564849853515625e-4 -#define c_minus_cephes_DP3 -3.77489497744594108e-8 -#define c_sincof_p0 -1.9515295891E-4 -#define c_sincof_p1 8.3321608736E-3 -#define c_sincof_p2 -1.6666654611E-1 -#define c_coscof_p0 2.443315711809948E-005 -#define c_coscof_p1 -1.388731625493765E-003 -#define c_coscof_p2 4.166664568298827E-002 -#define c_cephes_FOPI 1.27323954473516 // 4 / M_PI - -/* evaluation of 4 sines & cosines at once. - - The code is the exact rewriting of the cephes sinf function. - Precision is excellent as long as x < 8192 (I did not bother to - take into account the special handling they have for greater values - -- it does not return garbage for arguments over 8192, though, but - the extra precision is missing). - - Note that it is such that sinf((float)M_PI) = 8.74e-8, which is the - surprising but correct result. - - Note also that when you compute sin(x), cos(x) is available at - almost no extra price so both sin_ps and cos_ps make use of - sincos_ps.. - */ -inline void sincos_ps(v4sf x, v4sf *ysin, v4sf *ycos) { // any x - v4sf y; - - v4su emm2; - - v4su sign_mask_sin, sign_mask_cos; - sign_mask_sin = vcltq_f32(x, vdupq_n_f32(0)); - x = vabsq_f32(x); - - /* scale by 4/Pi */ - y = vmulq_n_f32(x, c_cephes_FOPI); - - /* store the integer part of y in mm0 */ - emm2 = vcvtq_u32_f32(y); - /* j=(j+1) & (~1) (see the cephes sources) */ - emm2 = vaddq_u32(emm2, vdupq_n_u32(1)); - emm2 = vandq_u32(emm2, vdupq_n_u32(~1)); - y = vcvtq_f32_u32(emm2); - - /* get the polynom selection mask - there is one polynom for 0 <= x <= Pi/4 - and another one for Pi/4 -#include "neon_mathfun.h" -#endif /* ==================== @@ -23,59 +17,8 @@ AngleMatrix ==================== */ -#if XASH_SIMD_NEON -static const uint32x4_t AngleMatrix_sign0 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0), 0); -static const uint32x4_t AngleMatrix_sign1 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0), 1); -static const uint32x4_t AngleMatrix_sign2 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0), 2); -#endif void AngleMatrix( const float *angles, float (*matrix)[4] ) { -#if XASH_SIMD_NEON - float32x4x3_t out_reg; - float32x4_t angles_reg = {}; - memcpy(&angles_reg, angles, sizeof(float) * 3); - - float32x4x2_t sp_sy_sr_0_cp_cy_cr_1; - sincos_ps(vmulq_n_f32(angles_reg, (M_PI * 2 / 360)), &sp_sy_sr_0_cp_cy_cr_1.val[0], &sp_sy_sr_0_cp_cy_cr_1.val[1]); - - float32x4x2_t sp_sr_cp_cr_sy_0_cy_1 = vuzpq_f32(sp_sy_sr_0_cp_cy_cr_1.val[0], sp_sy_sr_0_cp_cy_cr_1.val[1]); - float32x4x2_t sp_cp_sy_cy_sr_cr_0_1 = vzipq_f32(sp_sy_sr_0_cp_cy_cr_1.val[0], sp_sy_sr_0_cp_cy_cr_1.val[1]); - - float32x4_t _0_sr_cr_0 = vextq_f32(sp_sy_sr_0_cp_cy_cr_1.val[0], sp_cp_sy_cy_sr_cr_0_1.val[1], 3); - float32x4_t cp_cr_sr_0 = vcombine_f32(vget_high_f32(sp_sr_cp_cr_sy_0_cy_1.val[0]), vget_high_f32(sp_sy_sr_0_cp_cy_cr_1.val[0])); - float32x4_t cy_sy_sy_0 = vcombine_f32(vrev64_f32(vget_high_f32(sp_cp_sy_cy_sr_cr_0_1.val[0])), vget_low_f32(sp_sr_cp_cr_sy_0_cy_1.val[1])); - float32x4_t sy_cy_cy_1 = vcombine_f32(vget_high_f32(sp_cp_sy_cy_sr_cr_0_1.val[0]), vget_high_f32(sp_sr_cp_cr_sy_0_cy_1.val[1])); - - float32x4_t _0_srsp_crsp_0 = vmulq_laneq_f32(_0_sr_cr_0, sp_sy_sr_0_cp_cy_cr_1.val[0], 0); // *sp - out_reg.val[0] = vmulq_laneq_f32(_0_srsp_crsp_0, sp_sy_sr_0_cp_cy_cr_1.val[1], 1); // *cy - out_reg.val[1] = vmulq_laneq_f32(_0_srsp_crsp_0, sp_sy_sr_0_cp_cy_cr_1.val[0], 1); // *sy - - cy_sy_sy_0 = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(cy_sy_sy_0), AngleMatrix_sign1)); - sy_cy_cy_1 = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(sy_cy_cy_1), AngleMatrix_sign2)); - out_reg.val[0] = vfmaq_f32(out_reg.val[0], cp_cr_sr_0, cy_sy_sy_0); - out_reg.val[1] = vfmaq_f32(out_reg.val[1], cp_cr_sr_0, sy_cy_cy_1); - - float32x4_t cp_cr_0_1 = vcombine_f32(vget_high_f32(sp_sr_cp_cr_sy_0_cy_1.val[0]), vget_high_f32(sp_cp_sy_cy_sr_cr_0_1.val[1])); - float32x4_t _1_cp_cr_0 = vextq_f32(cp_cr_0_1, cp_cr_0_1, 3); - out_reg.val[2] = vmulq_f32(sp_sr_cp_cr_sy_0_cy_1.val[0], _1_cp_cr_0); - out_reg.val[2] = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(out_reg.val[2]), AngleMatrix_sign0)); - - memcpy(matrix, &out_reg, sizeof(float) * 3 * 4); -/* - matrix[0][0] = cp*cy; - matrix[0][1] = sr*sp*cy-cr*sy; - matrix[0][2] = cr*sp*cy+sr*sy; - matrix[0][3] = 0.0; - matrix[1][0] = cp*sy; - matrix[1][1] = sr*sp*sy+cr*cy; - matrix[1][2] = cr*sp*sy-sr*cy; - matrix[1][3] = 0.0; - matrix[2][0] = -sp*1; - matrix[2][1] = sr*cp; - matrix[2][2] = cp*cr; - matrix[2][3] = cr*0; -*/ -#else float angle; float sr, sp, sy, cr, cp, cy; @@ -102,7 +45,6 @@ void AngleMatrix( const float *angles, float (*matrix)[4] ) matrix[0][3] = 0.0f; matrix[1][3] = 0.0f; matrix[2][3] = 0.0f; -#endif } /* @@ -113,13 +55,6 @@ VectorCompare */ int VectorCompare( const float *v1, const float *v2 ) { -#if XASH_SIMD_NEON - // is this really works? - float32x4_t v1_reg = {}, v2_reg = {}; - memcpy(&v1_reg, v1, sizeof(float) * 3); - memcpy(&v2_reg, v2, sizeof(float) * 3); - return !vaddvq_u32(vceqq_f32(v1_reg, v2_reg)); -#else int i; for( i = 0; i < 3; i++ ) @@ -127,7 +62,6 @@ int VectorCompare( const float *v1, const float *v2 ) return 0; return 1; -#endif } /* @@ -138,23 +72,9 @@ CrossProduct */ void CrossProduct( const float *v1, const float *v2, float *cross ) { -#if XASH_SIMD_NEON - float32x4_t v1_reg = {}, v2_reg = {}; - memcpy(&v1_reg, v1, sizeof(float) * 3); - memcpy(&v2_reg, v2, sizeof(float) * 3); - - float32x4_t yzxy_a = vextq_f32(vextq_f32(v1_reg, v1_reg, 3), v1_reg, 2); // [aj, ak, ai, aj] - float32x4_t yzxy_b = vextq_f32(vextq_f32(v2_reg, v2_reg, 3), v2_reg, 2); // [bj, bk, bi, bj] - float32x4_t zxyy_a = vextq_f32(yzxy_a, yzxy_a, 1); // [ak, ai, aj, aj] - float32x4_t zxyy_b = vextq_f32(yzxy_b, yzxy_b, 1); // [bk, ai, bj, bj] - float32x4_t cross_reg = vfmsq_f32(vmulq_f32(yzxy_a, zxyy_b), zxyy_a, yzxy_b); // [ajbk-akbj, akbi-aibk, aibj-ajbi, 0] - - memcpy(cross, &cross_reg, sizeof(float) * 3); -#else cross[0] = v1[1] * v2[2] - v1[2] * v2[1]; cross[1] = v1[2] * v2[0] - v1[0] * v2[2]; cross[2] = v1[0] * v2[1] - v1[1] * v2[0]; -#endif } /* @@ -165,26 +85,9 @@ VectorTransform */ void VectorTransform( const float *in1, float in2[3][4], float *out ) { -#if XASH_SIMD_NEON - float32x4_t in1_reg = {}; - memcpy(&in1_reg, &in1, sizeof(float) * 3); - - float32x4x4_t in_t; - memcpy(&in_t, &in2, sizeof(float) * 3 * 4); - //memset(&in_t.val[3], 0, sizeof(in_t.val[3])); - in_t = vld4q_f32((const float*)&in_t); - - float32x4_t out_reg = in_t.val[3]; - out_reg = vfmaq_laneq_f32(out_reg, in_t.val[0], in1_reg, 0); - out_reg = vfmaq_laneq_f32(out_reg, in_t.val[1], in1_reg, 1); - out_reg = vfmaq_laneq_f32(out_reg, in_t.val[2], in1_reg, 2); - - memcpy(out, &out_reg, sizeof(float) * 3); -#else out[0] = DotProduct(in1, in2[0]) + in2[0][3]; out[1] = DotProduct(in1, in2[1]) + in2[1][3]; out[2] = DotProduct(in1, in2[2]) + in2[2][3]; -#endif } /* @@ -195,29 +98,6 @@ ConcatTransforms */ void ConcatTransforms( float in1[3][4], float in2[3][4], float out[3][4] ) { -#if XASH_SIMD_NEON - float32x4x3_t in1_reg, in2_reg; - memcpy(&in1_reg, in1, sizeof(float) * 3 * 4); - memcpy(&in2_reg, in2, sizeof(float) * 3 * 4); - float32x4x3_t out_reg = {}; - - out_reg.val[0] = vcopyq_laneq_f32(out_reg.val[0], 3, in1_reg.val[0], 3); // out[0][3] = in[0][3] - out_reg.val[0] = vfmaq_laneq_f32(out_reg.val[0], in2_reg.val[0], in1_reg.val[0], 0); // out[0][n] += in2[0][n] * in1[0][0] - out_reg.val[0] = vfmaq_laneq_f32(out_reg.val[0], in2_reg.val[1], in1_reg.val[0], 1); // out[0][n] += in2[1][n] * in1[0][1] - out_reg.val[0] = vfmaq_laneq_f32(out_reg.val[0], in2_reg.val[2], in1_reg.val[0], 2); // out[0][n] += in2[2][n] * in1[0][2] - - out_reg.val[1] = vcopyq_laneq_f32(out_reg.val[1], 3, in1_reg.val[1], 3); - out_reg.val[1] = vfmaq_laneq_f32(out_reg.val[1], in2_reg.val[0], in1_reg.val[1], 0); - out_reg.val[1] = vfmaq_laneq_f32(out_reg.val[1], in2_reg.val[1], in1_reg.val[1], 1); - out_reg.val[1] = vfmaq_laneq_f32(out_reg.val[1], in2_reg.val[2], in1_reg.val[1], 2); - - out_reg.val[2] = vcopyq_laneq_f32(out_reg.val[2], 3, in1_reg.val[2], 3); - out_reg.val[2] = vfmaq_laneq_f32(out_reg.val[2], in2_reg.val[0], in1_reg.val[2], 0); - out_reg.val[2] = vfmaq_laneq_f32(out_reg.val[2], in2_reg.val[1], in1_reg.val[2], 1); - out_reg.val[2] = vfmaq_laneq_f32(out_reg.val[2], in2_reg.val[2], in1_reg.val[2], 2); - - memcpy(out, &out_reg, sizeof(float) * 3 * 4); -#else out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0]; out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + @@ -242,7 +122,6 @@ void ConcatTransforms( float in1[3][4], float in2[3][4], float out[3][4] ) in1[2][2] * in2[2][2]; out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3]; -#endif } // angles index are not the same as ROLL, PITCH, YAW @@ -253,36 +132,8 @@ AngleQuaternion ==================== */ -#if XASH_SIMD_NEON -static const uint32x4_t AngleQuaternion_sign2 = vzipq_u32(vdupq_n_u32(0x80000000), vdupq_n_u32(0x00000000)).val[0]; // { 0x80000000, 0x00000000, 0x80000000, 0x00000000 }; -#endif void AngleQuaternion( float *angles, vec4_t quaternion ) { -#if XASH_SIMD_NEON - float32x4_t angles_reg = {}; - memcpy(&angles_reg, angles, sizeof(float) * 3); - float32x4x2_t sr_sp_sy_0_cr_cp_cy_1; - sincos_ps(vmulq_n_f32(angles_reg, 0.5), &sr_sp_sy_0_cr_cp_cy_1.val[0], &sr_sp_sy_0_cr_cp_cy_1.val[1]); - - float32x4x2_t sr_sy_cr_cy_sp_0_cp_1 = vuzpq_f32(sr_sp_sy_0_cr_cp_cy_1.val[0], sr_sp_sy_0_cr_cp_cy_1.val[1]); - float32x4_t cp_cp_cp_cp = vdupq_laneq_f32(sr_sp_sy_0_cr_cp_cy_1.val[1], 1); - float32x4_t sp_sp_sp_sp = vdupq_laneq_f32(sr_sp_sy_0_cr_cp_cy_1.val[0], 1); - - float32x4_t sr_sy_cr_cy = sr_sy_cr_cy_sp_0_cp_1.val[0]; - float32x4_t sy_cr_cy_sr = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 1); - float32x4_t cr_cy_sr_sy = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 2); - float32x4_t cy_sr_sy_cr = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 3); - float32x4_t sp_sp_sp_sp_signed = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(sp_sp_sp_sp), AngleQuaternion_sign2)); - - float32x4_t left = vmulq_f32(vmulq_f32(sr_sy_cr_cy, cp_cp_cp_cp), cy_sr_sy_cr); - - float32x4_t out_reg = vfmaq_f32(left, vmulq_f32(cr_cy_sr_sy, sp_sp_sp_sp_signed), sy_cr_cy_sr); - memcpy(quaternion, &out_reg, sizeof(float) * 4); - //quaternion[0] = sr * cp * cy - cr * sp * sy; // X - //quaternion[1] = sy * cp * sr + cy * sp * cr; // Y - //quaternion[2] = cr * cp * sy - sr * sp * cy; // Z - //quaternion[3] = cy * cp * cr + sy * sp * sr; // W -#else float angle; float sr, sp, sy, cr, cp, cy; @@ -301,7 +152,6 @@ void AngleQuaternion( float *angles, vec4_t quaternion ) quaternion[1] = cr * sp * cy + sr * cp * sy; // Y quaternion[2] = cr * cp * sy - sr * sp * cy; // Z quaternion[3] = cr * cp * cy + sr * sp * sy; // W -#endif } /* @@ -312,37 +162,6 @@ QuaternionSlerp */ void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt ) { -#if XASH_SIMD_NEON - float32x4_t p_reg = {}, q_reg = {}; - memcpy(&p_reg, p, sizeof(float) * 4); - memcpy(&q_reg, q, sizeof(float) * 4); - - // q = (cos(a/2), xsin(a/2), ysin(a/2), zsin(a/2)) - // cos(a-b) = cosacosb+sinasinb - const uint32x4_t signmask = vdupq_n_u32(0x80000000); - const float32x4_t one_minus_epsilon = vdupq_n_f32(1.0f - 0.00001f); - - float32x4_t vcosom = vdupq_n_f32(DotProduct(p, q)); - uint32x4_t sign = vandq_u32(vreinterpretq_u32_f32(vcosom), signmask); - q_reg = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(p_reg), sign)); - vcosom = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(vcosom), sign)); - - float x[4] = {(1.0f - t), t, 1, 0}; // cosom -> 1, sinom -> 0, sinx ~ x - float32x4_t x_reg; - memcpy(&x_reg, x, sizeof(float) * 4); - - // if ((1.0 - cosom) > 0.000001) x = sin(x * omega) - uint32x4_t cosom_less_then_one = vcltq_f32(vcosom, one_minus_epsilon); - float32x4_t vomega = acos_ps(vcosom); - x_reg = vbslq_f32(cosom_less_then_one, x_reg, sin_ps(vmulq_f32(x_reg, vomega))); - - // qt = (x[0] * p + x[1] * q) / x[2]; - float32x4_t qt_reg = vmulq_laneq_f32(p_reg, x_reg, 0); - qt_reg = vfmaq_laneq_f32(qt_reg, q_reg, x_reg, 1); - qt_reg = vdivq_f32(qt_reg, vdupq_laneq_f32(x_reg, 2)); // vdivq_laneq_f32 ? - - memcpy(qt, &qt_reg, sizeof(float) * 4); -#else int i; float omega, cosom, sinom, sclp, sclq; @@ -397,7 +216,6 @@ void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt ) qt[i] = sclp * p[i] + sclq * qt[i]; } } -#endif } /* @@ -406,60 +224,8 @@ QuaternionMatrix ==================== */ -#if XASH_SIMD_NEON -static const uint32x4_t QuaternionMatrix_sign1 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0x00000000), 0); // { 0x80000000, 0x00000000, 0x00000000, 0x00000000 }; -static const uint32x4_t QuaternionMatrix_sign2 = vsetq_lane_u32(0x80000000, vdupq_n_u32(0x00000000), 1); // { 0x00000000, 0x80000000, 0x00000000, 0x00000000 }; -static const uint32x4_t QuaternionMatrix_sign3 = vsetq_lane_u32(0x00000000, vdupq_n_u32(0x80000000), 2); // { 0x80000000, 0x80000000, 0x00000000, 0x80000000 }; -static const float32x4_t matrix3x4_identity_0 = vsetq_lane_f32(1, vdupq_n_f32(0), 0); // { 1, 0, 0, 0 } -static const float32x4_t matrix3x4_identity_1 = vsetq_lane_f32(1, vdupq_n_f32(0), 1); // { 0, 1, 0, 0 } -static const float32x4_t matrix3x4_identity_2 = vsetq_lane_f32(1, vdupq_n_f32(0), 2); // { 0, 0, 1, 0 } -#endif - void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] ) { -#if XASH_SIMD_NEON - float32x4_t quaternion_reg; - memcpy(&quaternion_reg, quaternion, sizeof(float) * 4); - - float32x4_t q1032 = vrev64q_f32(quaternion_reg); - float32x4_t q1032_signed = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(q1032), QuaternionMatrix_sign1)); - float32x4_t q2301 = vextq_f32(quaternion_reg, quaternion_reg, 2); - float32x4_t q2301_signed = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(q2301), QuaternionMatrix_sign3)); - float32x4_t q3210 = vrev64q_f32(q2301); - float32x4_t q3210_signed = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(q3210), QuaternionMatrix_sign2)); - - float32x4x3_t out_reg; - - out_reg.val[0] = vmulq_laneq_f32(q2301_signed, quaternion_reg, 2); - out_reg.val[0] = vfmaq_laneq_f32(out_reg.val[0], q1032_signed, quaternion_reg, 1); - out_reg.val[0] = vfmaq_n_f32(matrix3x4_identity_0, out_reg.val[0], 2.0f); - - out_reg.val[1] = vmulq_laneq_f32(q3210_signed, quaternion_reg, 2); - out_reg.val[1] = vfmsq_laneq_f32(out_reg.val[1], q1032_signed, quaternion_reg, 0); - out_reg.val[1] = vfmaq_n_f32(matrix3x4_identity_1, out_reg.val[1], 2.0f); - - out_reg.val[2] = vmulq_laneq_f32(q3210_signed, quaternion_reg, 1); - out_reg.val[2] = vfmaq_laneq_f32(out_reg.val[2], q2301_signed, quaternion_reg, 0); - out_reg.val[2] = vfmsq_n_f32(matrix3x4_identity_2, out_reg.val[2], 2.0f); - - memcpy(matrix, &out_reg, sizeof(float) * 3 * 4); -/* - matrix[0][0] = 1.0 + 2.0 * ( quaternion[1] * -quaternion[1] + -quaternion[2] * quaternion[2] ); - matrix[0][1] = 0.0 + 2.0 * ( quaternion[1] * quaternion[0] + -quaternion[3] * quaternion[2] ); - matrix[0][2] = 0.0 + 2.0 * ( quaternion[1] * quaternion[3] + quaternion[0] * quaternion[2] ); - matrix[0][3] = 0.0 + 2.0 * ( quaternion[1] * quaternion[2] + -quaternion[1] * quaternion[2] ); - - matrix[1][0] = 0.0 + 2.0 * ( -quaternion[0] * -quaternion[1] + quaternion[3] * quaternion[2] ); - matrix[1][1] = 1.0 + 2.0 * ( -quaternion[0] * quaternion[0] + -quaternion[2] * quaternion[2] ); - matrix[1][2] = 0.0 + 2.0 * ( -quaternion[0] * quaternion[3] + quaternion[1] * quaternion[2] ); - matrix[1][3] = 0.0 + 2.0 * ( -quaternion[0] * quaternion[2] + quaternion[0] * quaternion[2] ); - - matrix[2][0] = 0.0 + 2.0 * ( -quaternion[0] * -quaternion[2] + -quaternion[3] * quaternion[1] ); - matrix[2][1] = 0.0 + 2.0 * ( -quaternion[0] * -quaternion[3] + quaternion[2] * quaternion[1] ); - matrix[2][2] = 1.0 + 2.0 * ( -quaternion[0] * quaternion[0] + -quaternion[1] * quaternion[1] ); - matrix[2][3] = 0.0 + 2.0 * ( -quaternion[0] * -quaternion[1] + -quaternion[0] * quaternion[1] ); -*/ -#else matrix[0][0] = 1.0f - 2.0f * quaternion[1] * quaternion[1] - 2.0f * quaternion[2] * quaternion[2]; matrix[1][0] = 2.0f * quaternion[0] * quaternion[1] + 2.0f * quaternion[3] * quaternion[2]; matrix[2][0] = 2.0f * quaternion[0] * quaternion[2] - 2.0f * quaternion[3] * quaternion[1]; @@ -471,7 +237,6 @@ void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] ) matrix[0][2] = 2.0f * quaternion[0] * quaternion[2] + 2.0f * quaternion[3] * quaternion[1]; matrix[1][2] = 2.0f * quaternion[1] * quaternion[2] - 2.0f * quaternion[3] * quaternion[0]; matrix[2][2] = 1.0f - 2.0f * quaternion[0] * quaternion[0] - 2.0f * quaternion[1] * quaternion[1]; -#endif } /*