From ca9a53e4f7d458e7bed3cdff032b5a90238469cc Mon Sep 17 00:00:00 2001
From: D-AIRY <admin@ds-servers.com>
Date: Tue, 22 Dec 2020 15:14:55 +0300
Subject: [PATCH] Removed some onSync calls

---
 source/anim/DynamicModel.cpp     |  21 +++++--
 source/game/BaseAnimating.cpp    |  38 ++++--------
 source/game/BaseAnimating.h      |  51 ++++++++++++---
 source/game/BaseEntity.cpp       |   5 --
 source/game/BaseEntity.h         |   6 +-
 source/game/BaseLight.cpp        | 103 ++-----------------------------
 source/game/BaseLight.h          |  12 +---
 source/game/LightDirectional.cpp |   5 --
 source/game/LightDirectional.h   |   1 -
 source/game/LightPoint.cpp       |   6 --
 source/game/LightPoint.h         |   1 -
 source/game/LightSun.cpp         |   5 --
 source/game/LightSun.h           |   1 -
 source/game/PropDebris.cpp       |   3 +-
 source/game/SoundEmitter.cpp     |  50 ++++++++++-----
 source/game/SoundEmitter.h       |   6 +-
 source/game/SoundPlayer.cpp      |  56 ++++++++++++-----
 source/game/SoundPlayer.h        |  13 +++-
 source/xcommon/IXSoundSystem.h   |   4 +-
 19 files changed, 173 insertions(+), 214 deletions(-)

diff --git a/source/anim/DynamicModel.cpp b/source/anim/DynamicModel.cpp
index f83a8ead9..06f265584 100644
--- a/source/anim/DynamicModel.cpp
+++ b/source/anim/DynamicModel.cpp
@@ -94,9 +94,12 @@ void XMETHODCALLTYPE CDynamicModel::setPosition(const float3 &vPos)
 	m_vPosition = vPos;
 	m_isWorldDirty = true;
 
-	m_pProvider->notifyModelChanged(this, XEventModelChanged::TYPE_MOVED);
+	if(m_isEnabled)
+	{
+		m_pProvider->notifyModelChanged(this, XEventModelChanged::TYPE_MOVED);
 
-	m_pSceneObject->update(getLocalBound() + getPosition());
+		m_pSceneObject->update(getLocalBound() + getPosition());
+	}
 }
 
 SMQuaternion XMETHODCALLTYPE CDynamicModel::getOrientation() const
@@ -113,9 +116,12 @@ void XMETHODCALLTYPE CDynamicModel::setOrientation(const SMQuaternion &qRot)
 	m_isLocalAABBvalid = false;
 	m_isWorldDirty = true;
 
-	m_pProvider->notifyModelChanged(this, XEventModelChanged::TYPE_MOVED);
+	if(m_isEnabled)
+	{
+		m_pProvider->notifyModelChanged(this, XEventModelChanged::TYPE_MOVED);
 
-	m_pSceneObject->update(getLocalBound() + getPosition());
+		m_pSceneObject->update(getLocalBound() + getPosition());
+	}
 }
 
 float XMETHODCALLTYPE CDynamicModel::getScale() const
@@ -132,9 +138,12 @@ void XMETHODCALLTYPE CDynamicModel::setScale(float fScale)
 	m_isLocalAABBvalid = false;
 	m_isWorldDirty = true;
 
-	m_pProvider->notifyModelChanged(this, XEventModelChanged::TYPE_MOVED);
+	if(m_isEnabled)
+	{
+		m_pProvider->notifyModelChanged(this, XEventModelChanged::TYPE_MOVED);
 
-	m_pSceneObject->update(getLocalBound() + getPosition());
+		m_pSceneObject->update(getLocalBound() + getPosition());
+	}
 }
 
 UINT XMETHODCALLTYPE CDynamicModel::getSkin() const
diff --git a/source/game/BaseAnimating.cpp b/source/game/BaseAnimating.cpp
index ac92c7e51..4a19bb739 100644
--- a/source/game/BaseAnimating.cpp
+++ b/source/game/BaseAnimating.cpp
@@ -77,10 +77,11 @@ private:
 
 //##########################################################################
 
-CBaseAnimating::CBaseAnimating()
+CBaseAnimating::CBaseAnimating():
+	m_motionState(this),
+	m_pAnimationCallback(new CAnimationCallback(this))
 {
 	memset(m_vNextAnim, 0, sizeof(m_vNextAnim));
-	m_pAnimationCallback = new CAnimationCallback(this);
 }
 
 CBaseAnimating::~CBaseAnimating()
