See More

/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ #include "ScriptMoveType.h" #include "Map/Ground.h" #include "Map/MapInfo.h" #include "Sim/Misc/Wind.h" #include "Sim/Units/UnitDef.h" #include "Sim/Units/UnitTypes/Building.h" #include "System/EventHandler.h" #include "System/Matrix44f.h" #include "System/SpringMath.h" CR_BIND_DERIVED(CScriptMoveType, AMoveType, (nullptr)) CR_REG_METADATA(CScriptMoveType, ( CR_MEMBER(tag), CR_MEMBER(extrapolate), CR_MEMBER(useRelVel), CR_MEMBER(useRotVel), CR_MEMBER(drag), CR_MEMBER(velVec), CR_MEMBER(relVel), CR_MEMBER(rot), CR_MEMBER(rotVel), CR_MEMBER(mins), CR_MEMBER(maxs), CR_MEMBER(trackSlope), CR_MEMBER(trackGround), CR_MEMBER(groundOffset), CR_MEMBER(gravityFactor), CR_MEMBER(windFactor), CR_MEMBER(noBlocking), // copy of CSolidObject::PSTATE_BIT_BLOCKING CR_MEMBER(gndStop), CR_MEMBER(shotStop), CR_MEMBER(slopeStop), CR_MEMBER(collideStop), CR_MEMBER(scriptNotify) )) CScriptMoveType::CScriptMoveType(CUnit* owner): AMoveType(owner), tag(0), extrapolate(true), useRelVel(false), useRotVel(false), drag(0.0f), velVec(ZeroVector), relVel(ZeroVector), rot(ZeroVector), rotVel(ZeroVector), mins(-1.0e9f, -1.0e9f, -1.0e9f), maxs(+1.0e9f, +1.0e9f, +1.0e9f), trackSlope(false), trackGround(false), groundOffset(0.0f), gravityFactor(0.0f), windFactor(0.0f), noBlocking(false), gndStop(false), shotStop(false), slopeStop(false), collideStop(false), scriptNotify(0) { // use the transformation matrix instead of heading UseHeading(false); } CScriptMoveType::~CScriptMoveType() { // clean up if noBlocking was made true at // some point during this script's lifetime // and not reset owner->UnBlock(); } void CScriptMoveType::CheckNotify() { if (!scriptNotify) return; if (eventHandler.MoveCtrlNotify(owner, scriptNotify)) { // NOTE: deletes \ owner->DisableScriptMoveType(); } else { scriptNotify = 0; } } bool CScriptMoveType::Update() { if (useRotVel) owner->SetDirVectorsEuler(rot += rotVel); if (extrapolate) { // NOTE: only gravitational acc. is allowed to build up velocity // NOTE: strong wind plus low gravity can cause substantial drift const float3 gravVec = UpVector * (mapInfo->map.gravity * gravityFactor); const float3 windVec = (envResHandler.GetCurrentWindVec() * windFactor); const float3 unitVec = useRelVel? (owner->frontdir * relVel.z) + (owner->updir * relVel.y) + (owner->rightdir * -relVel.x): ZeroVector; owner->Move(gravVec + velVec, true); owner->Move(windVec, true); owner->Move(unitVec, true); // quadratic drag does not work well here velVec += gravVec; velVec *= (1.0f - drag); owner->SetVelocityAndSpeed(velVec); } if (trackGround) { const float gndMin = CGround::GetHeightReal(owner->pos.x, owner->pos.z) + groundOffset; if (owner->pos.y <= gndMin) { owner->Move(UpVector * (gndMin - owner->pos.y), true); owner->speed.y = 0.0f; if (gndStop) { velVec = ZeroVector; relVel = ZeroVector; rotVel = ZeroVector; scriptNotify = 1; } } } // positional clamps CheckLimits(); if (trackSlope) { owner->UpdateDirVectors(owner->IsOnGround(), owner->IsInAir()); owner->UpdateMidAndAimPos(); } // don't need the rest if the pos hasn't changed if (oldPos == owner->pos) { CheckNotify(); return false; } oldPos = owner->pos; if (!noBlocking) owner->Block(); CheckNotify(); return true; } void CScriptMoveType::CheckLimits() { if (owner->pos.x < mins.x) { owner->pos.x = mins.x; owner->speed.x = 0.0f; } if (owner->pos.x > maxs.x) { owner->pos.x = maxs.x; owner->speed.x = 0.0f; } if (owner->pos.y < mins.y) { owner->pos.y = mins.y; owner->speed.y = 0.0f; } if (owner->pos.y > maxs.y) { owner->pos.y = maxs.y; owner->speed.y = 0.0f; } if (owner->pos.z < mins.z) { owner->pos.z = mins.z; owner->speed.z = 0.0f; } if (owner->pos.z > maxs.z) { owner->pos.z = maxs.z; owner->speed.z = 0.0f; } owner->UpdateMidAndAimPos(); } void CScriptMoveType::SetPhysics(const float3& _pos, const float3& _vel, const float3& _rot) { SetPosition(_pos); SetVelocity(_vel); SetRotation(_rot); } void CScriptMoveType::SetPosition(const float3& _pos) { owner->Move(_pos, false); } void CScriptMoveType::SetVelocity(const float3& _vel) { owner->SetVelocityAndSpeed(velVec = _vel); } void CScriptMoveType::SetRelativeVelocity(const float3& _relVel) { relVel = _relVel; useRelVel = ((relVel.x != 0.0f) || (relVel.y != 0.0f) || (relVel.z != 0.0f)); } void CScriptMoveType::SetRotation(const float3& _rot) { owner->SetDirVectorsEuler(rot = _rot); } void CScriptMoveType::SetRotationVelocity(const float3& _rotVel) { rotVel = _rotVel; useRotVel = ((rotVel.x != 0.0f) || (rotVel.y != 0.0f) || (rotVel.z != 0.0f)); } void CScriptMoveType::SetHeading(short heading) { owner->SetHeading(heading, trackSlope, false); } void CScriptMoveType::SetNoBlocking(bool state) { // if false, forces blocking-map updates if ((noBlocking = state)) { owner->UnBlock(); } else { owner->Block(); } }