/* * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "precompiled.h" LINK_ENTITY_TO_CLASS(trigger_setorigin, CTriggerSetOrigin, CCSTriggerSetOrigin) void CTriggerSetOrigin::KeyValue(KeyValueData *pkvd) { if (FStrEq(pkvd->szKeyName, "triggerstate")) { int type = Q_atoi(pkvd->szValue); switch (type) { case 0: m_triggerType = USE_OFF; break; case 2: m_triggerType = USE_TOGGLE; break; default: m_triggerType = USE_ON; break; } pkvd->fHandled = TRUE; } else if (FStrEq(pkvd->szKeyName, "copypointer")) { m_copyPointer = ALLOC_STRING(pkvd->szValue); } else if (FStrEq(pkvd->szKeyName, "offset")) { UTIL_StringToVector(m_vecOffset, pkvd->szValue, ' '); pkvd->fHandled = TRUE; } else if (FStrEq(pkvd->szKeyName, "angleoffset")) { UTIL_StringToVector(m_vecAngleOffset, pkvd->szValue, ' '); pkvd->fHandled = TRUE; } else if (FStrEq(pkvd->szKeyName, "invert_x")) { m_bAngleInvertX = Q_atoi(pkvd->szValue) ? true : false; pkvd->fHandled = TRUE; } else if (FStrEq(pkvd->szKeyName, "invert_y")) { m_bAngleInvertY = Q_atoi(pkvd->szValue) ? true : false; pkvd->fHandled = TRUE; } else if (FStrEq(pkvd->szKeyName, "invert_z")) { m_bAngleInvertZ = Q_atoi(pkvd->szValue) ? true : false; pkvd->fHandled = TRUE; } else if (FStrEq(pkvd->szKeyName, "m_fRotate")) { pev->spawnflags |= SF_SETORIGIN_LOCK_OFFSETS; pkvd->fHandled = TRUE; } else { CBaseDelay::KeyValue(pkvd); } } void CTriggerSetOrigin::Use(CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value) { if (!(pev->spawnflags & SF_SETORIGIN_CONST_UPDATE)) { m_bSetupEntities = true; return; } switch (useType) { case USE_OFF: m_bUpdateEntities = false; break; case USE_ON: m_bUpdateEntities = true; break; case USE_TOGGLE: m_bUpdateEntities = !m_bUpdateEntities; break; } if (m_bUpdateEntities) { m_bSetupEntities = true; } } void CTriggerSetOrigin::UpdateTick() { if (m_bSetupEntities) { SetupEntities(); } if (m_bUpdateEntities) { UpdateKnownEntities(); } } void CTriggerSetOrigin::SetupEntities() { EntityHandle hPrevEnt(m_hCopyPointer); m_bSetupEntities = false; m_entityNum = 0; m_hCopyPointer = UTIL_FindEntityByTargetname(m_hCopyPointer, STRING(m_copyPointer)); if (!m_hCopyPointer.IsValid() && hPrevEnt.IsValid()) { m_hCopyPointer = hPrevEnt; } CBaseEntity *pEntity = nullptr; while ((pEntity = UTIL_FindEntityByTargetname(pEntity, STRING(pev->target)))) { if (m_entityNum > MAX_SETORIGIN_ENTITIES) break; if (FNullEnt(pEntity)) continue; if (m_hCopyPointer.IsValid() && !FNullEnt(m_hCopyPointer.Get())) { bool bForceCopy = false; if (!(pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_X) && !(pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_Y) && !(pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_Z) && !(pev->spawnflags & SF_SETORIGIN_COPY_AXIS_X) && !(pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Y) && !(pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Z)) { bForceCopy = true; } if (!(pev->spawnflags & SF_SETORIGIN_SKIP_INITIAL)) { Vector vecCopy(pEntity->pev->origin); // copy axis X if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_X) || bForceCopy) vecCopy.x = m_hCopyPointer->pev->origin.x; // copy axis Y if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Y) || bForceCopy) vecCopy.y = m_hCopyPointer->pev->origin.y; // copy axis Z if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Z) || bForceCopy) vecCopy.z = m_hCopyPointer->pev->origin.z; // copy angles X if (pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_X) pEntity->pev->angles.x = m_hCopyPointer->pev->angles.x; if (m_bAngleInvertX) pEntity->pev->angles.x = UTIL_AngleMod(-pEntity->pev->angles.x); // copy angles Y if (pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_Y) pEntity->pev->angles.y = m_hCopyPointer->pev->angles.y; if (m_bAngleInvertY) pEntity->pev->angles.y = UTIL_AngleMod(-pEntity->pev->angles.y); // copy angles Z if (pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_Z) pEntity->pev->angles.z = m_hCopyPointer->pev->angles.z; if (m_bAngleInvertZ) pEntity->pev->angles.z = UTIL_AngleMod(-pEntity->pev->angles.z); pEntity->pev->origin = vecCopy + m_vecOffset; pEntity->pev->angles = pEntity->pev->angles + m_vecAngleOffset; UTIL_SetOrigin(pEntity->pev, pEntity->pev->origin); } m_hEntities [m_entityNum] = pEntity; m_vecEntities[m_entityNum] = pEntity->pev->origin - m_hCopyPointer->pev->origin; Vector vecForward, vecRight, vecUp; UTIL_MakeVectorsPrivate(m_hCopyPointer->pev->angles, vecForward, vecRight, vecUp); m_vecEntities[m_entityNum++] *= vecForward + vecRight + vecUp; } else { pEntity->pev->origin = pEntity->pev->origin + m_vecOffset; pEntity->pev->angles = pEntity->pev->angles + m_vecAngleOffset; UTIL_SetOrigin(pev, pEntity->pev->origin); } } if (pev->spawnflags & SF_SETORIGIN_REMOVEFIRE) { UTIL_Remove(this); } } void CTriggerSetOrigin::UpdateKnownEntities() { bool bUpdated = false; for (int i = 0; i < MAX_SETORIGIN_ENTITIES; i++) { auto &pEntity = m_hEntities[i]; if (!pEntity.IsValid()) { pEntity = nullptr; continue; } if (!m_hCopyPointer.IsValid()) { m_bUpdateEntities = false; break; } bool bForceCopy = false; if (!(pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_X) && !(pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_Y) && !(pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_Z) && !(pev->spawnflags & SF_SETORIGIN_COPY_AXIS_X) && !(pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Y) && !(pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Z)) { bForceCopy = true; } if (pev->spawnflags & SF_SETORIGIN_LOCK_OFFSETS) { Vector vecForward, vecRight, vecUp; Vector vecAxisX(g_vecZero), vecAxisY(g_vecZero), vecAxisZ(g_vecZero); UTIL_MakeVectorsPrivate(m_hCopyPointer->pev->angles, vecForward, vecRight, vecUp); if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_X) || bForceCopy) vecAxisX = m_vecEntities[i].x * vecForward; if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Y) || bForceCopy) vecAxisY = m_vecEntities[i].y * vecRight; if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Z) || bForceCopy) vecAxisZ = m_vecEntities[i].z * vecUp; Vector vecCopy(m_hCopyPointer->pev->origin + vecAxisX + vecAxisY + vecAxisZ); if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_X) || bForceCopy) pEntity->pev->origin.x = vecCopy.x; if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Y) || bForceCopy) pEntity->pev->origin.y = vecCopy.y; if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Z) || bForceCopy) pEntity->pev->origin.z = vecCopy.z; } else { Vector vecCopy(pEntity->pev->origin); if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_X) || bForceCopy) vecCopy.x = m_hCopyPointer->pev->origin.x; if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Y) || bForceCopy) vecCopy.y = m_hCopyPointer->pev->origin.y; if ((pev->spawnflags & SF_SETORIGIN_COPY_AXIS_Z) || bForceCopy) vecCopy.z = m_hCopyPointer->pev->origin.z; pEntity->pev->origin = vecCopy + m_vecOffset; } // copy angles Y if (pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_X) pEntity->pev->angles.x = UTIL_AngleMod(m_hCopyPointer->pev->angles.x); if (m_bAngleInvertX) pEntity->pev->angles.x = UTIL_AngleMod(-pEntity->pev->angles.x); // copy angles X if (pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_Y) pEntity->pev->angles.y = UTIL_AngleMod(m_hCopyPointer->pev->angles.y); if (m_bAngleInvertY) pEntity->pev->angles.y = UTIL_AngleMod(-pEntity->pev->angles.y); // copy angles Z if (pev->spawnflags & SF_SETORIGIN_COPY_ANGLE_Z) pEntity->pev->angles.z = UTIL_AngleMod(m_hCopyPointer->pev->angles.z); if (m_bAngleInvertZ) pEntity->pev->angles.z = UTIL_AngleMod(-pEntity->pev->angles.z); pEntity->pev->angles += m_vecAngleOffset; pEntity->pev->groundentity = nullptr; pEntity->pev->flags &= ~FL_ONGROUND; bUpdated = true; UTIL_SetOrigin(pEntity->pev, pEntity->pev->origin); } if (!bUpdated) { m_bUpdateEntities = false; } } void CTriggerSetOrigin::OnCreate() { m_bUpdateEntities = false; m_bSetupEntities = false; CTriggerSetOriginManager::getInstance()->Add(this); } void CTriggerSetOrigin::OnDestroy() { CTriggerSetOriginManager::getInstance()->Remove(this); } void CTriggerSetOriginManager::Add(CTriggerSetOrigin *pInstance) { if (!pInstance) return; m_Entities.AddToTail(pInstance); } void CTriggerSetOriginManager::Remove(CTriggerSetOrigin *pInstance) { if (!pInstance) return; m_Entities.FindAndRemove(pInstance); } void CTriggerSetOriginManager::Update() { for (int i = 0; i < m_Entities.Count(); i++) { if (!m_Entities[i].IsValid()) { m_Entities.Remove(i); // Move iterator to back, because Remove method makes shift elements i--; continue; } // Update trigger m_Entities[i]->UpdateTick(); } }