@@ -190,32 +191,19 @@ SMQuaternion CBaseAnimating::getAttachmentRot(int id)
 	return(/*getOrient() * */rot);
 }
 
+#if 0
 void CBaseAnimating::onSync()
 {
 	BaseClass::onSync();
-	if(!m_pParent && m_pRigidBody && !m_isStatic)
-	{
-		btVector3 &v = m_pRigidBody->getWorldTransform().getOrigin();
-		setPos(BTVEC_F3(v));
-		btQuaternion &q = m_pRigidBody->getWorldTransform().getRotation();
-		setOrient(BTQUAT_Q4(q));
-	}
-	else if(m_pRigidBody)
-	{
-	//	m_pRigidBody->getWorldTransform().setOrigin(F3_BTVEC(getPos()));
-	//	m_pRigidBody->getWorldTransform().setRotation(Q4_BTQUAT(getOrient()));
-	}
 	if(m_pModel && m_pModel->isEnabled())
 	{
-		m_pModel->setPosition(getPos());
-		m_pModel->setOrientation(getOrient());
-
 		float3_t vGlowColor = m_vGlowColor;
 		//bool isGlowEnabled = m_pEntColorRef ? m_pEntColorRef->getMainColor(&vGlowColor) : m_vGlowColor.x != 0.0f || m_vGlowColor.y != 0.0f || m_vGlowColor.z != 0.0f;
 		m_pModel->setColor(float4(vGlowColor));
 		//m_pAnimPlayer->setGlowEnabled(isGlowEnabled);
 	}
 }
+#endif
 
 void CBaseAnimating::playAnimation(const char * name, UINT iFadeTime, UINT slot)
 {
@@ -381,13 +369,9 @@ void CBaseAnimating::createPhysBody()
 		const float fMass = 1.0f;
 		m_pCollideShape->calculateLocalInertia(fMass, vInertia);
 
-		float3 vPos = getPos();
-		SMQuaternion qRot = getOrient();
-
-		btDefaultMotionState * motionState = new btDefaultMotionState(btTransform(Q4_BTQUAT(qRot), F3_BTVEC(vPos)));
 		btRigidBody::btRigidBodyConstructionInfo rigidBodyCI(
 			fMass,                  // mass
-			motionState,        // initial position
+			&m_motionState,        // initial position
 			m_pCollideShape,    // collision shape of body
 			vInertia  // local inertia
 			);
@@ -452,15 +436,15 @@ COLLISION_GROUP CBaseAnimating::getCollisionGroup()
 	return(m_collisionGroup);
 }
 
-void CBaseAnimating::setPos(const float3 & pos)
+void CBaseAnimating::setPos(const float3 &pos)
 {
 	BaseClass::setPos(pos);
 	if(m_pRigidBody)
 	{
-		m_pRigidBody->getWorldTransform().setOrigin(F3_BTVEC(pos));
-
 		SPhysics_GetDynWorld()->updateSingleAabb(m_pRigidBody);
 	}
+
+	SAFE_CALL(m_pModel, setPosition, pos);
 }
 
 void CBaseAnimating::setOrient(const SMQuaternion & q)
@@ -468,10 +452,10 @@ void CBaseAnimating::setOrient(const SMQuaternion & q)
 	BaseClass::setOrient(q);
 	if(m_pRigidBody)
 	{
-		m_pRigidBody->getWorldTransform().setRotation(Q4_BTQUAT(q));
-
 		SPhysics_GetDynWorld()->updateSingleAabb(m_pRigidBody);
 	}
+
+	SAFE_CALL(m_pModel, setOrientation, q);
 }
 
 void CBaseAnimating::_cleanup()
diff --git a/source/game/BaseAnimating.h b/source/game/BaseAnimating.h
index b80b5ac98..bd0b17552 100644
--- a/source/game/BaseAnimating.h
+++ b/source/game/BaseAnimating.h
@@ -22,6 +22,37 @@ See the license in LICENSE
 
 #define BLEND_MAX 4
 
+struct CMotionState: public btMotionState
+{
+private:
+	CBaseEntity *m_pEntity;
+
+public:
+	CMotionState(CBaseEntity *pEntity):
+		m_pEntity(pEntity)
+	{
+	}
+
+	///synchronizes world transform from user to physics
+	void getWorldTransform(btTransform &centerOfMassWorldTrans) const override
+	{
+		float3 vPos = m_pEntity->getPos();
+		SMQuaternion qRot = m_pEntity->getOrient();
+
+		centerOfMassWorldTrans = btTransform(Q4_BTQUAT(qRot), F3_BTVEC(vPos));
+	}
+
+	///synchronizes world transform from physics to user
+	///Bullet only calls the update of worldtransform for active objects
+	void setWorldTransform(const btTransform& centerOfMassWorldTrans) override
+	{
+		const btVector3 &v = centerOfMassWorldTrans.getOrigin();
+		const btQuaternion &q = centerOfMassWorldTrans.getRotation();
+		m_pEntity->setPos(BTVEC_F3(v));
+		m_pEntity->setOrient(BTQUAT_Q4(q));
+	}
+};
+
 class CAnimationCallback;
 //! Анимированный игровой объект
 class CBaseAnimating: public CBaseEntity
@@ -34,16 +65,16 @@ public:
 	DECLARE_CONSTRUCTOR();
 	~CBaseAnimating();
 
-	void getMinMax(float3 * min, float3 * max);
+	void getMinMax(float3 *min, float3 *max);
 	// void getSphere(float3 * center, float * radius);
 
 	virtual void setModel(const char *szMdl);
 	virtual void setScale(float fScale);
 
-	float3 getAttachmentPos(int id);
-	SMQuaternion getAttachmentRot(int id);
+	float3 getAttachmentPos(int id) override;
+	SMQuaternion getAttachmentRot(int id) override;
 
-	void onSync() override;
+	//void onSync() override;
 
 	void playAnimation(const char * name, UINT uFadeTime = 0, UINT slot = 0);
 	void playActivity(const char * name, UINT uFadeTime = 0, UINT slot = 0);
@@ -68,13 +99,13 @@ protected:
 	virtual void _initEditorBoxes();
 	virtual void _releaseEditorBoxes();
 
-	void inputPlayAnim(inputdata_t * pInputdata);
-	void inputPlayAnimNext(inputdata_t * pInputdata);
+	void inputPlayAnim(inputdata_t *pInputdata);
+	void inputPlayAnimNext(inputdata_t *pInputdata);
 
-	void inputPlayActivity(inputdata_t * pInputdata);
-	void inputPlayActivityNext(inputdata_t * pInputdata);
+	void inputPlayActivity(inputdata_t *pInputdata);
+	void inputPlayActivityNext(inputdata_t *pInputdata);
 
-	void inputSetSkin(inputdata_t * pInputdata);
+	void inputSetSkin(inputdata_t *pInputdata);
 
 	IXModel *m_pModel = NULL;
 	const char * m_szModelFile;
@@ -115,6 +146,8 @@ private:
 	COLLISION_GROUP m_collisionGroup = CG_DEFAULT;
 	COLLISION_GROUP m_collisionMask = CG_ALL;
 	CAnimationCallback *m_pAnimationCallback;
+
+	CMotionState m_motionState;
 };
 
 #endif
diff --git a/source/game/BaseEntity.cpp b/source/game/BaseEntity.cpp
index 81e8ef7d7..662e96671 100644
--- a/source/game/BaseEntity.cpp
+++ b/source/game/BaseEntity.cpp
@@ -688,11 +688,6 @@ CBaseEntity* CBaseEntity::getParent()
 	}
 }*/
 
-void CBaseEntity::onSync()
-{
-	m_bSynced = true;
-}
-
 void CBaseEntity::onPostLoad()
 {
 	updateOutputs();
diff --git a/source/game/BaseEntity.h b/source/game/BaseEntity.h
index fcb4657c3..ff40b1349 100644
--- a/source/game/BaseEntity.h
+++ b/source/game/BaseEntity.h
@@ -223,7 +223,9 @@ protected:
 	CBaseEntity *m_pOwner = NULL;
 
 	//! Вызывается на стадии синхронизации
-	virtual void onSync();
+	virtual void onSync()
+	{
+	}
 	//! Вызывается при создании после установки всех свойств
 	virtual void onPostLoad();
 
@@ -247,8 +249,6 @@ protected:
 
 	void takeHealth(float fVal, CBaseEntity *pAttacker, CBaseEntity *pInflictor=NULL);
 
-	bool m_bSynced = false;
-
 
 	//! Для редактора
 	//@{
diff --git a/source/game/BaseLight.cpp b/source/game/BaseLight.cpp
index c245766e6..4940347de 100644
--- a/source/game/BaseLight.cpp
+++ b/source/game/BaseLight.cpp
@@ -19,8 +19,6 @@ BEGIN_PROPTABLE(CBaseLight)
 	//DEFINE_FIELD_FLOAT(m_fShadowDist, 0, "light_far", "Shadow far plane", EDITOR_TEXTFIELD)
 	//! Интенсивность теней
 	DEFINE_FIELD_FLOATFN(m_fShadowIntensity, 0, "shadow_intensity", "Shadow intensity", setShadowIntensity, EDITOR_TEXTFIELD)
-	//! Связанный свет (повторяет его состояние включения)
-	DEFINE_FIELD_ENTITYFN(m_pLinkedTo, 0, "linked_to", "Linked light to", setLinkedTo, EDITOR_TEXTFIELD)
 
 	//! Тип тени
 	DEFINE_FIELD_INTFN(m_iShadowType, 0, "type_shadow", "Type shadow", setShadowType, EDITOR_COMBOBOX)
@@ -47,10 +45,7 @@ REGISTER_ENTITY_NOLISTING(CBaseLight, base_light);
 
 CBaseLight::~CBaseLight()
 {
-	if(m_pLinkedTo)
-	{
-		((CBaseLight*)m_pLinkedTo)->removeLinkedLight(this);
-	}
+	mem_release(m_pLight);
 }
 
 void CBaseLight::toggleEnable()
@@ -58,28 +53,14 @@ void CBaseLight::toggleEnable()
 	setEnable(!m_isEnable);
 }
 
-void CBaseLight::onSync()
-{
-	BaseClass::onSync();
-
-	if(m_pLight)
-	{
-		m_pLight->setEnabled(m_isEnable);
-	}
-}
-
-
 void CBaseLight::turnOn(inputdata_t * pInputdata)
 {
 	if(!m_isEnable)
 	{
 		m_isEnable = true;
+		SAFE_CALL(m_pLight, setEnabled, m_isEnable);
 		FIRE_OUTPUT(m_onTurnOn, pInputdata->pInflictor);
 	}
-	for(int i = 0, l = m_vpLinkedLights.size(); i < l; ++i)
-	{
-		m_vpLinkedLights[i]->turnOn(pInputdata);
-	}
 }
 
 void CBaseLight::turnOff(inputdata_t * pInputdata)
@@ -87,12 +68,9 @@ void CBaseLight::turnOff(inputdata_t * pInputdata)
 	if(m_isEnable)
 	{
 		m_isEnable = false;
+		SAFE_CALL(m_pLight, setEnabled, m_isEnable);
 		FIRE_OUTPUT(m_onTurnOff, pInputdata->pInflictor);
 	}
-	for(int i = 0, l = m_vpLinkedLights.size(); i < l; ++i)
-	{
-		m_vpLinkedLights[i]->turnOff(pInputdata);
-	}
 }
 
 void CBaseLight::setEnable(bool isEnable)
@@ -100,18 +78,15 @@ void CBaseLight::setEnable(bool isEnable)
 	if(!m_isEnable && isEnable)
 	{
 		m_isEnable = isEnable;
+		SAFE_CALL(m_pLight, setEnabled, m_isEnable);
 		FIRE_OUTPUT(m_onTurnOn, this);
 	}
 	else if(m_isEnable && !isEnable)
 	{
 		m_isEnable = isEnable;
+		SAFE_CALL(m_pLight, setEnabled, m_isEnable);
 		FIRE_OUTPUT(m_onTurnOff, this);
 	}
-
-	for(int i = 0, l = m_vpLinkedLights.size(); i < l; ++i)
-	{
-		m_vpLinkedLights[i]->setEnable(isEnable);
-	}
 }
 
 void CBaseLight::updateFlags()
@@ -119,19 +94,7 @@ void CBaseLight::updateFlags()
 	BaseClass::updateFlags();
 
 	m_isEnable = !(getFlags() & LIGHT_INITIALLY_DARK);
-
-	for(int i = 0, l = m_vpLinkedLights.size(); i < l; ++i)
-	{
-		if(m_isEnable)
-		{
-			m_vpLinkedLights[i]->setFlags(m_vpLinkedLights[i]->getFlags() & ~LIGHT_INITIALLY_DARK);
-		}
-		else
-		{
-			m_vpLinkedLights[i]->setFlags(m_vpLinkedLights[i]->getFlags() | LIGHT_INITIALLY_DARK);
-		}
-		m_vpLinkedLights[i]->updateFlags();
-	}
+	SAFE_CALL(m_pLight, setEnabled, m_isEnable);
 }
 
 bool CBaseLight::getMainColor(float3_t *pOut)
@@ -143,60 +106,6 @@ bool CBaseLight::getMainColor(float3_t *pOut)
 	return(m_isEnable);
 }
 
-void CBaseLight::setLinkedTo(CBaseEntity *pEnt)
-{
-	if(m_pLinkedTo)
-	{
-		((CBaseLight*)m_pLinkedTo)->removeLinkedLight(this);
-	}
-	m_pLinkedTo = pEnt;
-	if(m_pLinkedTo)
-	{
-		((CBaseLight*)m_pLinkedTo)->addLinkedLight(this);
-		if((((CBaseLight*)m_pLinkedTo)->getFlags() & LIGHT_INITIALLY_DARK))
-		{
-			setFlags(getFlags() | LIGHT_INITIALLY_DARK);
-		}
-		else
-		{
-			setFlags(getFlags() & ~LIGHT_INITIALLY_DARK);
-		}
-		updateFlags();
-	}
-}
-
-void CBaseLight::addLinkedLight(CBaseLight *pEnt)
-{
-	if(!pEnt)
-	{
-		return;
-	}
-	for(int i = 0, l = m_vpLinkedLights.size(); i < l; ++i)
-	{
-		if(m_vpLinkedLights[i] == pEnt)
-		{
-			return;
-		}
-	}
-	m_vpLinkedLights.push_back(pEnt);
-}
-
-void CBaseLight::removeLinkedLight(CBaseLight *pEnt)
-{
-	if(!pEnt)
-	{
-		return;
-	}
-	for(int i = 0, l = m_vpLinkedLights.size(); i < l; ++i)
-	{
-		if(m_vpLinkedLights[i] == pEnt)
-		{
-			m_vpLinkedLights.erase(i);
-			return;
-		}
-	}
-}
-
 void CBaseLight::setPos(const float3 &pos)
 {
 	BaseClass::setPos(pos);
diff --git a/source/game/BaseLight.h b/source/game/BaseLight.h
index c029fd961..c29f632ec 100644
--- a/source/game/BaseLight.h
+++ b/source/game/BaseLight.h
@@ -98,17 +98,7 @@ protected:
 	int m_iShadowType = 1;
 	bool m_isEnable = true;
 	float m_fShadowIntensity = 1.0f;
-	CBaseEntity *m_pLinkedTo = NULL;
-
-	Array<CBaseLight*> m_vpLinkedLights;
-
-	void setLinkedTo(CBaseEntity *pEnt);
-
-	void onSync() override;
-
-	void addLinkedLight(CBaseLight *pEnt);
-	void removeLinkedLight(CBaseLight *pEnt);
-
+	
 	void turnOn(inputdata_t * pInputdata);
 	void turnOff(inputdata_t * pInputdata);
 
diff --git a/source/game/LightDirectional.cpp b/source/game/LightDirectional.cpp
index 13377a041..d0ae981e3 100644
--- a/source/game/LightDirectional.cpp
+++ b/source/game/LightDirectional.cpp
@@ -36,11 +36,6 @@ CLightDirectional::CLightDirectional()
 	}
 }
 
-CLightDirectional::~CLightDirectional()
-{
-	mem_release(m_pLight);
-}
-
 void CLightDirectional::setOrient(const SMQuaternion &q)
 {
 	BaseClass::setOrient(q);
diff --git a/source/game/LightDirectional.h b/source/game/LightDirectional.h
index df643f726..c9e981194 100644
--- a/source/game/LightDirectional.h
+++ b/source/game/LightDirectional.h
@@ -23,7 +23,6 @@ class CLightDirectional: public CBaseLight
 	DECLARE_PROPTABLE();
 public:
 	DECLARE_CONSTRUCTOR();
-	~CLightDirectional();
 
 	void setOuterAngle(float fAngle);
 	float getOuterAngle() const;
diff --git a/source/game/LightPoint.cpp b/source/game/LightPoint.cpp
index 65e323b1b..dd08c1ea8 100644
--- a/source/game/LightPoint.cpp
+++ b/source/game/LightPoint.cpp
@@ -21,13 +21,7 @@ CLightPoint::CLightPoint()
 	if(m_pLightSystem)
 	{
 		m_pLight = m_pLightSystem->newPoint();
-		//m_pLight->setDistance(m_fDist);
 		m_pLight->setColor(float4(float3(m_vColor) * m_vColor.w, m_fDist));
 	}
 }
 
-CLightPoint::~CLightPoint()
-{
-	mem_release(m_pLight);
-}
-
diff --git a/source/game/LightPoint.h b/source/game/LightPoint.h
index 5eeb62f98..ecf3c0e0d 100644
--- a/source/game/LightPoint.h
+++ b/source/game/LightPoint.h
@@ -23,7 +23,6 @@ class CLightPoint: public CBaseLight
 	DECLARE_PROPTABLE();
 public:
 	DECLARE_CONSTRUCTOR();
-	~CLightPoint();
 };
 
 #endif
diff --git a/source/game/LightSun.cpp b/source/game/LightSun.cpp
index 2da0e7036..e4e181780 100644
--- a/source/game/LightSun.cpp
+++ b/source/game/LightSun.cpp
@@ -25,11 +25,6 @@ CLightSun::CLightSun()
 	}
 }
 
-CLightSun::~CLightSun()
-{
-	mem_release(m_pLight);
-}
-
 void CLightSun::setOrient(const SMQuaternion &q)
 {
 	BaseClass::setOrient(q);
diff --git a/source/game/LightSun.h b/source/game/LightSun.h
index d23c80004..291b36f8d 100644
--- a/source/game/LightSun.h
+++ b/source/game/LightSun.h
@@ -23,7 +23,6 @@ class CLightSun: public CBaseLight
 	DECLARE_PROPTABLE();
 public:
 	DECLARE_CONSTRUCTOR();
-	~CLightSun();
 
 	void setOrient(const SMQuaternion &q) override;
 
diff --git a/source/game/PropDebris.cpp b/source/game/PropDebris.cpp
index 79522eb08..f6137b7c8 100644
--- a/source/game/PropDebris.cpp
+++ b/source/game/PropDebris.cpp
@@ -30,7 +30,8 @@ void CPropDebris::sheduleRemove()
 
 void CPropDebris::checkRemove(float fDT)
 {
-	//@TODO: Reimplement me
+	REMOVE_ENTITY(this);
+	// TODO Reimplement me
 #if 0
 	if(!m_pAnimPlayer->isVisibleFor(SX_ANIM_DEFAULT_VISCALCOBJ))
 	{
diff --git a/source/game/SoundEmitter.cpp b/source/game/SoundEmitter.cpp
index 8998dab38..23a641f76 100644
--- a/source/game/SoundEmitter.cpp
+++ b/source/game/SoundEmitter.cpp
@@ -15,10 +15,10 @@ BEGIN_PROPTABLE(CSoundEmitter)
 	DEFINE_FIELD_STRINGFN(m_szPathSound, 0, "file", "Sound file", setSound, EDITOR_SOUND)
 
 	//! Громкость
-	DEFINE_FIELD_FLOAT(m_fVolume, 0, "volume", "Volume", EDITOR_TEXTFIELD)
+	DEFINE_FIELD_FLOATFN(m_fVolume, 0, "volume", "Volume", setVolume, EDITOR_TEXTFIELD)
 
 	//! Дистанция слышимости
-	DEFINE_FIELD_FLOAT(m_fDist, 0, "distance", "Hearing distance", EDITOR_TEXTFIELD)
+	DEFINE_FIELD_FLOATFN(m_fDist, 0, "distance", "Hearing distance", setDistance, EDITOR_TEXTFIELD)
 	
 	//! Включить
 	DEFINE_INPUT(play, "play", "Play", PDF_NONE)
@@ -48,8 +48,10 @@ CSoundEmitter::~CSoundEmitter()
 
 void CSoundEmitter::setSound(const char *szSound)
 {
-	if(!m_pEmitter || fstrcmp(m_pEmitter->getName(), szSound) != 0)
+	if(!m_pEmitter || fstrcmp(m_szPathSound, szSound) != 0)
 	{
+		_setStrVal(&m_szPathSound, szSound);
+
 		mem_release(m_pEmitter);
 		IXSoundSystem *pSound = (IXSoundSystem*)(Core_GetIXCore()->getPluginManager()->getInterface(IXSOUNDSYSTEM_GUID));
 		IXSoundLayer *pGameLayer = pSound->findLayer("xGame");
@@ -59,34 +61,50 @@ void CSoundEmitter::setSound(const char *szSound)
 
 		if(m_pEmitter)
 		{
-			_setStrVal(&m_szPathSound, szSound);
 			m_pEmitter->setVolume(m_fVolume);
+			m_pEmitter->setWorldPos(getPos());
+			m_pEmitter->setDistance(m_fDist);
 		}
 	}
 }
 
 //##########################################################################
 
-void CSoundEmitter::onSync()
+void CSoundEmitter::setPos(const float3 &pos)
 {
-	BaseClass::onSync();
-	if(!m_pEmitter)
-		return;
+	BaseClass::setPos(pos);
 
-	float3 vPos = getPos();
-	m_pEmitter->setWorldPos(vPos);
+	SAFE_CALL(m_pEmitter, setWorldPos, pos);
+}
 
-	m_pEmitter->setVolume(m_fVolume);
+void CSoundEmitter::setVolume(float fVolume)
+{
+	m_fVolume = fVolume;
+
+	SAFE_CALL(m_pEmitter, setVolume, fVolume);
+}
+float CSoundEmitter::getVolume()
+{
+	return(m_fVolume);
+}
+
+void CSoundEmitter::setDistance(float fDistance)
+{
+	m_fDist = fDistance;
+
+	SAFE_CALL(m_pEmitter, setDistance, fDistance);
+}
+float CSoundEmitter::getDistance()
+{
+	return(m_fDist);
 }
 
 //##########################################################################
 
 void CSoundEmitter::play(inputdata_t * pInputdata)
 {
-	if(m_pEmitter)
-	{
-		m_pEmitter->play();
-	}
+	SAFE_CALL(m_pEmitter, play);
+
 	FIRE_OUTPUT(m_onTurnOn, pInputdata->pInflictor);
 }
 
@@ -99,7 +117,7 @@ void CSoundEmitter::updateFlags()
 	if(!m_pEmitter)
 		return;
 
-	if (getFlags() & SND_EMITTER_TYPE_AMBIENT)
+	if(getFlags() & SND_EMITTER_TYPE_AMBIENT)
 	{
 		m_pEmitter->setSpace(SOUND_SPACE_2D);
 	}
diff --git a/source/game/SoundEmitter.h b/source/game/SoundEmitter.h
index a4c73963b..10271cd8d 100644
--- a/source/game/SoundEmitter.h
+++ b/source/game/SoundEmitter.h
@@ -32,15 +32,17 @@ public:
 	DECLARE_TRIVIAL_CONSTRUCTOR();
 	~CSoundEmitter();
 
-	virtual void setSound(const char *szSound);
+	void setSound(const char *szSound);
 
 	void setPos(const float3 &pos) override;
 
 	void setVolume(float fVolume);
 	float getVolume();
 
-protected:
+	void setDistance(float fDistance);
+	float getDistance();
 
+protected:
 	void updateFlags() override;
 
 	void play(inputdata_t *pInputdata);
diff --git a/source/game/SoundPlayer.cpp b/source/game/SoundPlayer.cpp
index a60b0f898..7b835981d 100644
--- a/source/game/SoundPlayer.cpp
+++ b/source/game/SoundPlayer.cpp
@@ -15,13 +15,13 @@ BEGIN_PROPTABLE(CSoundPlayer)
 	DEFINE_FIELD_STRINGFN(m_szPathSound, 0, "file", "Sound file", setSound, EDITOR_SOUND)
 
 	//! Громкость
-	DEFINE_FIELD_FLOAT(m_fVolume, 0, "volume", "Volume", EDITOR_TEXTFIELD)
+	DEFINE_FIELD_FLOATFN(m_fVolume, 0, "volume", "Volume", setVolume, EDITOR_TEXTFIELD)
 
 	//! Дистанция слышимости
-	DEFINE_FIELD_FLOAT(m_fDist, 0, "distance", "Hearing distance", EDITOR_TEXTFIELD)
+	DEFINE_FIELD_FLOATFN(m_fDist, 0, "distance", "Hearing distance", setDistance, EDITOR_TEXTFIELD)
 
 	//! Зацикливание
-	DEFINE_FIELD_INT(m_iLoop, 0, "loop", "Loop", EDITOR_COMBOBOX)
+	DEFINE_FIELD_INTFN(m_iLoop, 0, "loop", "Loop", setLoop, EDITOR_COMBOBOX)
 		COMBO_OPTION("None", "0")		//!< Нет
 		COMBO_OPTION("Simple", "1")		//!< Простое (могут быть пустоты на стыках конца с началом)
 		COMBO_OPTION("Seamless", "2")	//!< Непрерывное (пустот не будет, все будет заполнено звуком)
@@ -60,8 +60,10 @@ CSoundPlayer::~CSoundPlayer()
 
 void CSoundPlayer::setSound(const char *szSound)
 {
-	if(!m_pPlayer || fstrcmp(m_pPlayer->getName(), szSound) != 0)
+	if(!m_pPlayer || fstrcmp(m_szPathSound, szSound) != 0)
 	{
+		_setStrVal(&m_szPathSound, szSound);
+
 		mem_release(m_pPlayer);
 		IXSoundSystem *pSound = (IXSoundSystem*)(Core_GetIXCore()->getPluginManager()->getInterface(IXSOUNDSYSTEM_GUID));
 		IXSoundLayer *pGameLayer = pSound->findLayer("xGame");
@@ -71,9 +73,10 @@ void CSoundPlayer::setSound(const char *szSound)
 
 		if(m_pPlayer)
 		{
-			_setStrVal(&m_szPathSound, szSound);
 			m_pPlayer->setLoop((SOUND_LOOP)m_iLoop);
 			m_pPlayer->setVolume(m_fVolume);
+			m_pPlayer->setDistance(m_fDist);
+			m_pPlayer->setWorldPos(getPos());
 
 			if(getFlags() & SND_PLAYER_START_PLAYED)
 				m_pPlayer->play();
@@ -83,20 +86,43 @@ void CSoundPlayer::setSound(const char *szSound)
 
 //##########################################################################
 
-void CSoundPlayer::onSync()
+void CSoundPlayer::setPos(const float3 &pos)
 {
-	BaseClass::onSync();
-	if (!m_pPlayer)
-		return;
+	BaseClass::setPos(pos);
+
+	SAFE_CALL(m_pPlayer, setWorldPos, pos);
+}
+
+void CSoundPlayer::setVolume(float fVolume)
+{
+	m_fVolume = fVolume;
+
+	SAFE_CALL(m_pPlayer, setVolume, fVolume);
+}
+float CSoundPlayer::getVolume()
+{
+	return(m_fVolume);
+}
 
-	float3 vPos = getPos();
-	m_pPlayer->setWorldPos(vPos);
+void CSoundPlayer::setDistance(float fDistance)
+{
+	m_fDist = fDistance;
 
-	if (m_pPlayer->getLoop() != (SOUND_LOOP)m_iLoop)
-		m_pPlayer->setLoop((SOUND_LOOP)m_iLoop);
+	SAFE_CALL(m_pPlayer, setDistance, fDistance);
+}
+float CSoundPlayer::getDistance()
+{
+	return(m_fDist);
+}
 
-	if (m_pPlayer->getVolume() != m_fVolume)
-		m_pPlayer->setVolume(m_fVolume);
+void CSoundPlayer::setLoop(int iLoop)
+{
+	m_iLoop = iLoop;
+	SAFE_CALL(m_pPlayer, setLoop, (SOUND_LOOP)iLoop);
+}
+SOUND_LOOP CSoundPlayer::getLoop()
+{
+	return((SOUND_LOOP)m_iLoop);
 }
 
 //##########################################################################
diff --git a/source/game/SoundPlayer.h b/source/game/SoundPlayer.h
index fc0c1748f..e90daef72 100644
--- a/source/game/SoundPlayer.h
+++ b/source/game/SoundPlayer.h
@@ -34,9 +34,18 @@ public:
 	DECLARE_TRIVIAL_CONSTRUCTOR();
 	~CSoundPlayer();
 
-	virtual void setSound(const char *szSound);
+	void setSound(const char *szSound);
 
-	void onSync() override;
+	void setPos(const float3 &pos) override;
+
+	void setVolume(float fVolume);
+	float getVolume();
+
+	void setDistance(float fDistance);
+	float getDistance();
+
+	void setLoop(int iLoop);
+	SOUND_LOOP getLoop();
 
 protected:
 
diff --git a/source/xcommon/IXSoundSystem.h b/source/xcommon/IXSoundSystem.h
index f33663b53..87d1d85e1 100644
--- a/source/xcommon/IXSoundSystem.h
+++ b/source/xcommon/IXSoundSystem.h
@@ -37,7 +37,9 @@ enum SOUND_LOOP
 {
 	SOUND_LOOP_NONE = 0,
 	SOUND_LOOP_SIMPLE = 1,
-	SOUND_LOOP_SEAMLESS = 2
+	SOUND_LOOP_SEAMLESS = 2,
+
+	SOUND_LOOP_FORCE_DWORD = 0x7fffffff  /* force 32-bit size enum */
 };
 
 //##########################################################################
-- 
GitLab